04388d2a574ddde1ce50e7968e6b0b5c32867c0c
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 *)
302 Log.String(' -U ident Remove preprocessor selector'); 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
319 s := DswOpts.str;
320 Strings.ToLower(s, s);
325 END
327 s := DswOpts.str;
328 Strings.ToLower(s, s);
337 END
339 s := DswOpts.str;
340 Strings.ToLower(s, s);
344 END
346 s := DswOpts.str;
347 Strings.ToLower(s, s);
350 END
354 END
355 END ParseTargetOpts;
357 PROCEDURE ParseCommandOpts;
358 BEGIN
365 END
366 END ParseCommandOpts;
368 PROCEDURE ParseExternalOpts;
369 BEGIN
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
398 | 0X: EXIT
399 END
400 END;
401 END ParseArgs;
403 PROCEDURE CheckParams;
404 BEGIN
405 IF compiler = anycp THEN
407 ELSIF compiler = cpnative THEN
408 IF processor = anymach THEN
410 ELSIF processor # mach386 THEN
412 END
413 END;
414 IF (compiler = cpfront) & (linker # anyint) THEN
416 END;
417 IF (compiler = cpfront) & (exe # NIL) THEN
419 END;
420 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
422 END;
423 IF (linker = dev2) & (os = anyos) THEN
425 END;
428 END;
429 IF cpcExe = NIL THEN
432 END
433 END;
434 IF cplExe = NIL THEN
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);
450 ELSE
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
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
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);
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
587 END;
588 Kernel.MakeFileName(path, type)
589 END MakePath;
591 BEGIN
593 Kernel.SplitName(modName, dir, name);
594 loc := Files.dir.This(dir).This(modDir);
595 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
598 IF text = NIL THEN
603 loc := Files.dir.This(sysDir).This(modDir);
605 IF text = NIL THEN
608 IF text = NIL THEN
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
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
687 FOR i := 0 TO mno - 1 DO
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);
725 IF p # NIL THEN
727 w.PutParam(p[0]);
728 FOR i := 1 TO LEN(p) - 1 DO
730 w.PutParam(p[i])
731 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);
742 ASSERT(m.worker = NIL, 22);
743 w := DswProcs.dir.New();
744 w.Program(cpcExe);
746 PutParams(w, cpcArgs);
747 CASE compiler OF
748 | cpfront:
751 | cpnative:
754 END;
755 CASE processor OF
756 | mach386:
759 | mach68k:
762 ELSE
765 END;
766 CASE os OF
767 | anyos:
774 | linux:
781 | freebsd:
789 | openbsd:
797 | win32:
805 | cygwin:
813 | darwin:
821 END;
822 CASE linker OF
823 | dev2:
825 ELSE
827 END;
828 w.PutParam(m.path);
829 w.Execute(ok);
830 IF ok THEN
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);
850 IF w # NIL THEN
852 m.worker := w;
853 INC(j)
854 ELSE
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
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
891 ASSERT(processor = mach386, 21);
892 ASSERT(compiler = cpnative, 22);
893 p := DswProcs.dir.New();
894 p.Program(cplExe);
895 IF os # anyos THEN
897 CASE os OF
903 END
904 END;
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
924 res := p.Result();
925 IF res # 0 THEN
927 END
928 ELSE
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
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.