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 ELSE err(ident)
482 END;
483 DevCPS.str := NIL
484 END ParseModule;
486 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
487 VAR s: Selector;
488 BEGIN
489 DevCPM.Init(source);
490 (*
491 DevCPM.symList := m.insym;
492 DevCPM.codePath := m.outcode;
493 DevCPM.symPath := m.outsym;
494 *)
495 DevCPM.name := m.name$;
496 (*
497 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
498 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
499 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
500 *)
501 DevCPR.Init;
502 s := m.selectors.next;
503 WHILE s # NIL DO
504 DevCPR.Set(s.name, s.value);
505 s := s.next
506 END;
507 ParseModule(m);
508 DevCPR.Check;
509 ok := DevCPM.noerr;
510 DevCPR.Close;
511 DevCPM.InsertMarks;
512 DevCPM.Close;
513 Kernel.FastCollect
514 END CheckModule;
516 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
518 VAR dir, name: Files.Name; loc: Files.Locator;
519 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
521 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
522 BEGIN
526 END;
527 Kernel.MakeFileName(path, type)
528 END MakePath;
530 BEGIN
532 Kernel.SplitName(modName, dir, name);
533 loc := Files.dir.This(dir).This(modDir);
534 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
537 IF text = NIL THEN
542 loc := Files.dir.This(sysDir).This(modDir);
544 IF text = NIL THEN
547 IF text = NIL THEN
549 END
550 END
551 END
552 END;
553 IF text # NIL THEN
554 NEW(s, text.Length() + 1);
555 IF s # NIL THEN
556 r := text.NewReader(NIL);
557 FOR i := 0 TO text.Length() - 1 DO
558 r.Read; s[i] := r.char
559 END
560 END
561 END
562 END GetSource;
564 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
565 VAR i: INTEGER;
566 BEGIN
567 IF ~(trace IN m.flags) THEN
568 INCL(m.flags, trace);
569 FOR i := 0 TO m.mno - 1 DO
570 Trace(m.imp[i], m, lno);
571 m.depth := MAX(m.depth, m.imp[i].depth + 1)
572 END;
573 IF ~(imported IN m.flags) THEN
574 INCL(m.flags, imported);
575 lnkList[lno] := m;
576 INC(lno)
577 END;
578 EXCL(m.flags, trace)
579 ELSE
581 END
582 END Trace;
584 PROCEDURE Sort;
585 VAR i, j: INTEGER; m: Module;
586 BEGIN
587 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
588 cmpList := lnkList;
589 i := 1;
590 WHILE i < mno DO
591 m := cmpList[i];
592 j := i - 1;
593 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
594 cmpList[j + 1] := cmpList[j];
595 DEC(j)
596 END;
597 cmpList[j + 1] := m;
598 INC(i)
599 END
600 END Sort;
602 PROCEDURE CheckDeps;
603 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
604 BEGIN
605 i := 0; rno := mno;
606 WHILE (err = 0) & (i < mno) DO
607 m := modList[i];
608 GetSource(m.name$, m.path, s);
609 IF s # NIL THEN
610 CheckModule(m, s, ok);
611 IF ~ok THEN INC(err) END
612 ELSE
614 END;
615 INC(i)
616 END;
617 INC(err, werr);
618 num := 0;
619 FOR i := 0 TO rno - 1 DO
620 Trace(modList[i], modList[i], num)
621 END;
622 ASSERT((err # 0) OR (num = mno), 100);
623 Sort;
624 IF debugOrder THEN
626 FOR i := 0 TO mno - 1 DO
628 END
629 END
630 END CheckDeps;
632 PROCEDURE IsCompiled (m: Module): BOOLEAN;
633 CONST target = {hasSym, hasObj};
634 VAR i: INTEGER; ready: BOOLEAN;
635 BEGIN
636 ASSERT(m # NIL, 20);
637 i := 0;
638 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
639 WHILE ready & (i < m.mno) DO
640 ready := IsCompiled(m.imp[i]);
641 INC(i)
642 END;
643 RETURN ready
644 END IsCompiled;
646 PROCEDURE Ready (m: Module): BOOLEAN;
647 CONST target = {hasSym, hasObj};
648 VAR i: INTEGER; ready: BOOLEAN;
649 BEGIN
650 i := 0;
651 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
652 WHILE ready & (i < m.mno) DO
653 ready := IsCompiled(m.imp[i]);
654 INC(i)
655 END;
656 RETURN ready
657 END Ready;
659 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
660 VAR i: INTEGER;
661 BEGIN
662 ASSERT(w # NIL, 20);
664 IF p # NIL THEN
666 w.PutParam(p[0]);
667 FOR i := 1 TO LEN(p) - 1 DO
669 w.PutParam(p[i])
670 END;
672 END;
673 IF debugArgs THEN Log.Ln END
674 END PutParams;
676 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
677 VAR w: DswProcs.Process; ok: BOOLEAN;
678 BEGIN
679 ASSERT(m # NIL, 20);
681 ASSERT(m.worker = NIL, 22);
682 w := DswProcs.dir.New();
683 w.Program(cpcExe);
685 PutParams(w, cpcArgs);
686 CASE compiler OF
687 | cpfront:
690 | cpnative:
693 END;
694 CASE processor OF
695 | mach386:
698 | mach68k:
701 ELSE
704 END;
705 CASE os OF
706 | anyos:
713 | linux:
720 | freebsd:
728 | openbsd:
736 | win32:
744 | cygwin:
752 | darwin:
760 END;
761 CASE linker OF
762 | dev2:
764 ELSE
766 END;
767 w.PutParam(m.path);
768 w.Execute(ok);
769 IF ok THEN
771 ELSE
772 w := NIL
773 END;
774 RETURN w
775 END ExecuteCompiler;
777 PROCEDURE Compile;
778 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
779 BEGIN
780 IF mno = 0 THEN RETURN END;
781 num := 0; j := 0;
782 WHILE (err = 0) & (num < mno) OR (j > 0) DO
783 i := 0;
784 WHILE (err = 0) & (i < mno) & (j < jobs) DO
785 m := cmpList[i];
786 IF Ready(m) THEN
787 w := ExecuteCompiler(m);
789 IF w # NIL THEN
791 m.worker := w;
792 INC(j)
793 ELSE
795 INCL(m.flags, hasErrors);
796 INC(err)
797 END;
798 IF debugJobs THEN Log.Ln END
799 END;
800 INC(i)
801 END;
802 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
803 i := 0;
804 WHILE (j > 0) & (i < mno) DO
805 m := cmpList[i];
806 w := m.worker;
807 IF (w # NIL) & w.IsTerminated() THEN
809 IF w.Result() = 0 THEN
810 INCL(m.flags, hasObj);
811 INCL(m.flags, hasSym);
812 INC(num)
813 ELSE
814 INCL(m.flags, hasErrors);
815 INC(err)
816 END;
817 m.worker := NIL;
818 DEC(j)
819 END;
820 INC(i)
821 END
822 END
823 END
824 END Compile;
826 PROCEDURE LinkDev2;
827 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
828 BEGIN
830 ASSERT(processor = mach386, 21);
831 ASSERT(compiler = cpnative, 22);
832 p := DswProcs.dir.New();
833 p.Program(cplExe);
834 IF os # anyos THEN
836 CASE os OF
842 END
843 END;
851 p.PutParam(exe);
852 PutParams(p, cplArgs);
853 i := 0;
854 WHILE i < mno DO
855 IF ~(library IN lnkList[i].flags) THEN
856 p.PutParam(lnkList[i].name$)
857 END;
858 INC(i)
859 END;
860 p.Execute(ok);
861 IF ok THEN
863 res := p.Result();
864 IF res # 0 THEN
866 INC(err)
867 END
868 ELSE
870 INC(err)
871 END
872 END LinkDev2;
874 PROCEDURE Link;
875 BEGIN
876 IF exe # NIL THEN
877 CASE linker OF
878 | anyint: (* do not link *)
879 | dev2: LinkDev2
880 END
881 END
882 END Link;
884 PROCEDURE Main;
885 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
886 BEGIN
887 IF Kernel.trapCount = 0 THEN
888 ParseArgs;
889 IF err = 0 THEN
890 CheckParams;
891 IF err = 0 THEN
892 CheckDeps;
893 IF err = 0 THEN
894 Compile;
895 IF err = 0 THEN
896 Link
897 END
898 END
899 END
900 END
901 ELSE INC(err)
902 END;
903 IF err = 0 THEN Kernel.Quit(0)
904 ELSE Kernel.Quit(1)
905 END;
906 END Main;
908 BEGIN
909 NEW(def);
910 Kernel.Start(Main)
911 END DswMakeMain.