bd06566f501cd9a00c76bd1fa0af2f0704680a2a
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
112 ELSE
121 (* --------- options --------- *)
125 BEGIN
130 RETURN i
135 BEGIN
149 ELSE
151 END
156 BEGIN
162 ELSE
164 END
169 BEGIN
177 RETURN t
182 BEGIN
194 END
195 ELSE
197 END
202 BEGIN
206 x := def
208 RETURN x
213 BEGIN
215 RETURN p
223 BEGIN
226 ELSE
235 END
240 BEGIN
243 ELSE
249 pars := p
254 BEGIN
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)
266 END
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
292 (*
295 *)
305 Log.String(' -U ident Remove preprocessor selector'); 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
322 s := DswOpts.str;
323 Strings.ToLower(s, s);
328 END
330 s := DswOpts.str;
331 Strings.ToLower(s, s);
340 END
342 s := DswOpts.str;
343 Strings.ToLower(s, s);
347 END
349 s := DswOpts.str;
350 Strings.ToLower(s, s);
353 END
357 END
358 END ParseTargetOpts;
360 PROCEDURE ParseCommandOpts;
361 BEGIN
368 END
369 END ParseCommandOpts;
371 PROCEDURE ParseExternalOpts;
372 BEGIN
379 END
380 END ParseExternalOpts;
382 PROCEDURE ParseInfoOpts;
383 BEGIN
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
412 | 0X: EXIT
413 END
414 END;
415 END ParseArgs;
417 PROCEDURE CheckParams;
418 BEGIN
419 IF compiler = anycp THEN
421 ELSIF compiler = cpnative THEN
422 IF processor = anymach THEN
424 ELSIF processor # mach386 THEN
426 END
427 END;
428 IF (compiler = cpfront) & (linker # anyint) THEN
430 END;
431 IF (compiler = cpfront) & (exe # NIL) THEN
433 END;
434 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
436 END;
437 IF (linker = dev2) & (os = anyos) THEN
439 END;
442 END;
443 IF (cpcExe = NIL) & (compiler # anycp) THEN
446 END;
447 IF cpcExe = NIL THEN
449 END
450 END;
451 IF (cplExe = NIL) & (linker # anyint) THEN
453 IF cplExe = NIL THEN
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);
470 ELSE
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
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
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);
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
607 END;
608 Kernel.MakeFileName(path, type)
609 END MakePath;
611 BEGIN
613 Kernel.SplitName(modName, dir, name);
614 loc := Files.dir.This(dir).This(modDir);
615 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
618 IF text = NIL THEN
623 loc := Files.dir.This(sysDir).This(modDir);
625 IF text = NIL THEN
628 IF text = NIL THEN
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
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
707 FOR i := 0 TO mno - 1 DO
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);
745 IF p # NIL THEN
747 w.PutParam(p[0]);
748 FOR i := 1 TO LEN(p) - 1 DO
750 w.PutParam(p[i])
751 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);
762 ASSERT(m.worker = NIL, 22);
763 w := DswProcs.dir.New();
764 w.Program(cpcExe);
766 PutParams(w, cpcArgs);
767 CASE compiler OF
768 | cpfront:
771 | cpnative:
774 END;
775 CASE processor OF
776 | mach386:
779 | mach68k:
782 ELSE
785 END;
786 CASE os OF
787 | linux:
794 | freebsd:
802 | openbsd:
810 | win32:
818 | cygwin:
826 | darwin:
834 ELSE
841 END;
842 CASE linker OF
843 | dev2:
845 ELSE
847 END;
848 w.PutParam(m.path);
849 w.Execute(ok);
850 IF ok THEN
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);
870 IF w # NIL THEN
872 m.worker := w;
873 INC(j)
874 ELSE
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
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
911 ASSERT(processor = mach386, 21);
912 ASSERT(compiler = cpnative, 22);
913 p := DswProcs.dir.New();
914 p.Program(cplExe);
915 IF os # anyos THEN
917 CASE os OF
923 END
924 END;
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
944 res := p.Result();
945 IF res # 0 THEN
947 END
948 ELSE
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
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.