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 *)
260 (*
262 *)
266 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
269 Kernel.Quit(1)
270 END Help;
272 PROCEDURE Version;
273 BEGIN
274 Log.String(version); Log.Ln;
275 Kernel.Quit(0)
276 END Version;
278 PROCEDURE ParseTargetOpts;
279 VAR s: DswOpts.String;
280 BEGIN
283 s := DswOpts.str;
284 Strings.ToLower(s, s);
289 END
291 s := DswOpts.str;
292 Strings.ToLower(s, s);
296 END
298 s := DswOpts.str;
299 Strings.ToLower(s, s);
303 END
305 s := DswOpts.str;
306 Strings.ToLower(s, s);
309 END
313 END
314 END ParseTargetOpts;
316 PROCEDURE ParseCommandOpts;
317 BEGIN
324 END
325 END ParseCommandOpts;
327 PROCEDURE ParseExternalOpts;
328 BEGIN
335 END
336 END ParseExternalOpts;
338 PROCEDURE ParseArgs;
339 BEGIN
340 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
341 processor := anymach; os := anyos; compiler := anycp;
342 LOOP
357 | 0X: EXIT
358 END
359 END;
360 END ParseArgs;
362 PROCEDURE CheckParams;
363 BEGIN
364 IF compiler = anycp THEN
366 ELSIF compiler = cpnative THEN
367 IF processor = anymach THEN
369 ELSIF processor # mach386 THEN
371 END
372 END;
373 IF (compiler = cpfront) & (linker # anyint) THEN
375 END;
376 IF (compiler = cpfront) & (exe # NIL) THEN
378 END;
379 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
381 END;
382 IF (linker = dev2) & (os = anyos) THEN
384 END;
387 END;
388 IF cpcExe = NIL THEN
391 END
392 END;
393 IF cplExe = NIL THEN
395 END
396 END CheckParams;
398 (* --------- loader --------- *)
400 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
401 VAR i, j: INTEGER; imp: Module;
402 BEGIN
403 ASSERT(m # NIL, 20);
409 ELSE
411 i := 0; (* find module in local list *)
412 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
413 IF i >= m.mno THEN
414 j := 0; (* find module in global list *)
415 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
416 IF j >= mno THEN
417 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
418 modList[mno] := imp; INC(mno)
419 ELSE
420 imp := modList[j]
421 END;
422 m.imp[m.mno] := imp; INC(m.mno)
423 ELSE DevCPM.err(1)
424 END
425 END;
426 IF debugImport THEN Log.Ln END;
427 END Import;
429 PROCEDURE ParseModule (m: Module);
430 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
432 PROCEDURE err (n: SHORTINT);
433 BEGIN DevCPM.err(n)
434 END err;
436 PROCEDURE CheckSym(s: SHORTINT);
437 BEGIN
438 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
439 END CheckSym;
441 BEGIN
443 DevCPS.Init; DevCPS.Get(sym);
444 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
445 IF sym = ident THEN
446 SelfName := DevCPS.name$; DevCPS.Get(sym);
447 IF sym = lbrak THEN
448 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
449 IF sym = eql THEN DevCPS.Get(sym)
450 ELSE INCL(DevCPM.options, DevCPM.noCode)
451 END;
452 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
453 ELSE err(string)
454 END;
455 CheckSym(rbrak)
456 END;
457 CheckSym(semicolon);
458 IF sym = import THEN DevCPS.Get(sym);
459 LOOP
460 IF sym = ident THEN
461 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
462 IF sym = becomes THEN DevCPS.Get(sym);
463 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
464 END;
465 Import(m, impName)
466 ELSE err(ident)
467 END;
468 IF sym = comma THEN DevCPS.Get(sym)
469 ELSIF sym = ident THEN err(comma)
470 ELSE EXIT
471 END
472 END;
473 CheckSym(semicolon)
474 END
475 ELSE err(ident)
476 END;
477 DevCPS.str := NIL
478 END ParseModule;
480 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
481 VAR s: Selector;
482 BEGIN
483 DevCPM.Init(source);
484 (*
485 DevCPM.symList := m.insym;
486 DevCPM.codePath := m.outcode;
487 DevCPM.symPath := m.outsym;
488 *)
489 DevCPM.name := m.name$;
490 (*
491 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
492 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
493 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
494 *)
495 DevCPR.Init;
496 s := m.selectors.next;
497 WHILE s # NIL DO
498 DevCPR.Set(s.name, s.value);
499 s := s.next
500 END;
501 ParseModule(m);
502 DevCPR.Check;
503 ok := DevCPM.noerr;
504 DevCPR.Close;
505 DevCPM.InsertMarks;
506 DevCPM.Close;
507 Kernel.FastCollect
508 END CheckModule;
510 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
512 VAR dir, name: Files.Name; loc: Files.Locator;
513 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
515 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
516 BEGIN
520 END;
521 Kernel.MakeFileName(path, type)
522 END MakePath;
524 BEGIN
526 Kernel.SplitName(modName, dir, name);
527 loc := Files.dir.This(dir).This(modDir);
528 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
531 IF text = NIL THEN
536 loc := Files.dir.This(sysDir).This(modDir);
538 IF text = NIL THEN
541 IF text = NIL THEN
543 END
544 END
545 END
546 END;
547 IF text # NIL THEN
548 NEW(s, text.Length() + 1);
549 IF s # NIL THEN
550 r := text.NewReader(NIL);
551 FOR i := 0 TO text.Length() - 1 DO
552 r.Read; s[i] := r.char
553 END
554 END
555 END
556 END GetSource;
558 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
559 VAR i: INTEGER;
560 BEGIN
561 IF ~(trace IN m.flags) THEN
562 INCL(m.flags, trace);
563 FOR i := 0 TO m.mno - 1 DO
564 Trace(m.imp[i], m, lno);
565 m.depth := MAX(m.depth, m.imp[i].depth + 1)
566 END;
567 IF ~(imported IN m.flags) THEN
568 INCL(m.flags, imported);
569 lnkList[lno] := m;
570 INC(lno)
571 END;
572 EXCL(m.flags, trace)
573 ELSE
575 END
576 END Trace;
578 PROCEDURE Sort;
579 VAR i, j: INTEGER; m: Module;
580 BEGIN
581 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
582 cmpList := lnkList;
583 i := 1;
584 WHILE i < mno DO
585 m := cmpList[i];
586 j := i - 1;
587 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
588 cmpList[j + 1] := cmpList[j];
589 DEC(j)
590 END;
591 cmpList[j + 1] := m;
592 INC(i)
593 END
594 END Sort;
596 PROCEDURE CheckDeps;
597 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
598 BEGIN
599 i := 0; rno := mno;
600 WHILE (err = 0) & (i < mno) DO
601 m := modList[i];
602 GetSource(m.name$, m.path, s);
603 IF s # NIL THEN
604 CheckModule(m, s, ok);
605 IF ~ok THEN INC(err) END
606 ELSE
608 END;
609 INC(i)
610 END;
611 num := 0;
612 FOR i := 0 TO rno - 1 DO
613 Trace(modList[i], modList[i], num)
614 END;
615 ASSERT((err # 0) OR (num = mno), 100);
616 Sort;
617 IF debugOrder THEN
619 FOR i := 0 TO mno - 1 DO
621 END
622 END
623 END CheckDeps;
625 PROCEDURE IsCompiled (m: Module): BOOLEAN;
626 CONST target = {hasSym, hasObj};
627 VAR i: INTEGER; ready: BOOLEAN;
628 BEGIN
629 ASSERT(m # NIL, 20);
630 i := 0;
631 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
632 WHILE ready & (i < m.mno) DO
633 ready := IsCompiled(m.imp[i]);
634 INC(i)
635 END;
636 RETURN ready
637 END IsCompiled;
639 PROCEDURE Ready (m: Module): BOOLEAN;
640 CONST target = {hasSym, hasObj};
641 VAR i: INTEGER; ready: BOOLEAN;
642 BEGIN
643 i := 0;
644 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
645 WHILE ready & (i < m.mno) DO
646 ready := IsCompiled(m.imp[i]);
647 INC(i)
648 END;
649 RETURN ready
650 END Ready;
652 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
653 VAR i: INTEGER;
654 BEGIN
655 ASSERT(w # NIL, 20);
657 IF p # NIL THEN
659 w.PutParam(p[0]);
660 FOR i := 1 TO LEN(p) - 1 DO
662 w.PutParam(p[i])
663 END;
665 END;
666 IF debugArgs THEN Log.Ln END
667 END PutParams;
669 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
670 VAR w: DswProcs.Process; ok: BOOLEAN;
671 BEGIN
672 ASSERT(m # NIL, 20);
674 ASSERT(m.worker = NIL, 22);
675 w := DswProcs.dir.New();
676 w.Program(cpcExe);
678 PutParams(w, cpcArgs);
679 w.PutParam(m.path);
680 w.Execute(ok);
681 IF ok THEN
683 ELSE
684 w := NIL
685 END;
686 RETURN w
687 END ExecuteCompiler;
689 PROCEDURE Compile;
690 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
691 BEGIN
692 IF mno = 0 THEN RETURN END;
693 num := 0; j := 0;
694 WHILE (err = 0) & (num < mno) OR (j > 0) DO
695 i := 0;
696 WHILE (err = 0) & (i < mno) & (j < jobs) DO
697 m := cmpList[i];
698 IF Ready(m) THEN
699 w := ExecuteCompiler(m);
701 IF w # NIL THEN
703 m.worker := w;
704 INC(j)
705 ELSE
707 INCL(m.flags, hasErrors);
708 INC(err)
709 END;
710 IF debugJobs THEN Log.Ln END
711 END;
712 INC(i)
713 END;
714 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
715 i := 0;
716 WHILE (j > 0) & (i < mno) DO
717 m := cmpList[i];
718 w := m.worker;
719 IF (w # NIL) & w.IsTerminated() THEN
721 IF w.Result() = 0 THEN
722 INCL(m.flags, hasObj);
723 INCL(m.flags, hasSym);
724 INC(num)
725 ELSE
726 INCL(m.flags, hasErrors);
727 INC(err)
728 END;
729 m.worker := NIL;
730 DEC(j)
731 END;
732 INC(i)
733 END
734 END
735 END
736 END Compile;
738 PROCEDURE LinkDev2;
739 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
740 BEGIN
742 ASSERT(processor = mach386, 21);
743 ASSERT(compiler = cpnative, 22);
744 ASSERT(os IN {linux, freebsd, openbsd, win32}, 23);
745 p := DswProcs.dir.New();
746 p.Program(cplExe);
747 IF os # anyos THEN
749 CASE os OF
754 END
755 END;
763 p.PutParam(exe);
764 PutParams(p, cplArgs);
765 i := 0;
766 WHILE i < mno DO
767 IF ~(library IN lnkList[i].flags) THEN
768 p.PutParam(lnkList[i].name$)
769 END;
770 INC(i)
771 END;
772 p.Execute(ok);
773 IF ok THEN
775 res := p.Result();
776 IF res # 0 THEN
778 INC(err)
779 END
780 ELSE
782 INC(err)
783 END
784 END LinkDev2;
786 PROCEDURE Link;
787 BEGIN
788 IF exe # NIL THEN
789 CASE linker OF
790 | anyint: (* do not link *)
791 | dev2: LinkDev2
792 END
793 END
794 END Link;
796 PROCEDURE Main;
797 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
798 BEGIN
799 IF Kernel.trapCount = 0 THEN
800 ParseArgs;
801 IF err = 0 THEN
802 CheckParams;
803 IF err = 0 THEN
804 CheckDeps;
805 IF err = 0 THEN
806 Compile;
807 IF err = 0 THEN
808 Link
809 END
810 END
811 END
812 END
813 ELSE INC(err)
814 END;
815 IF err = 0 THEN Kernel.Quit(0)
816 ELSE Kernel.Quit(1)
817 END;
818 END Main;
820 BEGIN
821 NEW(def);
822 Kernel.Start(Main)
823 END DswMakeMain.