3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
11 (* symbol values *)
28 (* module state flags *)
31 (* procesor types *)
34 (* operation system types *)
37 (* compiler types *)
40 (* internal linker types *)
48 TYPE
55 next: Selector
69 VAR
81 (* --------- options --------- *)
85 BEGIN
90 RETURN i
95 BEGIN
109 ELSE
111 END
116 BEGIN
122 ELSE
124 END
129 BEGIN
137 RETURN t
142 BEGIN
154 END
155 ELSE
157 END
162 BEGIN
166 x := def
168 RETURN x
173 BEGIN
175 RETURN p
183 BEGIN
186 ELSE
195 END
200 BEGIN
203 ELSE
209 pars := p
214 BEGIN
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)
226 END
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
252 (*
255 *)
264 Log.String(' -U ident Remove preprocessor selector'); 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
281 s := DswOpts.str;
282 Strings.ToLower(s, s);
287 END
289 s := DswOpts.str;
290 Strings.ToLower(s, s);
299 END
301 s := DswOpts.str;
302 Strings.ToLower(s, s);
306 END
308 s := DswOpts.str;
309 Strings.ToLower(s, s);
312 END
316 END
317 END ParseTargetOpts;
319 PROCEDURE ParseCommandOpts;
320 BEGIN
327 END
328 END ParseCommandOpts;
330 PROCEDURE ParseExternalOpts;
331 BEGIN
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
360 | 0X: EXIT
361 END
362 END;
363 END ParseArgs;
365 PROCEDURE CheckParams;
366 BEGIN
367 IF compiler = anycp THEN
369 ELSIF compiler = cpnative THEN
370 IF processor = anymach THEN
372 ELSIF processor # mach386 THEN
374 END
375 END;
376 IF (compiler = cpfront) & (linker # anyint) THEN
378 END;
379 IF (compiler = cpfront) & (exe # NIL) THEN
381 END;
382 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
384 END;
385 IF (linker = dev2) & (os = anyos) THEN
387 END;
390 END;
391 IF cpcExe = NIL THEN
394 END
395 END;
396 IF cplExe = NIL THEN
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);
412 ELSE
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
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
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);
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
549 END;
550 Kernel.MakeFileName(path, type)
551 END MakePath;
553 BEGIN
555 Kernel.SplitName(modName, dir, name);
556 loc := Files.dir.This(dir).This(modDir);
557 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
560 IF text = NIL THEN
565 loc := Files.dir.This(sysDir).This(modDir);
567 IF text = NIL THEN
570 IF text = NIL THEN
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
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
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
649 FOR i := 0 TO mno - 1 DO
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);
687 IF p # NIL THEN
689 w.PutParam(p[0]);
690 FOR i := 1 TO LEN(p) - 1 DO
692 w.PutParam(p[i])
693 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);
704 ASSERT(m.worker = NIL, 22);
705 w := DswProcs.dir.New();
706 w.Program(cpcExe);
708 PutParams(w, cpcArgs);
709 CASE compiler OF
710 | cpfront:
713 | cpnative:
716 END;
717 CASE processor OF
718 | mach386:
721 | mach68k:
724 ELSE
727 END;
728 CASE os OF
729 | anyos:
736 | linux:
743 | freebsd:
751 | openbsd:
759 | win32:
767 | cygwin:
775 | darwin:
783 END;
784 CASE linker OF
785 | dev2:
787 ELSE
789 END;
790 w.PutParam(m.path);
791 w.Execute(ok);
792 IF ok THEN
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);
812 IF w # NIL THEN
814 m.worker := w;
815 INC(j)
816 ELSE
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
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
853 ASSERT(processor = mach386, 21);
854 ASSERT(compiler = cpnative, 22);
855 p := DswProcs.dir.New();
856 p.Program(cplExe);
857 IF os # anyos THEN
859 CASE os OF
865 END
866 END;
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
886 res := p.Result();
887 IF res # 0 THEN
889 INC(err)
890 END
891 ELSE
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.