DEADSOFTWARE

989b8bcb2ce6727184062b5f0eb9489993a5acbf
[cpc.git] / src / generic / Dsw / Mod / MakeMain.cp
1 MODULE DswMakeMain;
3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
6 version = "0.3.0";
8 maxImps = 127;
9 maxJobs = maxImps;
11 (* symbol values *)
12 null = 0; times = 1; slash = 2; div = 3; mod = 4;
13 and = 5; plus = 6; minus = 7; or = 8; eql = 9;
14 neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14;
15 in = 15; is = 16; arrow = 17; dollar = 18; period = 19;
16 comma = 20; colon = 21; upto = 22; rparen = 23; rbrak = 24;
17 rbrace = 25; of = 26; then = 27; do = 28; to = 29;
18 by = 30; not = 33;
19 lparen = 40; lbrak = 41; lbrace = 42; becomes = 44;
20 number = 45; nil = 46; string = 47; ident = 48; semicolon = 49;
21 bar = 50; end = 51; else = 52; elsif = 53; until = 54;
22 if = 55; case = 56; while = 57; repeat = 58; for = 59;
23 loop = 60; with = 61; exit = 62; return = 63; array = 64;
24 record = 65; pointer = 66; begin = 67; const = 68; type = 69;
25 var = 70; out = 71; procedure = 72; close = 73; import = 74;
26 module = 75; eof = 76;
28 (* module state flags *)
29 imported = 0; trace = 1; hasObj = 2; hasSym = 3; hasErrors = 4; library = 5;
31 (* procesor types *)
32 anymach = 0; cmach = 1; mach386 = 10; mach68k = 20;
34 (* operation system types *)
35 anyos = 0; linux = 1; freebsd = 2; openbsd = 3; win32 = 4; cygwin = 5; darwin = 6;
37 (* compiler types *)
38 anycp = 0; cpnative = 1; cpfront = 2;
40 (* internal linker types *)
41 anyint = 0; dev2 = 1;
43 debugImport = FALSE;
44 debugOrder = FALSE;
45 debugJobs = FALSE;
46 debugArgs = FALSE;
48 TYPE
49 String = POINTER TO ARRAY OF CHAR;
50 StringList = POINTER TO ARRAY OF String;
52 Selector = POINTER TO RECORD
53 name: DevCPT.Name;
54 value: BOOLEAN;
55 next: Selector
56 END;
58 Module = POINTER TO RECORD
59 name: DevCPT.Name;
60 path: Files.Name;
61 selectors: Selector; (* with head, list of selectors for this module *)
62 depth: INTEGER; (* 0: leaf, MAX: root *)
63 mno: INTEGER;
64 imp: ARRAY maxImps OF Module;
65 flags: SET;
66 worker: DswProcs.Process;
67 END;
69 VAR
70 werr, err: INTEGER;
71 mno, rno: INTEGER; (* num modules *)
72 modList, lnkList, cmpList: ARRAY maxImps OF Module;
73 def: Selector; (* with head, global list of selectors *)
74 processor, compiler, os, linker: INTEGER;
75 cpcExe, cplExe: String;
76 cpcArgs, cplArgs: StringList;
77 auto: BOOLEAN;
78 jobs: INTEGER;
79 exe: String;
81 (* --------- options --------- *)
83 PROCEDURE IdentLen (IN s: ARRAY OF CHAR): INTEGER;
84 VAR i: INTEGER;
85 BEGIN
86 i := 0;
87 IF Strings.IsIdentStart(s[0]) THEN
88 REPEAT INC(i) UNTIL ~Strings.IsIdent(s[i])
89 END;
90 RETURN i
91 END IdentLen;
93 PROCEDURE Define (n: ARRAY OF CHAR);
94 VAR i: INTEGER; v: BOOLEAN; s: Selector;
95 BEGIN
96 i := IdentLen(n);
97 IF i # 0 THEN
98 IF ~((n[i] = 0X) OR (((n[i] = "+") OR (n[i] = "-")) & (n[i + 1] = 0X))) THEN
99 Log.String("option -D expect + or - after identifier"); Log.Ln; INC(err)
100 END;
101 v := n[i] # "-"; n[i] := 0X; s := def;
102 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
103 IF s.next = NIL THEN
104 NEW(s.next);
105 Strings.StringToUtf8(n, s.next.name, i);
106 ASSERT(i = 0)
107 END;
108 s.next.value := v
109 ELSE
110 Log.String("option -D expect identifier"); Log.Ln; INC(err)
111 END
112 END Define;
114 PROCEDURE Undefine (IN n: ARRAY OF CHAR);
115 VAR i: INTEGER; s: Selector;
116 BEGIN
117 i := IdentLen(n);
118 IF (i # 0) & (n[i] = 0X) THEN
119 s := def;
120 WHILE (s.next # NIL) & (s.next.name$ # n$) DO s := s.next END;
121 IF s.next # NIL THEN s.next := s.next.next END
122 ELSE
123 Log.String("option -U expect identifier"); Log.Ln; INC(err)
124 END
125 END Undefine;
127 PROCEDURE CopySelectorList (base: Selector): Selector;
128 VAR s, t, x: Selector;
129 BEGIN
130 ASSERT(base # NIL, 20);
131 s := base; NEW(t); x := t;
132 WHILE s # NIL DO
133 x^ := s^;
134 IF s.next # NIL THEN NEW(x.next); x := x.next END;
135 s := s.next
136 END;
137 RETURN t
138 END CopySelectorList;
140 PROCEDURE AddModule (IN n: ARRAY OF CHAR; selectors: Selector);
141 VAR i, res: INTEGER; m: Module;
142 BEGIN
143 i := IdentLen(n);
144 IF (i # 0) & (n[i] = 0X) THEN
145 i := 0;
146 WHILE (i < mno) & (modList[i].name$ # n$) DO INC(i) END;
147 IF i >= mno THEN
148 NEW(m);
149 Strings.StringToUtf8(n, m.name, res);
150 ASSERT(res = 0);
151 m.selectors := CopySelectorList(selectors);
152 modList[i] := m;
153 INC(mno)
154 END
155 ELSE
156 Log.String("module name must be identifier"); Log.Ln; INC(err)
157 END
158 END AddModule;
160 PROCEDURE StrToInt (IN s: ARRAY OF CHAR; def: INTEGER): INTEGER;
161 VAR x, res: INTEGER;
162 BEGIN
163 Strings.StringToInt(s, x, res);
164 IF res # 0 THEN
165 Log.String("expected integer"); Log.Ln; INC(err);
166 x := def
167 END;
168 RETURN x
169 END StrToInt;
171 PROCEDURE NewStr (IN s: ARRAY OF CHAR): String;
172 VAR p: String;
173 BEGIN
174 NEW(p, LEN(s$) + 1); p^ := s$;
175 RETURN p
176 END NewStr;
178 PROCEDURE ToStringList (IN s: ARRAY OF CHAR): StringList;
179 VAR i: INTEGER; ch, term: CHAR; pars: StringList;
181 PROCEDURE AddChar (c: CHAR);
182 VAR i, n, len: INTEGER; str: String;
183 BEGIN
184 IF pars = NIL THEN
185 NEW(pars, 1); NEW(pars[0], 2); pars[0, 0] := c
186 ELSE
187 n := LEN(pars) - 1;
188 len := LEN(pars[n]$);
189 NEW(str, len + 2);
190 FOR i := 0 TO len - 1 DO
191 str[i] := pars[n, i]
192 END;
193 str[i] := c;
194 pars[n] := str
195 END
196 END AddChar;
198 PROCEDURE AddLine;
199 VAR i, len: INTEGER; p: StringList;
200 BEGIN
201 IF pars = NIL THEN
202 NEW(pars, 1); i := 0;
203 ELSE
204 len := LEN(pars);
205 NEW(p, len + 1);
206 FOR i := 0 TO len - 1 DO
207 p[i] := pars[i]
208 END;
209 pars := p
210 END;
211 NEW(pars[i], 1)
212 END AddLine;
214 BEGIN
215 i := 0;
216 REPEAT ch := s[i]; INC(i) UNTIL ch # " ";
217 WHILE ch # 0X DO
218 CASE ch OF
219 | '"', "'":
220 term := ch; ch := s[i]; INC(i);
221 WHILE (ch # term) & (ch # 0X) DO
222 AddChar(ch); ch := s[i]; INC(i)
223 END;
224 IF ch # 0X THEN ch := s[i]; INC(i)
225 ELSE Log.String("unterminated string"); Log.Ln; INC(err)
226 END
227 | " ":
228 REPEAT ch := s[i]; INC(i) UNTIL ch # " ";
229 IF ch # 0X THEN AddLine END
230 ELSE
231 AddChar(ch); ch := s[i]; INC(i)
232 END
233 END;
234 RETURN pars
235 END ToStringList;
237 PROCEDURE Help;
238 BEGIN
239 Log.String("Usage: cpmake [options] module..."); Log.Ln;
240 Log.String("Options:"); Log.Ln;
241 Log.String(" -Tm cpu Generate code for specified processor"); Log.Ln;
242 Log.String(" none Unknown processor (cpfront only)"); Log.Ln;
243 Log.String(" 486 Intel 486"); Log.Ln;
244 Log.String(" -Ts os Generate code for specified operation system"); Log.Ln;
245 Log.String(" none Unknown operation system"); Log.Ln;
246 Log.String(" linux Linux"); Log.Ln;
247 Log.String(" -Tg compiler Specify Component Pascal compiler"); Log.Ln;
248 Log.String(" native BlackBox based native code compiler"); Log.Ln;
249 Log.String(" cpfront BlackBox based C code translator"); Log.Ln;
250 Log.String(" -Ti linker Specify internal linker (native only)"); Log.Ln;
251 Log.String(" dev2 Dev2 based ELF/PE linker"); Log.Ln;
252 (*
253 Log.String(" -Fp path Add path with project"); Log.Ln;
254 Log.String(" -Fx path Add postfix for project directories"); Log.Ln;
255 *)
256 Log.String(" -Xp path Use executable file for Component Pascal compiler"); Log.Ln;
257 Log.String(" -Xi path Use executable file for internal linker (native only)"); Log.Ln;
258 Log.String(" -Cg params Pass parameters to Component Pasacal compiler directly"); Log.Ln;
259 Log.String(" -Ci params Pass parameters to internal linker directly"); Log.Ln;
260 Log.String(" -a Enable automatic dependency resolution"); Log.Ln;
261 Log.String(" -o name Generate executable file"); Log.Ln;
262 Log.String(" -j num Specifies the number of jobs to run simultaneously"); Log.Ln;
263 Log.String(' -D ident["+"|"-"] Add preprocessor selector'); Log.Ln;
264 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
265 Log.String(" -h Print help and quit"); Log.Ln;
266 Log.String(" -V Print version and quit"); Log.Ln;
267 Kernel.Quit(1)
268 END Help;
270 PROCEDURE Version;
271 BEGIN
272 Log.String(version); Log.Ln;
273 Kernel.Quit(0)
274 END Version;
276 PROCEDURE ParseTargetOpts;
277 VAR s: DswOpts.String;
278 BEGIN
279 CASE DswOpts.GetOpt("m:s:g:i:") OF
280 | "m":
281 s := DswOpts.str;
282 Strings.ToLower(s, s);
283 IF s$ = "none" THEN processor := anymach
284 ELSIF s$ = "486" THEN processor := mach386
285 ELSIF s$ = "68k" THEN processor := mach68k
286 ELSE Log.String("unknwon processor "); Log.String(s); Log.Ln; INC(err)
287 END
288 | "s":
289 s := DswOpts.str;
290 Strings.ToLower(s, s);
291 IF s$ = "none" THEN os := anyos
292 ELSIF s$ = "linux" THEN os := linux
293 ELSIF s$ = "freebsd" THEN os := freebsd
294 ELSIF s$ = "openbsd" THEN os := openbsd
295 ELSIF s$ = "win32" THEN os := win32
296 ELSIF s$ = "cygwin" THEN os := cygwin
297 ELSIF s$ = "darwin" THEN os := darwin
298 ELSE Log.String("unknwon os "); Log.String(s); Log.Ln; INC(err)
299 END
300 | "g":
301 s := DswOpts.str;
302 Strings.ToLower(s, s);
303 IF s$ = "native" THEN compiler := cpnative
304 ELSIF s$ = "cpfront" THEN compiler := cpfront
305 ELSE Log.String("unknwon compiler "); Log.String(s); Log.Ln; INC(err)
306 END
307 | "i":
308 s := DswOpts.str;
309 Strings.ToLower(s, s);
310 IF s$ = "dev2" THEN linker := dev2
311 ELSE Log.String("unknwon linker "); Log.String(s); Log.Ln; INC(err)
312 END
313 | ":": Log.String("missing argument for option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
314 | "?": Log.String("unknown option -T"); Log.String(DswOpts.str); Log.Ln; INC(err)
315 | 0X: Log.String("unknown option -T"); Log.Ln; INC(err)
316 END
317 END ParseTargetOpts;
319 PROCEDURE ParseCommandOpts;
320 BEGIN
321 CASE DswOpts.GetOpt("g:i:") OF
322 | "g": cpcArgs := ToStringList(DswOpts.str);
323 | "i": cplArgs := ToStringList(DswOpts.str);
324 | ":": Log.String("missing argument for option -C"); Log.String(DswOpts.str); Log.Ln; INC(err)
325 | "?": Log.String("unknown option -C"); Log.String(DswOpts.str); Log.Ln; INC(err)
326 | 0X: Log.String("unknown option -C"); Log.Ln; INC(err)
327 END
328 END ParseCommandOpts;
330 PROCEDURE ParseExternalOpts;
331 BEGIN
332 CASE DswOpts.GetOpt("g:i:") OF
333 | "g": cpcExe := DswOpts.str;
334 | "i": cplExe := DswOpts.str;
335 | ":": Log.String("missing argument for option -X"); Log.String(DswOpts.str); Log.Ln; INC(err)
336 | "?": Log.String("unknown option -X"); Log.String(DswOpts.str); Log.Ln; INC(err)
337 | 0X: Log.String("unknown option -X"); Log.Ln; INC(err)
338 END
339 END ParseExternalOpts;
341 PROCEDURE ParseArgs;
342 BEGIN
343 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
344 processor := anymach; os := anyos; compiler := anycp;
345 LOOP
346 CASE DswOpts.GetOpt("ao:j:D:U:TCXhV") OF
347 | "a": auto := TRUE
348 | "o": exe := DswOpts.str
349 | "j": jobs := MIN(MAX(StrToInt(DswOpts.str, 1), 1), maxJobs)
350 | "h": Help
351 | "V": Version
352 | "D": Define(DswOpts.str)
353 | "U": Undefine(DswOpts.str)
354 | "T": ParseTargetOpts
355 | "C": ParseCommandOpts
356 | "X": ParseExternalOpts
357 | ":": Log.String("missing argument for option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
358 | "?": Log.String("unknown option -"); Log.String(DswOpts.str); Log.Ln; INC(err)
359 | "$": AddModule(DswOpts.str, def)
360 | 0X: EXIT
361 END
362 END;
363 END ParseArgs;
365 PROCEDURE CheckParams;
366 BEGIN
367 IF compiler = anycp THEN
368 Log.String("compiler not selected"); Log.Ln; INC(err)
369 ELSIF compiler = cpnative THEN
370 IF processor = anymach THEN
371 Log.String("processor not selected"); Log.Ln; INC(err)
372 ELSIF processor # mach386 THEN
373 Log.String("processor not supported by native compiler"); Log.Ln; INC(err)
374 END
375 END;
376 IF (compiler = cpfront) & (linker # anyint) THEN
377 Log.String("internal linker not required for cpfront"); Log.Ln; INC(err)
378 END;
379 IF (compiler = cpfront) & (exe # NIL) THEN
380 Log.String("cpfront can't out executable file"); Log.Ln; INC(err)
381 END;
382 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
383 Log.String("linker not selected"); Log.Ln; INC(err)
384 END;
385 IF (linker = dev2) & (os = anyos) THEN
386 Log.String("os not selected"); Log.Ln; INC(err)
387 END;
388 IF (exe # NIL) & (exe^ = "") THEN
389 Log.String("output file name can't be empty"); Log.Ln; INC(err)
390 END;
391 IF cpcExe = NIL THEN
392 IF compiler = cpnative THEN cpcExe := NewStr("cpc486")
393 ELSIF compiler = cpfront THEN cpcExe := NewStr("cpfront")
394 END
395 END;
396 IF cplExe = NIL THEN
397 IF linker = dev2 THEN cplExe := NewStr("cpl486") END
398 END
399 END CheckParams;
401 (* --------- loader --------- *)
403 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
404 VAR i, j: INTEGER; imp: Module;
405 BEGIN
406 ASSERT(m # NIL, 20);
407 ASSERT(name # "", 21);
408 IF debugImport THEN Log.String(" import "); Log.String(name$) END;
409 IF name = "SYSTEM" THEN INCL(DevCPM.options, DevCPM.sysImp)
410 ELSIF name = "COM" THEN INCL(DevCPM.options, DevCPM.com)
411 ELSIF name = "JAVA" THEN INCL(DevCPM.options, DevCPM.java)
412 ELSE
413 IF debugImport THEN Log.Char(" ") END;
414 i := 0; (* find module in local list *)
415 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
416 IF i >= m.mno THEN
417 j := 0; (* find module in global list *)
418 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
419 IF j >= mno THEN
420 IF ~auto THEN
421 Log.String("module " + name + " required before " + m.name); Log.Ln; INC(werr)
422 END;
423 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
424 modList[mno] := imp; INC(mno)
425 ELSE
426 imp := modList[j]
427 END;
428 m.imp[m.mno] := imp; INC(m.mno)
429 ELSE DevCPM.err(1)
430 END
431 END;
432 IF debugImport THEN Log.Ln END;
433 END Import;
435 PROCEDURE ParseModule (m: Module);
436 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
438 PROCEDURE err (n: SHORTINT);
439 BEGIN DevCPM.err(n)
440 END err;
442 PROCEDURE CheckSym(s: SHORTINT);
443 BEGIN
444 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
445 END CheckSym;
447 BEGIN
448 IF debugImport THEN Log.String("module " + m.name); Log.Ln END;
449 DevCPS.Init; DevCPS.Get(sym);
450 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
451 IF sym = ident THEN
452 SelfName := DevCPS.name$; DevCPS.Get(sym);
453 IF sym = lbrak THEN
454 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
455 IF sym = eql THEN DevCPS.Get(sym)
456 ELSE INCL(DevCPM.options, DevCPM.noCode)
457 END;
458 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
459 ELSE err(string)
460 END;
461 CheckSym(rbrak)
462 END;
463 CheckSym(semicolon);
464 IF sym = import THEN DevCPS.Get(sym);
465 LOOP
466 IF sym = ident THEN
467 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
468 IF sym = becomes THEN DevCPS.Get(sym);
469 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
470 END;
471 Import(m, impName)
472 ELSE err(ident)
473 END;
474 IF sym = comma THEN DevCPS.Get(sym)
475 ELSIF sym = ident THEN err(comma)
476 ELSE EXIT
477 END
478 END;
479 CheckSym(semicolon)
480 END;
481 LOOP (* preprocessor must read module fully *)
482 IF sym = end THEN
483 DevCPS.Get(sym);
484 IF sym = ident THEN
485 DevCPS.Get(sym);
486 IF sym = period THEN
487 IF DevCPS.name # SelfName THEN err(4) END;
488 EXIT
489 ELSIF sym = eof THEN
490 err(period);
491 EXIT
492 END
493 ELSIF sym = eof THEN
494 err(ident);
495 EXIT
496 END;
497 ELSIF sym = eof THEN
498 err(end);
499 EXIT
500 ELSE
501 DevCPS.Get(sym);
502 END
503 END
504 ELSE err(ident)
505 END;
506 DevCPS.str := NIL
507 END ParseModule;
509 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
510 VAR s: Selector;
511 BEGIN
512 DevCPM.Init(source);
513 (*
514 DevCPM.symList := m.insym;
515 DevCPM.codePath := m.outcode;
516 DevCPM.symPath := m.outsym;
517 *)
518 DevCPM.name := m.name$;
519 (*
520 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
521 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
522 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
523 *)
524 DevCPR.Init;
525 s := m.selectors.next;
526 WHILE s # NIL DO
527 DevCPR.Set(s.name, s.value);
528 s := s.next
529 END;
530 ParseModule(m);
531 DevCPR.Check;
532 ok := DevCPM.noerr;
533 DevCPR.Close;
534 DevCPM.InsertMarks;
535 DevCPM.Close;
536 Kernel.FastCollect
537 END CheckModule;
539 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
540 CONST modDir = "Mod"; sysDir = "System";
541 VAR dir, name: Files.Name; loc: Files.Locator;
542 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
544 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
545 BEGIN
546 ASSERT(name # "", 21);
547 IF dir = "" THEN path := modDir + "/" + name
548 ELSE path := dir + "/" + modDir + "/" + name
549 END;
550 Kernel.MakeFileName(path, type)
551 END MakePath;
553 BEGIN
554 s := NIL; path := "";
555 Kernel.SplitName(modName, dir, name);
556 loc := Files.dir.This(dir).This(modDir);
557 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
558 MakePath(dir, name, "cp", path);
559 DswDocuments.Open(loc, name + ".cp", text, res);
560 IF text = NIL THEN
561 MakePath(dir, name, "odc", path);
562 DswDocuments.Open(loc, name + ".odc", text, res);
563 IF (text = NIL) & (dir = "") THEN
564 MakePath(sysDir, name, "cp", path);
565 loc := Files.dir.This(sysDir).This(modDir);
566 DswDocuments.Open(loc, name + ".cp", text, res);
567 IF text = NIL THEN
568 MakePath(sysDir, name, "odc", path);
569 DswDocuments.Open(loc, name + ".odc", text, res);
570 IF text = NIL THEN
571 path := ""
572 END
573 END
574 END
575 END;
576 IF text # NIL THEN
577 NEW(s, text.Length() + 1);
578 IF s # NIL THEN
579 r := text.NewReader(NIL);
580 FOR i := 0 TO text.Length() - 1 DO
581 r.Read; s[i] := r.char
582 END
583 END
584 END
585 END GetSource;
587 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
588 VAR i: INTEGER;
589 BEGIN
590 IF ~(trace IN m.flags) THEN
591 INCL(m.flags, trace);
592 FOR i := 0 TO m.mno - 1 DO
593 Trace(m.imp[i], m, lno);
594 m.depth := MAX(m.depth, m.imp[i].depth + 1)
595 END;
596 IF ~(imported IN m.flags) THEN
597 INCL(m.flags, imported);
598 lnkList[lno] := m;
599 INC(lno)
600 END;
601 EXCL(m.flags, trace)
602 ELSE
603 Log.String("recursive import of " + m.name + " in " + parent.name); Log.Ln; INC(err)
604 END
605 END Trace;
607 PROCEDURE Sort;
608 VAR i, j: INTEGER; m: Module;
609 BEGIN
610 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
611 cmpList := lnkList;
612 i := 1;
613 WHILE i < mno DO
614 m := cmpList[i];
615 j := i - 1;
616 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
617 cmpList[j + 1] := cmpList[j];
618 DEC(j)
619 END;
620 cmpList[j + 1] := m;
621 INC(i)
622 END
623 END Sort;
625 PROCEDURE CheckDeps;
626 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
627 BEGIN
628 i := 0; rno := mno;
629 WHILE (err = 0) & (i < mno) DO
630 m := modList[i];
631 GetSource(m.name$, m.path, s);
632 IF s # NIL THEN
633 CheckModule(m, s, ok);
634 IF ~ok THEN INC(err) END
635 ELSE
636 Log.String("unable to open module " + m.name); Log.Ln; INC(err)
637 END;
638 INC(i)
639 END;
640 INC(err, werr);
641 num := 0;
642 FOR i := 0 TO rno - 1 DO
643 Trace(modList[i], modList[i], num)
644 END;
645 ASSERT((err # 0) OR (num = mno), 100);
646 Sort;
647 IF debugOrder THEN
648 Log.String("Parallel depth:"); Log.Ln;
649 FOR i := 0 TO mno - 1 DO
650 Log.String(" " + cmpList[i].name); Log.Int(cmpList[i].depth); Log.Ln;
651 END
652 END
653 END CheckDeps;
655 PROCEDURE IsCompiled (m: Module): BOOLEAN;
656 CONST target = {hasSym, hasObj};
657 VAR i: INTEGER; ready: BOOLEAN;
658 BEGIN
659 ASSERT(m # NIL, 20);
660 i := 0;
661 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
662 WHILE ready & (i < m.mno) DO
663 ready := IsCompiled(m.imp[i]);
664 INC(i)
665 END;
666 RETURN ready
667 END IsCompiled;
669 PROCEDURE Ready (m: Module): BOOLEAN;
670 CONST target = {hasSym, hasObj};
671 VAR i: INTEGER; ready: BOOLEAN;
672 BEGIN
673 i := 0;
674 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
675 WHILE ready & (i < m.mno) DO
676 ready := IsCompiled(m.imp[i]);
677 INC(i)
678 END;
679 RETURN ready
680 END Ready;
682 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
683 VAR i: INTEGER;
684 BEGIN
685 ASSERT(w # NIL, 20);
686 IF debugArgs THEN Log.String("PutParams") END;
687 IF p # NIL THEN
688 IF debugArgs THEN Log.String(":[" + p[0]) END;
689 w.PutParam(p[0]);
690 FOR i := 1 TO LEN(p) - 1 DO
691 IF debugArgs THEN Log.String("|" + p[i]) END;
692 w.PutParam(p[i])
693 END;
694 IF debugArgs THEN Log.Char("]") END
695 END;
696 IF debugArgs THEN Log.Ln END
697 END PutParams;
699 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
700 VAR w: DswProcs.Process; ok: BOOLEAN;
701 BEGIN
702 ASSERT(m # NIL, 20);
703 ASSERT(m.path # "", 21);
704 ASSERT(m.worker = NIL, 22);
705 w := DswProcs.dir.New();
706 w.Program(cpcExe);
707 w.PutParam("-legacy");
708 PutParams(w, cpcArgs);
709 CASE compiler OF
710 | cpfront:
711 w.PutParam("-define+"); w.PutParam("CPFRONT");
712 w.PutParam("-define-"); w.PutParam("NATIVE");
713 | cpnative:
714 w.PutParam("-define-"); w.PutParam("CPFRONT");
715 w.PutParam("-define+"); w.PutParam("NATIVE");
716 END;
717 CASE processor OF
718 | mach386:
719 w.PutParam("-define+"); w.PutParam("I486");
720 w.PutParam("-define-"); w.PutParam("M68K");
721 | mach68k:
722 w.PutParam("-define+"); w.PutParam("I486");
723 w.PutParam("-define-"); w.PutParam("M68K");
724 ELSE
725 w.PutParam("-define-"); w.PutParam("I486");
726 w.PutParam("-define-"); w.PutParam("M68K");
727 END;
728 CASE os OF
729 | anyos:
730 w.PutParam("-define-"); w.PutParam("POSIX");
731 w.PutParam("-define-"); w.PutParam("LINUX");
732 w.PutParam("-define-"); w.PutParam("FREEBSD");
733 w.PutParam("-define-"); w.PutParam("OPENBSD");
734 w.PutParam("-define-"); w.PutParam("WIN32");
735 w.PutParam("-define-"); w.PutParam("DARWIN");
736 | linux:
737 w.PutParam("-define+"); w.PutParam("POSIX");
738 w.PutParam("-define+"); w.PutParam("LINUX");
739 w.PutParam("-define-"); w.PutParam("FREEBSD");
740 w.PutParam("-define-"); w.PutParam("OPENBSD");
741 w.PutParam("-define-"); w.PutParam("WIN32");
742 w.PutParam("-define-"); w.PutParam("DARWIN");
743 | freebsd:
744 w.PutParam("-define+"); w.PutParam("POSIX");
745 w.PutParam("-define-"); w.PutParam("LINUX");
746 w.PutParam("-define+"); w.PutParam("FREEBSD");
747 w.PutParam("-define-"); w.PutParam("OPENBSD");
748 w.PutParam("-define-"); w.PutParam("WIN32");
749 w.PutParam("-define-"); w.PutParam("CYGWIN");
750 w.PutParam("-define-"); w.PutParam("DARWIN");
751 | openbsd:
752 w.PutParam("-define+"); w.PutParam("POSIX");
753 w.PutParam("-define-"); w.PutParam("LINUX");
754 w.PutParam("-define-"); w.PutParam("FREEBSD");
755 w.PutParam("-define+"); w.PutParam("OPENBSD");
756 w.PutParam("-define-"); w.PutParam("WIN32");
757 w.PutParam("-define-"); w.PutParam("CYGWIN");
758 w.PutParam("-define-"); w.PutParam("DARWIN");
759 | win32:
760 w.PutParam("-define-"); w.PutParam("POSIX");
761 w.PutParam("-define-"); w.PutParam("LINUX");
762 w.PutParam("-define-"); w.PutParam("FREEBSD");
763 w.PutParam("-define-"); w.PutParam("OPENBSD");
764 w.PutParam("-define+"); w.PutParam("WIN32");
765 w.PutParam("-define-"); w.PutParam("CYGWIN");
766 w.PutParam("-define-"); w.PutParam("DARWIN");
767 | cygwin:
768 w.PutParam("-define+"); w.PutParam("POSIX");
769 w.PutParam("-define-"); w.PutParam("LINUX");
770 w.PutParam("-define-"); w.PutParam("FREEBSD");
771 w.PutParam("-define-"); w.PutParam("OPENBSD");
772 w.PutParam("-define+"); w.PutParam("WIN32");
773 w.PutParam("-define+"); w.PutParam("CYGWIN");
774 w.PutParam("-define-"); w.PutParam("DARWIN");
775 | darwin:
776 w.PutParam("-define+"); w.PutParam("POSIX");
777 w.PutParam("-define-"); w.PutParam("LINUX");
778 w.PutParam("-define-"); w.PutParam("FREEBSD");
779 w.PutParam("-define-"); w.PutParam("OPENBSD");
780 w.PutParam("-define-"); w.PutParam("WIN32");
781 w.PutParam("-define-"); w.PutParam("CYGWIN");
782 w.PutParam("-define+"); w.PutParam("DARWIN");
783 END;
784 CASE linker OF
785 | dev2:
786 w.PutParam("-define+"); w.PutParam("DEV2");
787 ELSE
788 w.PutParam("-define-"); w.PutParam("DEV2");
789 END;
790 w.PutParam(m.path);
791 w.Execute(ok);
792 IF ok THEN
793 Log.String("Compile " + m.name + " (" + m.path + ")"); Log.Ln;
794 ELSE
795 w := NIL
796 END;
797 RETURN w
798 END ExecuteCompiler;
800 PROCEDURE Compile;
801 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
802 BEGIN
803 IF mno = 0 THEN RETURN END;
804 num := 0; j := 0;
805 WHILE (err = 0) & (num < mno) OR (j > 0) DO
806 i := 0;
807 WHILE (err = 0) & (i < mno) & (j < jobs) DO
808 m := cmpList[i];
809 IF Ready(m) THEN
810 w := ExecuteCompiler(m);
811 IF debugJobs THEN Log.String("Start job " + m.name) END;
812 IF w # NIL THEN
813 IF debugJobs THEN Log.String(" ok") END;
814 m.worker := w;
815 INC(j)
816 ELSE
817 IF debugJobs THEN Log.String(" fail") END;
818 INCL(m.flags, hasErrors);
819 INC(err)
820 END;
821 IF debugJobs THEN Log.Ln END
822 END;
823 INC(i)
824 END;
825 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
826 i := 0;
827 WHILE (j > 0) & (i < mno) DO
828 m := cmpList[i];
829 w := m.worker;
830 IF (w # NIL) & w.IsTerminated() THEN
831 IF debugJobs THEN Log.String("Stop job " + m.name); Log.Int(w.Result()); Log.Ln END;
832 IF w.Result() = 0 THEN
833 INCL(m.flags, hasObj);
834 INCL(m.flags, hasSym);
835 INC(num)
836 ELSE
837 INCL(m.flags, hasErrors);
838 INC(err)
839 END;
840 m.worker := NIL;
841 DEC(j)
842 END;
843 INC(i)
844 END
845 END
846 END
847 END Compile;
849 PROCEDURE LinkDev2;
850 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
851 BEGIN
852 ASSERT((exe # NIL) & (exe^ # ""), 20);
853 ASSERT(processor = mach386, 21);
854 ASSERT(compiler = cpnative, 22);
855 p := DswProcs.dir.New();
856 p.Program(cplExe);
857 IF os # anyos THEN
858 p.PutParam("-os");
859 CASE os OF
860 | linux: p.PutParam("linux")
861 | freebsd: p.PutParam("freebsd")
862 | openbsd: p.PutParam("openbsd")
863 | win32, cygwin: p.PutParam("win32")
864 | darwin: p.PutParam("darwin")
865 END
866 END;
867 p.PutParam("-kernel");
868 p.PutParam("Kernel");
869 p.PutParam("-main");
870 p.PutParam("Kernel");
871 p.PutParam("-legacycodedir");
872 p.PutParam(".");
873 p.PutParam("-o");
874 p.PutParam(exe);
875 PutParams(p, cplArgs);
876 i := 0;
877 WHILE i < mno DO
878 IF ~(library IN lnkList[i].flags) THEN
879 p.PutParam(lnkList[i].name$)
880 END;
881 INC(i)
882 END;
883 p.Execute(ok);
884 IF ok THEN
885 Log.String("Link "); Log.String(exe); Log.Ln;
886 res := p.Result();
887 IF res # 0 THEN
888 Log.String("linker terminated with error"); Log.Int(res); Log.Ln;
889 INC(err)
890 END
891 ELSE
892 Log.String("unable to execute linker"); Log.Int(i); Log.Ln;
893 INC(err)
894 END
895 END LinkDev2;
897 PROCEDURE Link;
898 BEGIN
899 IF exe # NIL THEN
900 CASE linker OF
901 | anyint: (* do not link *)
902 | dev2: LinkDev2
903 END
904 END
905 END Link;
907 PROCEDURE Main;
908 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
909 BEGIN
910 IF Kernel.trapCount = 0 THEN
911 ParseArgs;
912 IF err = 0 THEN
913 CheckParams;
914 IF err = 0 THEN
915 CheckDeps;
916 IF err = 0 THEN
917 Compile;
918 IF err = 0 THEN
919 Link
920 END
921 END
922 END
923 END
924 ELSE INC(err)
925 END;
926 IF err = 0 THEN Kernel.Quit(0)
927 ELSE Kernel.Quit(1)
928 END;
929 END Main;
931 BEGIN
932 NEW(def);
933 Kernel.Start(Main)
934 END DswMakeMain.