3 IMPORT Kernel, Files, Log, Strings, DswOpts, DswProcs, DswDocuments, DevCPM, DevCPT, DevCPR, DevCPS;
5 CONST
9 (* symbol values *)
26 (* module state flags *)
29 (* procesor types *)
32 (* operation system types *)
35 (* compiler types *)
38 (* internal linker types *)
46 TYPE
53 next: Selector
67 VAR
79 (* --------- options --------- *)
83 BEGIN
88 RETURN i
93 BEGIN
107 ELSE
109 END
114 BEGIN
120 ELSE
122 END
127 BEGIN
135 RETURN t
140 BEGIN
152 END
153 ELSE
155 END
160 BEGIN
164 x := def
166 RETURN x
171 BEGIN
173 RETURN p
181 BEGIN
184 ELSE
193 END
198 BEGIN
201 ELSE
207 pars := p
212 BEGIN
218 term := ch; ch := s[i]; INC(i);
219 WHILE (ch # term) & (ch # 0X) DO
220 AddChar(ch); ch := s[i]; INC(i)
221 END;
222 IF ch # 0X THEN ch := s[i]; INC(i)
224 END
227 IF ch # 0X THEN AddLine END
228 ELSE
229 AddChar(ch); ch := s[i]; INC(i)
230 END
231 END;
232 RETURN pars
233 END ToStringList;
235 PROCEDURE Help;
236 BEGIN
250 (*
253 *)
258 (*
260 *)
264 Log.String(' -U ident Remove preprocessor selector'); Log.Ln;
267 Kernel.Quit(1)
268 END Help;
270 PROCEDURE ParseTargetOpts;
271 VAR s: DswOpts.String;
272 BEGIN
275 s := DswOpts.str;
276 Strings.ToLower(s, s);
281 END
283 s := DswOpts.str;
284 Strings.ToLower(s, s);
288 END
290 s := DswOpts.str;
291 Strings.ToLower(s, s);
295 END
297 s := DswOpts.str;
298 Strings.ToLower(s, s);
301 END
305 END
306 END ParseTargetOpts;
308 PROCEDURE ParseCommandOpts;
309 BEGIN
316 END
317 END ParseCommandOpts;
319 PROCEDURE ParseExternalOpts;
320 BEGIN
327 END
328 END ParseExternalOpts;
330 PROCEDURE ParseArgs;
331 BEGIN
332 exe := NIL; auto := FALSE; jobs := 1; def.next := NIL; mno := 0; rno := 0;
333 processor := anymach; os := anyos; compiler := anycp;
334 LOOP
348 | 0X: EXIT
349 END
350 END
351 END ParseArgs;
353 PROCEDURE CheckParams;
354 BEGIN
355 IF compiler = anycp THEN
357 ELSIF compiler = cpnative THEN
358 IF processor = anymach THEN
360 ELSIF processor # mach386 THEN
362 END
363 END;
364 IF (compiler = cpfront) & (linker # anyint) THEN
366 END;
367 IF (compiler = cpfront) & (exe # NIL) THEN
369 END;
370 IF (exe # NIL) & (compiler = cpnative) & (linker = anyint) THEN
372 END;
373 IF (linker = dev2) & (os = anyos) THEN
375 END;
378 END;
379 IF cpcExe = NIL THEN
382 END
383 END;
384 IF cplExe = NIL THEN
386 END
387 END CheckParams;
389 (* --------- loader --------- *)
391 PROCEDURE Import (m: Module; IN name: DevCPT.Name);
392 VAR i, j: INTEGER; imp: Module;
393 BEGIN
394 ASSERT(m # NIL, 20);
400 ELSE
402 i := 0; (* find module in local list *)
403 WHILE (i < m.mno) & (m.imp[i].name$ # name$) DO INC(i) END;
404 IF i >= m.mno THEN
405 j := 0; (* find module in global list *)
406 WHILE (j < mno) & (modList[j].name$ # name$) DO INC(j) END;
407 IF j >= mno THEN
408 NEW(imp); imp.name := name$; imp.selectors := CopySelectorList(m.selectors);
409 modList[mno] := imp; INC(mno)
410 ELSE
411 imp := modList[j]
412 END;
413 m.imp[m.mno] := imp; INC(m.mno)
414 ELSE DevCPM.err(1)
415 END
416 END;
417 IF debugImport THEN Log.Ln END;
418 END Import;
420 PROCEDURE ParseModule (m: Module);
421 VAR sym: BYTE; SelfName, impName, aliasName: DevCPT.Name;
423 PROCEDURE err (n: SHORTINT);
424 BEGIN DevCPM.err(n)
425 END err;
427 PROCEDURE CheckSym(s: SHORTINT);
428 BEGIN
429 IF sym = s THEN DevCPS.Get(sym) ELSE DevCPM.err(s) END
430 END CheckSym;
432 BEGIN
434 DevCPS.Init; DevCPS.Get(sym);
435 IF sym = module THEN DevCPS.Get(sym) ELSE err(16) END;
436 IF sym = ident THEN
437 SelfName := DevCPS.name$; DevCPS.Get(sym);
438 IF sym = lbrak THEN
439 INCL(DevCPM.options, DevCPM.interface); DevCPS.Get(sym);
440 IF sym = eql THEN DevCPS.Get(sym)
441 ELSE INCL(DevCPM.options, DevCPM.noCode)
442 END;
443 IF sym = string THEN INCL(m.flags, library); DevCPS.Get(sym)
444 ELSE err(string)
445 END;
446 CheckSym(rbrak)
447 END;
448 CheckSym(semicolon);
449 IF sym = import THEN DevCPS.Get(sym);
450 LOOP
451 IF sym = ident THEN
452 aliasName := DevCPS.name$; impName := aliasName$; DevCPS.Get(sym);
453 IF sym = becomes THEN DevCPS.Get(sym);
454 IF sym = ident THEN impName := DevCPS.name$; DevCPS.Get(sym) ELSE err(ident) END
455 END;
456 Import(m, impName)
457 ELSE err(ident)
458 END;
459 IF sym = comma THEN DevCPS.Get(sym)
460 ELSIF sym = ident THEN err(comma)
461 ELSE EXIT
462 END
463 END;
464 CheckSym(semicolon)
465 END
466 ELSE err(ident)
467 END;
468 DevCPS.str := NIL
469 END ParseModule;
471 PROCEDURE CheckModule (m: Module; source: String; OUT ok: BOOLEAN);
472 VAR s: Selector;
473 BEGIN
474 DevCPM.Init(source);
475 (*
476 DevCPM.symList := m.insym;
477 DevCPM.codePath := m.outcode;
478 DevCPM.symPath := m.outsym;
479 *)
480 DevCPM.name := m.name$;
481 (*
482 IF m.found THEN INCL(DevCPM.options, DevCPM.comAware) END;
483 IF errorTrap IN m.opts THEN INCL(DevCPM.options, DevCPM.trap) END;
484 IF oberon IN m.opts THEN INCL(DevCPM.options, DevCPM.oberon) END;
485 *)
486 DevCPR.Init;
487 s := m.selectors.next;
488 WHILE s # NIL DO
489 DevCPR.Set(s.name, s.value);
490 s := s.next
491 END;
492 ParseModule(m);
493 DevCPR.Check;
494 ok := DevCPM.noerr;
495 DevCPR.Close;
496 DevCPM.InsertMarks;
497 DevCPM.Close;
498 Kernel.FastCollect
499 END CheckModule;
501 PROCEDURE GetSource (IN modName: ARRAY OF CHAR; OUT path: Files.Name; OUT s: String);
503 VAR dir, name: Files.Name; loc: Files.Locator;
504 text: DswDocuments.Model; r: DswDocuments.Reader; i, res: INTEGER;
506 PROCEDURE MakePath (dir, name: Files.Name; type: Files.Type; OUT path: Files.Name);
507 BEGIN
511 END;
512 Kernel.MakeFileName(path, type)
513 END MakePath;
515 BEGIN
517 Kernel.SplitName(modName, dir, name);
518 loc := Files.dir.This(dir).This(modDir);
519 (* --> Kernel.MakeFileName(name, Kernel.docType); <-- *)
522 IF text = NIL THEN
527 loc := Files.dir.This(sysDir).This(modDir);
529 IF text = NIL THEN
532 IF text = NIL THEN
534 END
535 END
536 END
537 END;
538 IF text # NIL THEN
539 NEW(s, text.Length() + 1);
540 IF s # NIL THEN
541 r := text.NewReader(NIL);
542 FOR i := 0 TO text.Length() - 1 DO
543 r.Read; s[i] := r.char
544 END
545 END
546 END
547 END GetSource;
549 PROCEDURE Trace (m, parent: Module; VAR lno: INTEGER);
550 VAR i: INTEGER;
551 BEGIN
552 IF ~(trace IN m.flags) THEN
553 INCL(m.flags, trace);
554 FOR i := 0 TO m.mno - 1 DO
555 Trace(m.imp[i], m, lno);
556 m.depth := MAX(m.depth, m.imp[i].depth + 1)
557 END;
558 IF ~(imported IN m.flags) THEN
559 INCL(m.flags, imported);
560 lnkList[lno] := m;
561 INC(lno)
562 END;
563 EXCL(m.flags, trace)
564 ELSE
566 END
567 END Trace;
569 PROCEDURE Sort;
570 VAR i, j: INTEGER; m: Module;
571 BEGIN
572 ASSERT((mno = 0) OR (lnkList[0] # NIL), 20);
573 cmpList := lnkList;
574 i := 1;
575 WHILE i < mno DO
576 m := cmpList[i];
577 j := i - 1;
578 WHILE (j >= 0) & (cmpList[j].depth > m.depth) DO
579 cmpList[j + 1] := cmpList[j];
580 DEC(j)
581 END;
582 cmpList[j + 1] := m;
583 INC(i)
584 END
585 END Sort;
587 PROCEDURE CheckDeps;
588 VAR i, j, num: INTEGER; m: Module; s: String; ok: BOOLEAN;
589 BEGIN
590 i := 0; rno := mno;
591 WHILE (err = 0) & (i < mno) DO
592 m := modList[i];
593 GetSource(m.name$, m.path, s);
594 IF s # NIL THEN
595 CheckModule(m, s, ok);
596 IF ~ok THEN INC(err) END
597 ELSE
599 END;
600 INC(i)
601 END;
602 num := 0;
603 FOR i := 0 TO rno - 1 DO
604 Trace(modList[i], modList[i], num)
605 END;
606 ASSERT((err # 0) OR (num = mno), 100);
607 Sort;
608 IF debugOrder THEN
610 FOR i := 0 TO mno - 1 DO
612 END
613 END
614 END CheckDeps;
616 PROCEDURE IsCompiled (m: Module): BOOLEAN;
617 CONST target = {hasSym, hasObj};
618 VAR i: INTEGER; ready: BOOLEAN;
619 BEGIN
620 ASSERT(m # NIL, 20);
621 i := 0;
622 ready := ~(hasErrors IN m.flags) & (m.flags * target = target);
623 WHILE ready & (i < m.mno) DO
624 ready := IsCompiled(m.imp[i]);
625 INC(i)
626 END;
627 RETURN ready
628 END IsCompiled;
630 PROCEDURE Ready (m: Module): BOOLEAN;
631 CONST target = {hasSym, hasObj};
632 VAR i: INTEGER; ready: BOOLEAN;
633 BEGIN
634 i := 0;
635 ready := ~(hasErrors IN m.flags) & (m.flags * target # target) & (m.worker = NIL);
636 WHILE ready & (i < m.mno) DO
637 ready := IsCompiled(m.imp[i]);
638 INC(i)
639 END;
640 RETURN ready
641 END Ready;
643 PROCEDURE PutParams (w: DswProcs.Process; p: StringList);
644 VAR i: INTEGER;
645 BEGIN
646 ASSERT(w # NIL, 20);
648 IF p # NIL THEN
650 w.PutParam(p[0]);
651 FOR i := 1 TO LEN(p) - 1 DO
653 w.PutParam(p[i])
654 END;
656 END;
657 IF debugArgs THEN Log.Ln END
658 END PutParams;
660 PROCEDURE ExecuteCompiler (m: Module): DswProcs.Process;
661 VAR w: DswProcs.Process; ok: BOOLEAN;
662 BEGIN
663 ASSERT(m # NIL, 20);
665 ASSERT(m.worker = NIL, 22);
666 w := DswProcs.dir.New();
667 w.Program(cpcExe);
669 PutParams(w, cpcArgs);
670 w.PutParam(m.path);
671 w.Execute(ok);
672 IF ok THEN
674 ELSE
675 w := NIL
676 END;
677 RETURN w
678 END ExecuteCompiler;
680 PROCEDURE Compile;
681 VAR i, j, num: INTEGER; ok: BOOLEAN; m: Module; w: DswProcs.Process;
682 BEGIN
683 IF mno = 0 THEN RETURN END;
684 num := 0; j := 0;
685 WHILE (err = 0) & (num < mno) OR (j > 0) DO
686 i := 0;
687 WHILE (err = 0) & (i < mno) & (j < jobs) DO
688 m := cmpList[i];
689 IF Ready(m) THEN
690 w := ExecuteCompiler(m);
692 IF w # NIL THEN
694 m.worker := w;
695 INC(j)
696 ELSE
698 INCL(m.flags, hasErrors);
699 INC(err)
700 END;
701 IF debugJobs THEN Log.Ln END
702 END;
703 INC(i)
704 END;
705 WHILE (err = 0) & (j >= jobs) OR (j > 0) DO
706 i := 0;
707 WHILE (j > 0) & (i < mno) DO
708 m := cmpList[i];
709 w := m.worker;
710 IF (w # NIL) & w.IsTerminated() THEN
712 IF w.Result() = 0 THEN
713 INCL(m.flags, hasObj);
714 INCL(m.flags, hasSym);
715 INC(num)
716 ELSE
717 INCL(m.flags, hasErrors);
718 INC(err)
719 END;
720 m.worker := NIL;
721 DEC(j)
722 END;
723 INC(i)
724 END
725 END
726 END
727 END Compile;
729 PROCEDURE LinkDev2;
730 VAR p: DswProcs.Process; i, res: INTEGER; ok: BOOLEAN;
731 BEGIN
733 ASSERT(processor = mach386, 21);
734 ASSERT(compiler = cpnative, 22);
735 ASSERT(os IN {linux, freebsd, openbsd, win32}, 23);
736 p := DswProcs.dir.New();
737 p.Program(cplExe);
738 IF os # anyos THEN
740 CASE os OF
745 END
746 END;
754 p.PutParam(exe);
755 PutParams(p, cplArgs);
756 i := 0;
757 WHILE i < mno DO
758 IF ~(library IN lnkList[i].flags) THEN
759 p.PutParam(lnkList[i].name$)
760 END;
761 INC(i)
762 END;
763 p.Execute(ok);
764 IF ok THEN
766 res := p.Result();
767 IF res # 0 THEN
769 INC(err)
770 END
771 ELSE
773 INC(err)
774 END
775 END LinkDev2;
777 PROCEDURE Link;
778 BEGIN
779 IF exe # NIL THEN
780 CASE linker OF
781 | anyint: (* do not link *)
782 | dev2: LinkDev2
783 END
784 END
785 END Link;
787 PROCEDURE Main;
788 VAR m: Module; s: Selector; p: DswProcs.Process; ok: BOOLEAN; i, res: INTEGER;
789 BEGIN
790 IF Kernel.trapCount = 0 THEN
791 ParseArgs;
792 IF err = 0 THEN
793 CheckParams;
794 IF err = 0 THEN
795 CheckDeps;
796 IF err = 0 THEN
797 Compile;
798 IF err = 0 THEN
799 Link
800 END
801 END
802 END
803 END
804 ELSE INC(err)
805 END;
806 IF err = 0 THEN Kernel.Quit(0)
807 ELSE Kernel.Quit(1)
808 END;
809 END Main;
811 BEGIN
812 NEW(def);
813 Kernel.Start(Main)
814 END DswMakeMain.