DEADSOFTWARE

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