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
83 BEGIN
110 ELSE
119 (* --------- options --------- *)
123 BEGIN
128 RETURN i
133 BEGIN
147 ELSE
149 END
154 BEGIN
160 ELSE
162 END
167 BEGIN
175 RETURN t
180 BEGIN
192 END
193 ELSE
195 END
200 BEGIN
204 x := def
206 RETURN x
211 BEGIN
213 RETURN p
221 BEGIN
224 ELSE
233 END
238 BEGIN
241 ELSE
247 pars := p
252 BEGIN
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)
264 END
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
290 (*
293 *)
303 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
306 Kernel.Quit(1)
307 END Help;
309 PROCEDURE Version;
310 BEGIN
311 Log.String(version); Log.Ln;
312 Kernel.Quit(0)
313 END Version;
315 PROCEDURE ParseTargetOpts;
316 VAR s: DswOpts.String;
317 BEGIN
320 s := DswOpts.str;
321 Strings.ToLower(s, s);
326 END
328 s := DswOpts.str;
329 Strings.ToLower(s, s);
338 END
340 s := DswOpts.str;
341 Strings.ToLower(s, s);
345 END
347 s := DswOpts.str;
348 Strings.ToLower(s, s);
351 END
355 END
356 END ParseTargetOpts;
358 PROCEDURE ParseCommandOpts;
359 BEGIN
366 END
367 END ParseCommandOpts;
369 PROCEDURE ParseExternalOpts;
370 BEGIN
377 END
378 END ParseExternalOpts;
380 PROCEDURE ParseInfoOpts;
381 BEGIN
387 END
388 END ParseInfoOpts;
390 PROCEDURE ParseArgs;
391 BEGIN
392 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
393 processor := anymach; os := anyos; compiler := anycp;
394 LOOP
410 | 0X: EXIT
411 END
412 END;
413 END ParseArgs;
415 PROCEDURE CheckParams;
416 BEGIN
417 IF compiler = anycp THEN
419 ELSIF compiler = cpnative THEN
420 IF processor = anymach THEN
422 ELSIF processor # mach386 THEN
424 END
425 END;
426 IF (compiler = cpfront) & (linker # anyint) THEN
428 END;
429 IF (compiler = cpfront) & (exe # NIL) THEN
431 END;
432 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
434 END;
435 IF (linker = dev2) & (os = anyos) THEN
437 END;
440 END;
441 IF cpcExe = NIL THEN
444 END
445 END;
446 IF cplExe = NIL THEN
448 END
449 END CheckParams;
451 (* --------- loader --------- *)
453 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
454 VAR i, j: INTEGER; imp: Module;
455 BEGIN
456 ASSERT(m # NIL, 20);
462 ELSE
464 i := 0; (* find module in local list *)
465 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
466 IF i >= m.mno THEN
467 j := 0; (* find module in global list *)
468 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
469 IF j >= mno THEN
470 IF ~auto THEN
472 END;
473 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
474 modList[mno] := imp; INC(mno)
475 ELSE
476 imp := modList[j]
477 END;
478 m.imp[m.mno] := imp; INC(m.mno)
479 ELSE DevCPM.err(1)
480 END
481 END;
482 IF debugImport THEN Log.Ln END;
483 END Import;
485 PROCEDURE ParseModule (m: Module);
486 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
488 PROCEDURE err (n: SHORTINT);
489 BEGIN DevCPM.err(n)
490 END err;
492 PROCEDURE CheckSym(s: SHORTINT);
493 BEGIN
494 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
495 END CheckSym;
497 BEGIN
499 DevCPS.Init; DevCPS.Get(sym);
500 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
501 IF sym = ident THEN
502 SelfName := DevCPS.name$; DevCPS.Get(sym);
503 IF sym = lbrak THEN
504 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
505 IF sym = eql THEN DevCPS.Get(sym)
506 ELSE INCL(DevCPM.options, DevCPM.noCode)
507 END;
508 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
509 ELSE err(string)
510 END;
511 CheckSym(rbrak)
512 END;
513 CheckSym(semicolon);
514 IF sym = import THEN DevCPS.Get(sym);
515 LOOP
516 IF sym = ident THEN
517 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
518 IF sym = becomes THEN DevCPS.Get(sym);
519 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
520 END;
521 Import(m, impName)
522 ELSE err(ident)
523 END;
524 IF sym = comma THEN DevCPS.Get(sym)
525 ELSIF sym = ident THEN err(comma)
526 ELSE EXIT
527 END
528 END;
529 CheckSym(semicolon)
530 END;
531 LOOP (* preprocessor must read module fully *)
532 IF sym = end THEN
533 DevCPS.Get(sym);
534 IF sym = ident THEN
535 DevCPS.Get(sym);
536 IF sym = period THEN
537 IF DevCPS.name # SelfName THEN err(4) END;
538 EXIT
539 ELSIF sym = eof THEN
540 err(period);
541 EXIT
542 END
543 ELSIF sym = eof THEN
544 err(ident);
545 EXIT
546 END;
547 ELSIF sym = eof THEN
548 err(end);
549 EXIT
550 ELSE
551 DevCPS.Get(sym);
552 END
553 END
554 ELSE err(ident)
555 END;
556 DevCPS.str := NIL
557 END ParseModule;
559 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
560 VAR s: Selector;
561 BEGIN
562 DevCPM.Init(source);
563 (*
564 DevCPM.symList := m.insym;
565 DevCPM.codePath := m.outcode;
566 DevCPM.symPath := m.outsym;
567 *)
568 DevCPM.name := m.name$;
569 (*
570 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
571 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
572 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
573 *)
574 DevCPR.Init;
575 s := m.selectors.next;
576 WHILE s # NIL DO
577 DevCPR.Set(s.name, s.value);
578 s := s.next
579 END;
580 ParseModule(m);
581 DevCPR.Check;
582 ok := DevCPM.noerr;
583 DevCPR.Close;
584 DevCPM.InsertMarks;
585 DevCPM.Close;
586 Kernel.FastCollect
587 END CheckModule;
589 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
591 VAR dir, name: Files.Name; loc: Files.Locator;
592 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
594 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
595 BEGIN
599 END;
600 Kernel.MakeFileName(path, type)
601 END MakePath;
603 BEGIN
605 Kernel.SplitName(modName, dir, name);
606 loc := Files.dir.This(dir).This(modDir);
607 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
610 IF text = NIL THEN
615 loc := Files.dir.This(sysDir).This(modDir);
617 IF text = NIL THEN
620 IF text = NIL THEN
622 END
623 END
624 END
625 END;
626 IF text # NIL THEN
627 NEW(s, text.Length() + 1);
628 IF s # NIL THEN
629 r := text.NewReader(NIL);
630 FOR i := 0 TO text.Length() - 1 DO
631 r.Read; s[i] := r.char
632 END
633 END
634 END
635 END GetSource;
637 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
638 VAR i: INTEGER;
639 BEGIN
640 IF ~(trace IN m.flags) THEN
641 INCL(m.flags, trace);
642 FOR i := 0 TO m.mno - 1 DO
643 Trace(m.imp[i], m, lno);
644 m.depth := MAX(m.depth, m.imp[i].depth + 1)
645 END;
646 IF ~(imported IN m.flags) THEN
647 INCL(m.flags, imported);
648 lnkList[lno] := m;
649 INC(lno)
650 END;
651 EXCL(m.flags, trace)
652 ELSE
653 Error(20, m.name$, parent.name$, 0)
654 END
655 END Trace;
657 PROCEDURE Sort;
658 VAR i, j: INTEGER; m: Module;
659 BEGIN
660 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
661 cmpList := lnkList;
662 i := 1;
663 WHILE i < mno DO
664 m := cmpList[i];
665 j := i - 1;
666 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
667 cmpList[j + 1] := cmpList[j];
668 DEC(j)
669 END;
670 cmpList[j + 1] := m;
671 INC(i)
672 END
673 END Sort;
675 PROCEDURE CheckDeps;
676 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
677 BEGIN
678 i := 0; rno := mno;
679 WHILE (err = 0) & (i < mno) DO
680 m := modList[i];
681 GetSource(m.name$, m.path, s);
682 IF s # NIL THEN
683 CheckModule(m, s, ok);
684 IF ~ok THEN INC(err) END
685 ELSE
687 END;
688 INC(i)
689 END;
690 INC(err, werr);
691 num := 0;
692 FOR i := 0 TO rno - 1 DO
693 Trace(modList[i], modList[i], num)
694 END;
695 ASSERT((err # 0) OR (num = mno), 100);
696 Sort;
697 IF debugOrder THEN
699 FOR i := 0 TO mno - 1 DO
701 END
702 END
703 END CheckDeps;
705 PROCEDURE IsCompiled (m: Module): BOOLEAN;
706 CONST target = {hasSym, hasObj};
707 VAR i: INTEGER; ready: BOOLEAN;
708 BEGIN
709 ASSERT(m # NIL, 20);
710 i := 0;
711 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
712 WHILE ready & (i < m.mno) DO
713 ready := IsCompiled(m.imp[i]);
714 INC(i)
715 END;
716 RETURN ready
717 END IsCompiled;
719 PROCEDURE Ready (m: Module): BOOLEAN;
720 CONST target = {hasSym, hasObj};
721 VAR i: INTEGER; ready: BOOLEAN;
722 BEGIN
723 i := 0;
724 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
725 WHILE ready & (i < m.mno) DO
726 ready := IsCompiled(m.imp[i]);
727 INC(i)
728 END;
729 RETURN ready
730 END Ready;
732 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
733 VAR i: INTEGER;
734 BEGIN
735 ASSERT(w # NIL, 20);
737 IF p # NIL THEN
739 w.PutParam(p[0]);
740 FOR i := 1 TO LEN(p) - 1 DO
742 w.PutParam(p[i])
743 END;
745 END;
746 IF debugArgs THEN Log.Ln END
747 END PutParams;
749 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
750 VAR w: DswProcs.Process; ok: BOOLEAN;
751 BEGIN
752 ASSERT(m # NIL, 20);
754 ASSERT(m.worker = NIL, 22);
755 w := DswProcs.dir.New();
756 w.Program(cpcExe);
758 PutParams(w, cpcArgs);
759 CASE compiler OF
760 | cpfront:
763 | cpnative:
766 END;
767 CASE processor OF
768 | mach386:
771 | mach68k:
774 ELSE
777 END;
778 CASE os OF
779 | anyos:
786 | linux:
793 | freebsd:
801 | openbsd:
809 | win32:
817 | cygwin:
825 | darwin:
833 END;
834 CASE linker OF
835 | dev2:
837 ELSE
839 END;
840 w.PutParam(m.path);
841 w.Execute(ok);
842 IF ok THEN
844 ELSE
845 w := NIL
846 END;
847 RETURN w
848 END ExecuteCompiler;
850 PROCEDURE Compile;
851 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
852 BEGIN
853 IF mno = 0 THEN RETURN END;
854 num := 0; j := 0;
855 WHILE (err = 0) & (num < mno) OR (j > 0) DO
856 i := 0;
857 WHILE (err = 0) & (i < mno) & (j < jobs) DO
858 m := cmpList[i];
859 IF Ready(m) THEN
860 w := ExecuteCompiler(m);
862 IF w # NIL THEN
864 m.worker := w;
865 INC(j)
866 ELSE
868 INCL(m.flags, hasErrors);
869 INC(err)
870 END;
871 IF debugJobs THEN Log.Ln END
872 END;
873 INC(i)
874 END;
875 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
876 i := 0;
877 WHILE (j > 0) & (i < mno) DO
878 m := cmpList[i];
879 w := m.worker;
880 IF (w # NIL) & w.IsTerminated() THEN
882 IF w.Result() = 0 THEN
883 INCL(m.flags, hasObj);
884 INCL(m.flags, hasSym);
885 INC(num)
886 ELSE
887 INCL(m.flags, hasErrors);
888 INC(err)
889 END;
890 m.worker := NIL;
891 DEC(j)
892 END;
893 INC(i)
894 END
895 END
896 END
897 END Compile;
899 PROCEDURE LinkDev2;
900 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
901 BEGIN
903 ASSERT(processor = mach386, 21);
904 ASSERT(compiler = cpnative, 22);
905 p := DswProcs.dir.New();
906 p.Program(cplExe);
907 IF os # anyos THEN
909 CASE os OF
915 END
916 END;
924 p.PutParam(exe);
925 PutParams(p, cplArgs);
926 i := 0;
927 WHILE i < mno DO
928 IF ~(library IN lnkList[i].flags) THEN
929 p.PutParam(lnkList[i].name$)
930 END;
931 INC(i)
932 END;
933 p.Execute(ok);
934 IF ok THEN
936 res := p.Result();
937 IF res # 0 THEN
939 END
940 ELSE
942 END
943 END LinkDev2;
945 PROCEDURE Link;
946 BEGIN
947 IF exe # NIL THEN
948 CASE linker OF
949 | anyint: (* do not link *)
950 | dev2: LinkDev2
951 END
952 END
953 END Link;
955 PROCEDURE Main;
956 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
957 BEGIN
958 IF Kernel.trapCount = 0 THEN
959 ParseArgs;
960 IF err = 0 THEN
961 CheckParams;
962 IF err = 0 THEN
963 CheckDeps;
964 IF err = 0 THEN
965 Compile;
966 IF err = 0 THEN
967 Link
968 END
969 END
970 END
971 END
973 END;
974 IF err = 0 THEN Kernel.Quit(0)
975 ELSE Kernel.Quit(1)
976 END;
977 END Main;
979 BEGIN
980 NEW(def);
981 ASSERT(def # NIL, 100);
982 Kernel.intTrap := FALSE;
983 Kernel.Start(Main)
984 END DswMakeMain.