DEADSOFTWARE

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