9cb6a98e7ed5de28fee74f202633123605f25b76
3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
14 (* symbol values *)
31 (* module state flags *)
34 (* procesor types *)
37 (* operation system types *)
40 (* compiler types *)
43 (* internal linker types *)
51 TYPE
58 next: Selector
73 VAR
88 BEGIN
117 ELSE
126 (* --------- options --------- *)
130 BEGIN
135 RETURN i
140 BEGIN
154 ELSE
156 END
161 BEGIN
167 ELSE
169 END
174 BEGIN
182 RETURN t
187 BEGIN
200 END
201 ELSE
203 END
208 BEGIN
212 x := def
214 RETURN x
219 BEGIN
221 RETURN p
229 BEGIN
232 ELSE
241 END
246 BEGIN
249 ELSE
255 pars := p
260 BEGIN
266 term := ch; ch := s[i]; INC(i);
267 WHILE (ch # term) & (ch # 0X) DO
268 AddChar(ch); ch := s[i]; INC(i)
269 END;
270 IF ch # 0X THEN ch := s[i]; INC(i)
272 END
275 IF ch # 0X THEN AddLine END
276 ELSE
277 AddChar(ch); ch := s[i]; INC(i)
278 END
279 END;
280 RETURN pars
281 END ToStringList;
283 PROCEDURE Help;
284 BEGIN
298 (*
300 *)
310 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
313 Kernel.Quit(1)
314 END Help;
316 PROCEDURE Version;
317 BEGIN
318 Log.String(version); Log.Ln;
319 Kernel.Quit(0)
320 END Version;
322 PROCEDURE ParseTargetOpts;
323 VAR s: DswOpts.String;
324 BEGIN
327 s := DswOpts.str;
328 Strings.ToLower(s, s);
333 END
335 s := DswOpts.str;
336 Strings.ToLower(s, s);
345 END
347 s := DswOpts.str;
348 Strings.ToLower(s, s);
352 END
354 s := DswOpts.str;
355 Strings.ToLower(s, s);
358 END
362 END
363 END ParseTargetOpts;
365 PROCEDURE ParseCommandOpts;
366 BEGIN
373 END
374 END ParseCommandOpts;
376 PROCEDURE ParseExternalOpts;
377 BEGIN
384 END
385 END ParseExternalOpts;
387 PROCEDURE ParseInfoOpts;
388 BEGIN
394 END
395 END ParseInfoOpts;
397 PROCEDURE ParseFileOpts;
398 VAR d: DevCPM.Directory;
399 BEGIN
405 END
406 END ParseFileOpts;
408 PROCEDURE ParseArgs;
409 BEGIN
410 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
411 processor := anymach; os := anyos; compiler := anycp;
412 LOOP
429 | 0X: EXIT
430 END
431 END;
432 END ParseArgs;
434 PROCEDURE CheckParams;
435 BEGIN
436 IF compiler = anycp THEN
438 ELSIF compiler = cpnative THEN
439 IF processor = anymach THEN
441 ELSIF processor # mach386 THEN
443 END
444 END;
445 IF (compiler = cpfront) & (linker # anyint) THEN
447 END;
448 IF (compiler = cpfront) & (exe # NIL) THEN
450 END;
451 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
453 END;
454 IF (linker = dev2) & (os = anyos) THEN
456 END;
459 END;
460 IF (cpcExe = NIL) & (compiler # anycp) THEN
463 END;
464 IF cpcExe = NIL THEN
466 END
467 END;
468 IF (cplExe = NIL) & (linker # anyint) THEN
470 IF cplExe = NIL THEN
472 END
473 END
474 END CheckParams;
476 (* --------- loader --------- *)
478 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
479 VAR i, j: INTEGER; imp: Module;
480 BEGIN
481 ASSERT(m # NIL, 20);
487 ELSE
489 i := 0; (* find module in local list *)
490 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
491 IF i >= m.mno THEN
492 j := 0; (* find module in global list *)
493 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
494 IF j >= mno THEN
495 IF ~auto THEN
497 END;
498 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
499 modList[mno] := imp; INC(mno)
500 ELSE
501 imp := modList[j]
502 END;
503 m.imp[m.mno] := imp; INC(m.mno)
504 ELSE DevCPM.err(1)
505 END
506 END;
507 IF debugImport THEN Log.Ln END;
508 END Import;
510 PROCEDURE ParseModule (m: Module);
511 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
513 PROCEDURE err (n: SHORTINT);
514 BEGIN DevCPM.err(n)
515 END err;
517 PROCEDURE CheckSym(s: SHORTINT);
518 BEGIN
519 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
520 END CheckSym;
522 BEGIN
524 DevCPS.Init; DevCPS.Get(sym);
525 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
526 IF sym = ident THEN
527 SelfName := DevCPS.name$; DevCPS.Get(sym);
528 IF sym = lbrak THEN
529 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
530 IF sym = eql THEN DevCPS.Get(sym)
531 ELSE INCL(DevCPM.options, DevCPM.noCode)
532 END;
533 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
534 ELSE err(string)
535 END;
536 CheckSym(rbrak)
537 END;
538 CheckSym(semicolon);
539 IF sym = import THEN DevCPS.Get(sym);
540 LOOP
541 IF sym = ident THEN
542 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
543 IF sym = becomes THEN DevCPS.Get(sym);
544 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
545 END;
546 Import(m, impName)
547 ELSE err(ident)
548 END;
549 IF sym = comma THEN DevCPS.Get(sym)
550 ELSIF sym = ident THEN err(comma)
551 ELSE EXIT
552 END
553 END;
554 CheckSym(semicolon)
555 END;
556 LOOP (* preprocessor must read module fully *)
557 IF sym = end THEN
558 DevCPS.Get(sym);
559 IF sym = ident THEN
560 DevCPS.Get(sym);
561 IF sym = period THEN
562 IF DevCPS.name # SelfName THEN err(4) END;
563 EXIT
564 ELSIF sym = eof THEN
565 err(period);
566 EXIT
567 END
568 ELSIF sym = eof THEN
569 err(ident);
570 EXIT
571 END;
572 ELSIF sym = eof THEN
573 err(end);
574 EXIT
575 ELSE
576 DevCPS.Get(sym);
577 END
578 END
579 ELSE err(ident)
580 END;
581 DevCPS.str := NIL
582 END ParseModule;
584 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
585 VAR s: Selector;
586 BEGIN
587 DevCPM.Init(source);
588 DevCPM.symList := m.dir;
589 (*
590 DevCPM.codePath := m.outcode;
591 DevCPM.symPath := m.outsym;
592 *)
593 DevCPM.name := m.name$;
594 (*
595 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
596 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
597 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
598 *)
599 DevCPR.Init;
600 s := m.selectors.next;
601 WHILE s # NIL DO
602 DevCPR.Set(s.name, s.value);
603 s := s.next
604 END;
605 ParseModule(m);
606 DevCPR.Check;
607 ok := DevCPM.noerr;
608 DevCPR.Close;
609 DevCPM.InsertMarks;
610 DevCPM.Close;
611 Kernel.FastCollect
612 END CheckModule;
614 PROCEDURE MakePath (IN dir, name: Files.Name; IN type: Files.Type; OUT path: Files.Name);
615 BEGIN
619 END;
620 Kernel.MakeFileName(path, type)
621 END MakePath;
623 PROCEDURE Open (loc: Files.Locator; IN sub, name: Files.Name; OUT path: Files.Name; OUT text: DswDocuments.Model);
624 VAR res: INTEGER;
625 BEGIN
626 ASSERT(loc # NIL, 20);
631 IF text = NIL THEN
636 loc := Files.dir.This(sysDir).This(modDir);
638 IF text = NIL THEN
641 IF text = NIL THEN
643 END
644 END
645 END
646 END
647 END Open;
649 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; list: DevCPM.Directory; OUT path: Files.Name; OUT s: String);
650 VAR
651 sub, name: Files.Name; loc: Files.Locator; base: DevCPM.Directory;
652 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
653 BEGIN
655 Kernel.SplitName(modName, sub, name);
656 loc := Files.dir.This(sub).This(modDir);
657 Open(loc, sub, name, path, text);
658 WHILE (text = NIL) & (base # NIL) DO
659 ASSERT(base.legacy, 100);
660 loc := Files.dir.This(base.path).This(sub).This(modDir);
661 Open(loc, sub, name, path, text);
662 base := base.next
663 END;
664 IF text # NIL THEN
665 NEW(s, text.Length() + 1);
666 IF s # NIL THEN
667 r := text.NewReader(NIL);
668 FOR i := 0 TO text.Length() - 1 DO
669 r.Read; s[i] := r.char
670 END
671 END
672 END
673 END GetSource;
675 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
676 VAR i: INTEGER;
677 BEGIN
678 IF ~(trace IN m.flags) THEN
679 INCL(m.flags, trace);
680 FOR i := 0 TO m.mno - 1 DO
681 Trace(m.imp[i], m, lno);
682 m.depth := MAX(m.depth, m.imp[i].depth + 1)
683 END;
684 IF ~(imported IN m.flags) THEN
685 INCL(m.flags, imported);
686 lnkList[lno] := m;
687 INC(lno)
688 END;
689 EXCL(m.flags, trace)
690 ELSE
691 Error(20, m.name$, parent.name$, 0)
692 END
693 END Trace;
695 PROCEDURE Sort;
696 VAR i, j: INTEGER; m: Module;
697 BEGIN
698 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
699 cmpList := lnkList;
700 i := 1;
701 WHILE i < mno DO
702 m := cmpList[i];
703 j := i - 1;
704 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
705 cmpList[j + 1] := cmpList[j];
706 DEC(j)
707 END;
708 cmpList[j + 1] := m;
709 INC(i)
710 END
711 END Sort;
713 PROCEDURE CheckDeps;
714 VAR i, j, num: INTEGER; m: Module; src: String; ok: BOOLEAN;
715 BEGIN
716 i := 0; rno := mno;
717 WHILE (err = 0) & (i < mno) DO
718 m := modList[i];
719 GetSource(m.name$, m.dir, m.path, src);
720 IF src # NIL THEN
721 CheckModule(m, src, ok);
722 IF ~ok THEN INC(err) END
723 ELSE
725 END;
726 INC(i)
727 END;
728 INC(err, werr);
729 num := 0;
730 FOR i := 0 TO rno - 1 DO
731 Trace(modList[i], modList[i], num)
732 END;
733 ASSERT((err # 0) OR (num = mno), 100);
734 Sort;
735 IF debugOrder THEN
737 FOR i := 0 TO mno - 1 DO
739 END
740 END
741 END CheckDeps;
743 PROCEDURE IsCompiled (m: Module): BOOLEAN;
744 CONST target = {hasSym, hasObj};
745 VAR i: INTEGER; ready: BOOLEAN;
746 BEGIN
747 ASSERT(m # NIL, 20);
748 i := 0;
749 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
750 WHILE ready & (i < m.mno) DO
751 ready := IsCompiled(m.imp[i]);
752 INC(i)
753 END;
754 RETURN ready
755 END IsCompiled;
757 PROCEDURE Ready (m: Module): BOOLEAN;
758 CONST target = {hasSym, hasObj};
759 VAR i: INTEGER; ready: BOOLEAN;
760 BEGIN
761 i := 0;
762 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
763 WHILE ready & (i < m.mno) DO
764 ready := IsCompiled(m.imp[i]);
765 INC(i)
766 END;
767 RETURN ready
768 END Ready;
770 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
771 VAR i: INTEGER;
772 BEGIN
773 ASSERT(w # NIL, 20);
775 IF p # NIL THEN
777 w.PutParam(p[0]);
778 FOR i := 1 TO LEN(p) - 1 DO
780 w.PutParam(p[i])
781 END;
783 END;
784 IF debugArgs THEN Log.Ln END
785 END PutParams;
787 PROCEDURE PutPathList (w: DswProcs.Process; IN par: ARRAY OF CHAR; base: DevCPM.Directory);
788 BEGIN
789 IF base # NIL THEN
790 PutPath(w, base.next); (* in revese order *)
791 w.PutParam(par);
792 w.PutParam(base.path);
793 END
794 END PutPathList;
796 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
797 VAR w: DswProcs.Process; ok: BOOLEAN;
798 BEGIN
799 ASSERT(m # NIL, 20);
801 ASSERT(m.worker = NIL, 22);
802 w := DswProcs.dir.New();
803 w.Program(cpcExe);
806 PutParams(w, cpcArgs);
807 CASE compiler OF
808 | cpfront:
811 | cpnative:
814 END;
815 CASE processor OF
816 | mach386:
819 | mach68k:
822 ELSE
825 END;
826 CASE os OF
827 | linux:
834 | freebsd:
842 | openbsd:
850 | win32:
858 | cygwin:
866 | darwin:
874 ELSE
881 END;
882 CASE linker OF
883 | dev2:
885 ELSE
887 END;
888 w.PutParam(m.path);
889 w.Execute(ok);
890 IF ok THEN
892 ELSE
893 w := NIL
894 END;
895 RETURN w
896 END ExecuteCompiler;
898 PROCEDURE Compile;
899 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
900 BEGIN
901 IF mno = 0 THEN RETURN END;
902 num := 0; j := 0;
903 WHILE (err = 0) & (num < mno) OR (j > 0) DO
904 i := 0;
905 WHILE (err = 0) & (i < mno) & (j < jobs) DO
906 m := cmpList[i];
907 IF Ready(m) THEN
908 w := ExecuteCompiler(m);
910 IF w # NIL THEN
912 m.worker := w;
913 INC(j)
914 ELSE
916 INCL(m.flags, hasErrors);
917 INC(err)
918 END;
919 IF debugJobs THEN Log.Ln END
920 END;
921 INC(i)
922 END;
923 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
924 i := 0;
925 WHILE (j > 0) & (i < mno) DO
926 m := cmpList[i];
927 w := m.worker;
928 IF (w # NIL) & w.IsTerminated() THEN
930 IF w.Result() = 0 THEN
931 INCL(m.flags, hasObj);
932 INCL(m.flags, hasSym);
933 INC(num)
934 ELSE
935 INCL(m.flags, hasErrors);
936 INC(err)
937 END;
938 m.worker := NIL;
939 DEC(j)
940 END;
941 INC(i)
942 END
943 END
944 END
945 END Compile;
947 PROCEDURE LinkDev2;
948 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
949 BEGIN
951 ASSERT(processor = mach386, 21);
952 ASSERT(compiler = cpnative, 22);
953 p := DswProcs.dir.New();
954 p.Program(cplExe);
956 IF os # anyos THEN
958 CASE os OF
964 END
965 END;
973 p.PutParam(exe);
974 PutParams(p, cplArgs);
975 i := 0;
976 WHILE i < mno DO
977 IF ~(library IN lnkList[i].flags) THEN
978 p.PutParam(lnkList[i].name$)
979 END;
980 INC(i)
981 END;
982 p.Execute(ok);
983 IF ok THEN
985 res := p.Result();
986 IF res # 0 THEN
988 END
989 ELSE
991 END
992 END LinkDev2;
994 PROCEDURE Link;
995 BEGIN
996 IF exe # NIL THEN
997 CASE linker OF
998 | anyint: (* do not link *)
999 | dev2: LinkDev2
1000 END
1001 END
1002 END Link;
1004 PROCEDURE Main;
1005 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
1006 BEGIN
1007 IF Kernel.trapCount = 0 THEN
1008 ParseArgs;
1009 IF err = 0 THEN
1010 CheckParams;
1011 IF err = 0 THEN
1012 CheckDeps;
1013 IF err = 0 THEN
1014 Compile;
1015 IF err = 0 THEN
1016 Link
1017 END
1018 END
1019 END
1020 END
1022 END;
1023 IF err = 0 THEN Kernel.Quit(0)
1024 ELSE Kernel.Quit(1)
1025 END;
1026 END Main;
1028 BEGIN
1029 NEW(def);
1030 ASSERT(def # NIL, 100);
1031 Kernel.intTrap := FALSE;
1032 Kernel.Start(Main)
1033 END DswMakeMain.