libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / m2 / mc / decl.mod
blob356290b349ca49b08e7a71179178fef64309bc09
1 (* decl.mod declaration nodes used to create the AST.
3 Copyright (C) 2015-2024 Free Software Foundation, Inc.
4 Contributed by Gaius Mulley <gaius@glam.ac.uk>.
6 This file is part of GNU Modula-2.
8 GNU Modula-2 is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
13 GNU Modula-2 is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Modula-2; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. *)
22 IMPLEMENTATION MODULE decl ; (*!m2pim*)
24 FROM ASCII IMPORT lf, tab ;
25 FROM symbolKey IMPORT NulKey, symbolTree, initTree, getSymKey, putSymKey, foreachNodeDo ;
26 FROM mcDebug IMPORT assert ;
27 FROM Storage IMPORT ALLOCATE, DEALLOCATE ;
28 FROM nameKey IMPORT NulName, makeKey, lengthKey, makekey, keyToCharStar ;
29 FROM SFIO IMPORT OpenToWrite, WriteS ;
30 FROM FIO IMPORT File, Close, FlushBuffer, StdOut, WriteLine, WriteChar ;
31 FROM DynamicStrings IMPORT String, InitString, EqualArray, InitStringCharStar, KillString, ConCat, Mark, RemoveWhitePostfix, RemoveWhitePrefix ;
32 FROM StringConvert IMPORT CardinalToString, ostoc ;
34 FROM mcOptions IMPORT getOutputFile, getDebugTopological, getHPrefix, getIgnoreFQ,
35 getExtendedOpaque, writeGPLheader, getGccConfigSystem,
36 getScaffoldDynamic, getScaffoldMain, getSuppressNoReturn,
37 useBool, getCRealType, getCShortRealType,
38 getCLongRealType ;
40 FROM FormatStrings IMPORT Sprintf0, Sprintf1, Sprintf2, Sprintf3 ;
41 FROM libc IMPORT printf, memset ;
42 FROM mcMetaError IMPORT metaError1, metaError2, metaError3, metaErrors1, metaErrors2 ;
43 FROM mcError IMPORT errorAbort0, flushErrors ;
45 FROM mcLexBuf IMPORT findFileNameFromToken, tokenToLineNo, tokenToColumnNo,
46 getProcedureComment, getBodyComment, getAfterComment,
47 lastcomment ;
49 FROM mcComment IMPORT commentDesc, isProcedureComment, isAfterComment, isBodyComment, getContent, initComment, addText ;
51 FROM StrLib IMPORT StrEqual, StrLen ;
53 FROM mcPretty IMPORT pretty, initPretty, dupPretty, killPretty, print, prints, raw,
54 setNeedSpace, noSpace, setindent, getindent, getcurpos,
55 getseekpos, getcurline,
56 pushPretty, popPretty ;
58 FROM Indexing IMPORT Index, InitIndex, ForeachIndiceInIndexDo,
59 IncludeIndiceIntoIndex, IsIndiceInIndex,
60 HighIndice, LowIndice, GetIndice, RemoveIndiceFromIndex,
61 PutIndice, InBounds ;
63 IMPORT DynamicStrings ;
64 IMPORT alists, wlists ;
65 IMPORT keyc ;
66 IMPORT mcStream ;
68 FROM alists IMPORT alist ;
69 FROM wlists IMPORT wlist ;
72 CONST
73 indentation = 3 ;
74 indentationC = 2 ;
75 debugScopes = FALSE ;
76 debugDecl = FALSE ;
77 caseException = TRUE ;
78 returnException = TRUE ;
79 (* this is a work around to avoid ever having to handle dangling else. *)
80 forceCompoundStatement = TRUE ; (* TRUE will avoid dangling else, by always using {}. *)
81 enableDefForCStrings = FALSE ; (* currently disabled. *)
82 enableMemsetOnAllocation = TRUE ; (* Should we memset (..., 0, ...) the allocated mem? *)
83 forceQualified = TRUE ;
84 debugOpaque = FALSE ;
86 TYPE
87 language = (ansiC, ansiCP, pim4) ;
89 nodeT = (explist, funccall,
90 exit, return, stmtseq, comment, halt,
91 new, dispose, inc, dec, incl, excl,
92 length,
93 (* base constants. *)
94 nil, true, false,
95 (* system types. *)
96 address, loc, byte, word,
97 csizet, cssizet,
98 (* base types. *)
99 char,
100 cardinal, longcard, shortcard,
101 integer, longint, shortint,
102 real, longreal, shortreal,
103 bitset, boolean, proc,
104 ztype, rtype,
105 complex, longcomplex, shortcomplex,
106 (* language features and compound type attributes. *)
107 type, record, varient, var, enumeration,
108 subrange, array, subscript,
109 string, const, literal, varparam, param, varargs, optarg,
110 pointer, recordfield, varientfield, enumerationfield,
111 set, proctype,
112 (* blocks. *)
113 procedure, def, imp, module,
114 (* statements. *)
115 loop, while, for, repeat,
116 case, caselabellist, caselist, range,
117 assignment,
118 if, elsif,
119 (* expressions. *)
120 constexp,
121 neg,
122 cast, val,
123 plus, sub, div, mod, mult, divide, in,
124 adr, size, tsize, ord, float, trunc, chr, abs, cap,
125 high, throw, unreachable,
126 cmplx, re, im,
127 min, max,
128 componentref, pointerref, arrayref, deref,
129 equal, notequal, less, greater, greequal, lessequal,
130 lsl, lsr, lor, land, lnot, lxor,
131 and, or, not, identlist, vardecl, setvalue, opaquecast) ;
133 node = POINTER TO nodeRec ;
135 nodeRec = RECORD
136 CASE kind: nodeT OF
138 unreachable,
139 throw,
140 new,
141 dispose,
142 inc,
143 dec,
144 incl,
145 excl,
146 halt : intrinsicF: intrinsicT |
147 explist : explistF: explistT |
148 exit : exitF : exitT |
149 return : returnF : returnT |
150 stmtseq : stmtF : stmtT |
151 comment : commentF: commentT |
152 (* base constants. *)
153 nil,
154 true,
155 false,
156 (* system types. *)
157 address,
158 loc,
159 byte,
160 word,
161 csizet,
162 cssizet : |
163 (* base types. *)
164 boolean,
165 proc,
166 char,
167 integer,
168 cardinal,
169 longcard,
170 shortcard,
171 longint,
172 shortint,
173 real,
174 longreal,
175 shortreal,
176 bitset,
177 ztype,
178 rtype,
179 complex,
180 longcomplex,
181 shortcomplex : |
182 (* language features and compound type attributes. *)
183 type : typeF : typeT |
184 record : recordF : recordT |
185 varient : varientF : varientT |
186 var : varF : varT |
187 enumeration : enumerationF : enumerationT |
188 subrange : subrangeF : subrangeT |
189 subscript : subscriptF : subscriptT |
190 array : arrayF : arrayT |
191 string : stringF : stringT |
192 const : constF : constT |
193 literal : literalF : literalT |
194 varparam : varparamF : varparamT |
195 param : paramF : paramT |
196 varargs : varargsF : varargsT |
197 optarg : optargF : optargT |
198 pointer : pointerF : pointerT |
199 recordfield : recordfieldF : recordfieldT |
200 varientfield : varientfieldF : varientfieldT |
201 enumerationfield: enumerationfieldF: enumerationfieldT |
202 set : setF : setT |
203 proctype : proctypeF : proctypeT |
204 (* blocks. *)
205 procedure : procedureF : procedureT |
206 def : defF : defT |
207 imp : impF : impT |
208 module : moduleF : moduleT |
209 (* statements. *)
210 loop : loopF : loopT |
211 while : whileF : whileT |
212 for : forF : forT |
213 repeat : repeatF : repeatT |
214 case : caseF : caseT |
215 caselabellist : caselabellistF : caselabellistT |
216 caselist : caselistF : caselistT |
217 range : rangeF : rangeT |
218 if : ifF : ifT |
219 elsif : elsifF : elsifT |
220 assignment : assignmentF : assignmentT |
221 (* expressions. *)
222 arrayref : arrayrefF : arrayrefT |
223 pointerref : pointerrefF : pointerrefT |
224 componentref : componentrefF : componentrefT |
225 cmplx,
226 and,
228 equal,
229 notequal,
230 less,
231 greater,
232 greequal,
233 lessequal,
234 val,
235 cast,
236 plus,
237 sub,
238 div,
239 mod,
240 mult,
241 divide,
242 in : binaryF : binaryT |
243 constexp,
244 deref,
245 abs,
246 chr,
247 cap,
248 high,
249 ord,
250 float,
251 trunc,
254 not,
255 neg,
256 adr,
257 size,
258 tsize,
259 min,
260 max : unaryF : unaryT |
261 identlist : identlistF : identlistT |
262 vardecl : vardeclF : vardeclT |
263 funccall : funccallF : funccallT |
264 setvalue : setvalueF : setvalueT |
265 opaquecast : opaquecastF : opaquecastT
267 END ;
268 at: where ;
269 END ;
271 opaqueCastState = RECORD
272 opaque,
273 voidStar: BOOLEAN ;
274 END ;
276 opaquecastT = RECORD
277 (* Describes the cast of the opaque. *)
278 exp : node ;
279 opaqueState: opaqueCastState ;
280 END ;
282 intrinsicT = RECORD
283 args : node ;
284 noArgs : CARDINAL ;
285 type : node ;
286 intrinsicComment: commentPair ;
287 postUnreachable : BOOLEAN ;
288 END ;
290 fixupInfo = RECORD
291 count: CARDINAL ;
292 info : Index ;
293 END ;
295 explistT = RECORD
296 exp: Index ;
297 END ;
299 setvalueT = RECORD
300 type: node ;
301 values: Index ;
302 END ;
304 identlistT = RECORD
305 names : wlist ;
306 cnamed: BOOLEAN ;
307 END ;
309 funccallT = RECORD
310 function : node ;
311 args : node ;
312 type : node ;
313 funccallComment: commentPair ;
314 opaqueState : opaqueCastState ;
315 END ;
317 commentT = RECORD
318 content: commentDesc ;
319 END ;
321 stmtT = RECORD
322 statements: Index ;
323 END ;
325 returnT = RECORD
326 exp : node ;
327 scope : node ;
328 returnComment: commentPair ;
329 END ;
331 exitT = RECORD
332 loop: node ;
333 END ;
335 vardeclT = RECORD
336 names: wlist ;
337 type : node ;
338 scope: node ;
339 END ;
341 typeT = RECORD
342 name : Name ;
343 type : node ;
344 scope : node ;
345 isOpaque,
346 isHidden,
347 isInternal: BOOLEAN ;
348 END ;
350 recordT = RECORD
351 localSymbols: symbolTree ;
352 listOfSons : Index ;
353 scope : node ;
354 END ;
356 varientT = RECORD
357 listOfSons: Index ;
358 varient : node ;
359 tag : node ;
360 scope : node ;
361 END ;
363 varT = RECORD
364 name : Name ;
365 type : node ;
366 decl : node ;
367 scope : node ;
368 isInitialised,
369 isParameter,
370 isVarParameter,
371 isUsed : BOOLEAN ;
372 cname : cnameT ;
373 opaqueState : opaqueCastState ;
374 END ;
376 enumerationT = RECORD
377 noOfElements: CARDINAL ;
378 localSymbols: symbolTree ;
379 listOfSons : Index ;
380 low, high : node ;
381 scope : node ;
382 END ;
384 subrangeT = RECORD
385 low,
386 high : node ;
387 type : node ;
388 scope: node ;
389 END ;
391 subscriptT = RECORD
392 type: node ;
393 expr: node ;
394 END ;
396 arrayT = RECORD
397 subr : node ;
398 type,
399 scope : node ;
400 isUnbounded: BOOLEAN ;
401 opaqueState: opaqueCastState ;
402 END ;
404 stringT = RECORD
405 name : Name ;
406 length : CARDINAL ;
407 isCharCompatible: BOOLEAN ;
408 cstring : String ;
409 clength : CARDINAL ;
410 cchar : String ;
411 END ;
413 literalT = RECORD
414 name : Name ;
415 type : node ;
416 END ;
418 constT = RECORD
419 name : Name ;
420 type : node ;
421 value: node ;
422 scope: node ;
423 END ;
425 varparamT = RECORD
426 namelist : node ;
427 type : node ;
428 scope : node ;
429 isUnbounded: BOOLEAN ;
430 isForC : BOOLEAN ;
431 isUsed : BOOLEAN ;
432 opaqueState: opaqueCastState ;
433 END ;
435 paramT = RECORD
436 namelist : node ;
437 type : node ;
438 scope : node ;
439 isUnbounded: BOOLEAN ;
440 isForC : BOOLEAN ;
441 isUsed : BOOLEAN ;
442 opaqueState: opaqueCastState ;
443 END ;
445 varargsT = RECORD
446 scope : node ;
447 END ;
449 optargT = RECORD
450 namelist : node ;
451 type : node ;
452 scope : node ;
453 init : node ;
454 END ;
456 pointerT = RECORD
457 type : node ;
458 scope : node ;
459 opaqueState: opaqueCastState ;
460 END ;
462 recordfieldT = RECORD
463 name : Name ;
464 type : node ;
465 tag : BOOLEAN ;
466 parent : node ;
467 varient : node ;
468 scope : node ;
469 cname : cnameT ;
470 opaqueState: opaqueCastState ;
471 END ;
473 varientfieldT = RECORD
474 name : Name ;
475 parent : node ;
476 varient : node ;
477 simple : BOOLEAN ;
478 listOfSons: Index ;
479 scope : node ;
480 END ;
482 enumerationfieldT = RECORD
483 name : Name ;
484 type : node ;
485 scope: node ;
486 value: CARDINAL ;
487 cname: cnameT ;
488 END ;
490 setT = RECORD
491 type : node ;
492 scope: node ;
493 END ;
495 componentrefT = RECORD
496 rec : node ;
497 field : node ;
498 resultType : node ;
499 opaqueState: opaqueCastState ;
500 END ;
502 pointerrefT = RECORD
503 ptr : node ;
504 field : node ;
505 resultType : node ;
506 opaqueState: opaqueCastState ;
507 END ;
509 arrayrefT = RECORD
510 array : node ;
511 index : node ;
512 resultType : node ;
513 opaqueState: opaqueCastState ;
514 END ;
516 commentPair = RECORD
517 after,
518 body : node ;
519 END ;
521 assignmentT = RECORD
522 des,
523 expr : node ;
524 assignComment: commentPair ;
525 END ;
527 ifT = RECORD
528 expr,
529 elsif, (* either else or elsif must be NIL. *)
530 then,
531 else : node ;
532 ifComment,
533 elseComment, (* used for else or elsif *)
534 endComment : commentPair ;
535 END ;
537 elsifT = RECORD
538 expr,
539 elsif, (* either else or elsif must be NIL. *)
540 then,
541 else : node ;
542 elseComment: commentPair ; (* used for else or elsif *)
543 END ;
545 loopT = RECORD
546 statements: node ;
547 labelno : CARDINAL ; (* 0 means no label. *)
548 END ;
550 whileT = RECORD
551 expr,
552 statements: node ;
553 doComment,
554 endComment: commentPair ;
555 END ;
557 repeatT = RECORD
558 expr,
559 statements : node ;
560 repeatComment,
561 untilComment : commentPair ;
562 END ;
564 caseT = RECORD
565 expression : node ;
566 caseLabelList: Index ;
567 else : node ;
568 END ;
570 caselabellistT = RECORD
571 caseList : node ;
572 statements: node ;
573 END ;
575 caselistT = RECORD
576 rangePairs: Index ;
577 END ;
579 rangeT = RECORD
581 hi: node ;
582 END ;
584 forT = RECORD
585 des,
586 start,
587 end,
588 increment,
589 statements: node ;
590 END ;
592 statementT = RECORD
593 sequence: Index ;
594 END ;
596 scopeT = RECORD
597 symbols : symbolTree ;
598 constants,
599 types,
600 procedures,
601 variables : Index ;
602 END ;
604 procedureT = RECORD
605 name : Name ;
606 decls : scopeT ;
607 scope : node ;
608 parameters : Index ;
609 isForC,
610 built,
611 checking,
612 returnopt,
613 vararg,
614 noreturnused,
615 noreturn : BOOLEAN ;
616 paramcount : CARDINAL ;
617 optarg : node ;
618 returnType : node ;
619 beginStatements: node ;
620 cname : cnameT ;
621 defComment,
622 modComment : commentDesc ;
623 opaqueState : opaqueCastState ;
624 END ;
626 proctypeT = RECORD
627 parameters : Index ;
628 returnopt,
629 vararg : BOOLEAN ;
630 optarg : node ;
631 scope : node ;
632 returnType : node ;
633 opaqueState: opaqueCastState ;
634 END ;
636 binaryT = RECORD
637 left,
638 right,
639 resultType: node ;
640 END ;
642 unaryT = RECORD
643 arg,
644 resultType: node ;
645 END ;
647 moduleT = RECORD
648 name : Name ;
649 source : Name ;
650 importedModules : Index ;
651 constFixup,
652 enumFixup : fixupInfo ;
653 decls : scopeT ;
654 beginStatements,
655 finallyStatements: node ;
656 enumsComplete,
657 constsComplete,
658 visited : BOOLEAN ;
659 com : commentPair ;
660 END ;
662 defT = RECORD
663 name : Name ;
664 source : Name ;
665 unqualified,
666 hasHidden,
667 forC : BOOLEAN ;
668 exported,
669 importedModules : Index ;
670 constFixup,
671 enumFixup : fixupInfo ;
672 decls : scopeT ;
673 enumsComplete,
674 constsComplete,
675 visited : BOOLEAN ;
676 com : commentPair ;
677 END ;
679 impT = RECORD
680 name : Name ;
681 source : Name ;
682 importedModules : Index ;
683 constFixup,
684 enumFixup : fixupInfo ;
685 beginStatements,
686 finallyStatements: node ;
687 definitionModule : node ;
688 decls : scopeT ;
689 enumsComplete,
690 constsComplete,
691 visited : BOOLEAN ;
692 com : commentPair ;
693 END ;
695 where = RECORD
696 defDeclared,
697 modDeclared,
698 firstUsed : CARDINAL ;
699 END ;
701 outputStates = (text, punct, space) ;
703 nodeProcedure = PROCEDURE (node) ;
705 dependentState = (completed, blocked, partial, recursive) ;
707 cnameT = RECORD
708 name : Name ;
709 init : BOOLEAN ;
710 END ;
712 group = POINTER TO RECORD
713 todoQ,
714 partialQ,
715 doneQ : alist ;
716 next : group ;
717 END ;
721 freeGroup,
722 globalGroup : group ; (* The global group of all alists. *)
723 outputFile : File ;
724 lang : language ;
725 charStarN,
726 constCharStarN,
727 bitsperunitN,
728 bitsperwordN,
729 bitspercharN,
730 unitsperwordN,
731 mainModule,
732 currentModule,
733 defModule,
734 systemN,
735 addressN,
736 locN,
737 byteN,
738 wordN,
739 csizetN,
740 cssizetN,
741 adrN,
742 sizeN,
743 tsizeN,
744 newN,
745 disposeN,
746 lengthN,
747 incN,
748 decN,
749 inclN,
750 exclN,
751 highN,
752 m2rtsN,
753 haltN,
754 throwN,
755 chrN,
756 capN,
757 absN,
758 floatN,
759 truncN,
760 ordN,
761 valN,
762 minN,
763 maxN,
764 booleanN,
765 procN,
766 charN,
767 integerN,
768 cardinalN,
769 longcardN,
770 shortcardN,
771 longintN,
772 shortintN,
773 bitsetN,
774 bitnumN,
775 ztypeN,
776 rtypeN,
777 complexN,
778 longcomplexN,
779 shortcomplexN,
780 cmplxN,
781 reN,
782 imN,
783 realN,
784 longrealN,
785 shortrealN,
786 nilN,
787 trueN,
788 falseN : node ;
789 scopeStack,
790 defUniverseI,
791 modUniverseI : Index ;
792 modUniverse,
793 defUniverse : symbolTree ;
794 baseSymbols : symbolTree ;
795 outputState : outputStates ;
796 doP : pretty ;
797 mustVisitScope,
798 simplified : BOOLEAN ;
799 tempCount : CARDINAL ;
803 newNode - create and return a new node of kind k.
806 PROCEDURE newNode (k: nodeT) : node ;
808 d: node ;
809 BEGIN
810 NEW (d) ;
811 IF enableMemsetOnAllocation
812 THEN
813 d := memset (d, 0, SIZE (d^))
814 END ;
815 IF d=NIL
816 THEN
817 HALT
818 ELSE
819 d^.kind := k ;
820 d^.at.defDeclared := 0 ;
821 d^.at.modDeclared := 0 ;
822 d^.at.firstUsed := 0 ;
823 RETURN d
825 END newNode ;
829 disposeNode - dispose node, n.
832 PROCEDURE disposeNode (VAR n: node) ;
833 BEGIN
834 DISPOSE (n) ;
835 n := NIL
836 END disposeNode ;
840 newGroup -
843 PROCEDURE newGroup (VAR g: group) ;
844 BEGIN
845 IF freeGroup = NIL
846 THEN
847 NEW (g)
848 ELSE
849 g := freeGroup ;
850 freeGroup := freeGroup^.next
852 END newGroup ;
856 initGroup - returns a group which with all lists initialized.
859 PROCEDURE initGroup () : group ;
861 g: group ;
862 BEGIN
863 newGroup (g) ;
864 WITH g^ DO
865 todoQ := alists.initList () ;
866 partialQ := alists.initList () ;
867 doneQ := alists.initList () ;
868 next := NIL
869 END ;
870 RETURN g
871 END initGroup ;
875 killGroup - deallocate the group and place the group record into the freeGroup list.
878 PROCEDURE killGroup (VAR g: group) ;
879 BEGIN
880 alists.killList (g^.todoQ) ;
881 alists.killList (g^.partialQ) ;
882 alists.killList (g^.doneQ) ;
883 g^.next := freeGroup ;
884 freeGroup := g ;
885 END killGroup ;
889 dupGroup - If g is not NIL then destroy g.
890 Return a duplicate of GlobalGroup (not g).
893 PROCEDURE dupGroup (g: group) : group ;
894 BEGIN
895 IF g # NIL
896 THEN
897 (* Kill old group. *)
898 killGroup (g)
899 END ;
900 newGroup (g) ;
901 WITH g^ DO
902 (* Copy all lists. *)
903 todoQ := alists.duplicateList (globalGroup^.todoQ) ;
904 partialQ := alists.duplicateList (globalGroup^.partialQ) ;
905 doneQ := alists.duplicateList (globalGroup^.doneQ) ;
906 next := NIL
907 END ;
908 RETURN g
909 END dupGroup ;
913 equalGroup - return TRUE if group left = right.
916 PROCEDURE equalGroup (left, right: group) : BOOLEAN ;
917 BEGIN
918 RETURN ((left = right) OR
919 (alists.equalList (left^.todoQ, right^.todoQ) AND
920 alists.equalList (left^.partialQ, right^.partialQ) AND
921 alists.equalList (left^.doneQ, right^.doneQ)))
922 END equalGroup ;
926 getDeclaredDef - returns the token number associated with the nodes declaration
927 in the definition module.
930 PROCEDURE getDeclaredDef (n: node) : CARDINAL ;
931 BEGIN
932 RETURN n^.at.defDeclared
933 END getDeclaredDef ;
937 getDeclaredMod - returns the token number associated with the nodes declaration
938 in the implementation or program module.
941 PROCEDURE getDeclaredMod (n: node) : CARDINAL ;
942 BEGIN
943 RETURN n^.at.modDeclared
944 END getDeclaredMod ;
948 getFirstUsed - returns the token number associated with the first use of
949 node, n.
952 PROCEDURE getFirstUsed (n: node) : CARDINAL ;
953 BEGIN
954 RETURN n^.at.firstUsed
955 END getFirstUsed ;
959 setVisited - set the visited flag on a def/imp/module node.
962 PROCEDURE setVisited (n: node) ;
963 BEGIN
964 CASE n^.kind OF
966 def : n^.defF.visited := TRUE |
967 imp : n^.impF.visited := TRUE |
968 module: n^.moduleF.visited := TRUE
971 END setVisited ;
975 unsetVisited - unset the visited flag on a def/imp/module node.
978 PROCEDURE unsetVisited (n: node) ;
979 BEGIN
980 CASE n^.kind OF
982 def : n^.defF.visited := FALSE |
983 imp : n^.impF.visited := FALSE |
984 module: n^.moduleF.visited := FALSE
987 END unsetVisited ;
991 isVisited - returns TRUE if the node was visited.
994 PROCEDURE isVisited (n: node) : BOOLEAN ;
995 BEGIN
996 CASE n^.kind OF
998 def : RETURN n^.defF.visited |
999 imp : RETURN n^.impF.visited |
1000 module: RETURN n^.moduleF.visited
1003 END isVisited ;
1007 isDef - return TRUE if node, n, is a definition module.
1010 PROCEDURE isDef (n: node) : BOOLEAN ;
1011 BEGIN
1012 assert (n#NIL) ;
1013 RETURN n^.kind = def
1014 END isDef ;
1018 isImp - return TRUE if node, n, is an implementation module.
1021 PROCEDURE isImp (n: node) : BOOLEAN ;
1022 BEGIN
1023 assert (n#NIL) ;
1024 RETURN n^.kind = imp
1025 END isImp ;
1029 isModule - return TRUE if node, n, is a program module.
1032 PROCEDURE isModule (n: node) : BOOLEAN ;
1033 BEGIN
1034 assert (n#NIL) ;
1035 RETURN n^.kind = module
1036 END isModule ;
1040 isImpOrModule - returns TRUE if, n, is a program module or implementation module.
1043 PROCEDURE isImpOrModule (n: node) : BOOLEAN ;
1044 BEGIN
1045 RETURN isImp (n) OR isModule (n)
1046 END isImpOrModule ;
1050 isProcedure - returns TRUE if node, n, is a procedure.
1053 PROCEDURE isProcedure (n: node) : BOOLEAN ;
1054 BEGIN
1055 assert (n#NIL) ;
1056 RETURN n^.kind = procedure
1057 END isProcedure ;
1061 isConst - returns TRUE if node, n, is a const.
1064 PROCEDURE isConst (n: node) : BOOLEAN ;
1065 BEGIN
1066 assert (n#NIL) ;
1067 RETURN n^.kind = const
1068 END isConst ;
1072 isType - returns TRUE if node, n, is a type.
1075 PROCEDURE isType (n: node) : BOOLEAN ;
1076 BEGIN
1077 assert (n#NIL) ;
1078 RETURN n^.kind = type
1079 END isType ;
1083 isVar - returns TRUE if node, n, is a type.
1086 PROCEDURE isVar (n: node) : BOOLEAN ;
1087 BEGIN
1088 assert (n#NIL) ;
1089 RETURN n^.kind = var
1090 END isVar ;
1094 isTemporary - returns TRUE if node, n, is a variable and temporary.
1097 PROCEDURE isTemporary (n: node) : BOOLEAN ;
1098 BEGIN
1099 RETURN FALSE
1100 END isTemporary ;
1104 isExported - returns TRUE if symbol, n, is exported from
1105 the definition module.
1108 PROCEDURE isExported (n: node) : BOOLEAN ;
1110 s: node ;
1111 BEGIN
1112 s := getScope (n) ;
1113 IF s#NIL
1114 THEN
1115 CASE s^.kind OF
1117 def: RETURN IsIndiceInIndex (s^.defF.exported, n)
1119 ELSE
1120 RETURN FALSE
1122 END ;
1123 RETURN FALSE
1124 END isExported ;
1128 isLocal - returns TRUE if symbol, n, is locally declared in a procedure.
1131 PROCEDURE isLocal (n: node) : BOOLEAN ;
1133 s: node ;
1134 BEGIN
1135 s := getScope (n) ;
1136 IF s#NIL
1137 THEN
1138 RETURN isProcedure (s)
1139 END ;
1140 RETURN FALSE
1141 END isLocal ;
1145 lookupExported - attempts to lookup a node named, i, from definition
1146 module, n. The node is returned if found.
1147 NIL is returned if not found.
1150 PROCEDURE lookupExported (n: node; i: Name) : node ;
1152 r: node ;
1153 BEGIN
1154 assert (isDef (n)) ;
1155 r := getSymKey (n^.defF.decls.symbols, i) ;
1156 IF (r#NIL) AND isExported (r)
1157 THEN
1158 RETURN r
1159 END ;
1160 RETURN NIL
1161 END lookupExported ;
1165 importEnumFields - if, n, is an enumeration type import the all fields into module, m.
1168 PROCEDURE importEnumFields (m, n: node) ;
1170 r, e: node ;
1171 i, h: CARDINAL ;
1172 BEGIN
1173 assert (isDef (m) OR isModule (m) OR isImp (m)) ;
1174 n := skipType (n) ;
1175 IF (n#NIL) AND isEnumeration (n)
1176 THEN
1177 i := LowIndice (n^.enumerationF.listOfSons) ;
1178 h := HighIndice (n^.enumerationF.listOfSons) ;
1179 WHILE i<=h DO
1180 e := GetIndice (n^.enumerationF.listOfSons, i) ;
1181 r := import (m, e) ;
1182 IF e#r
1183 THEN
1184 metaError2 ('enumeration field {%1ad} cannot be imported implicitly into {%2d} due to a name clash',
1185 e, m)
1186 END ;
1187 INC (i)
1190 END importEnumFields ;
1194 checkGccType - check to see if node n is gcc tree or location_t
1195 and record its use in keyc.
1198 PROCEDURE checkGccType (n: node) ;
1199 BEGIN
1200 IF getGccConfigSystem () AND (getScope (n) # NIL) AND
1201 (getSymName (getScope (n)) = makeKey ('gcctypes'))
1202 THEN
1203 IF getSymName (n) = makeKey ('location_t')
1204 THEN
1205 keyc.useGccLocation
1206 ELSIF getSymName (n) = makeKey ('tree')
1207 THEN
1208 keyc.useGccTree
1211 END checkGccType ;
1215 checkCDataTypes - check to see if node n is CharStar or ConstCharStar
1216 and if necessary assign n to the global variable.
1219 PROCEDURE checkCDataTypes (n: node) ;
1220 BEGIN
1221 IF (getScope (n) # NIL) AND (getSymName (getScope (n)) = makeKey ('CDataTypes'))
1222 THEN
1223 IF getSymName (n) = makeKey ('CharStar')
1224 THEN
1225 charStarN := n
1226 ELSIF getSymName (n) = makeKey ('ConstCharStar')
1227 THEN
1228 constCharStarN := n
1231 END checkCDataTypes ;
1235 import - attempts to add node, n, into the scope of module, m.
1236 It might fail due to a name clash in which case the
1237 previous named symbol is returned. On success, n,
1238 is returned.
1241 PROCEDURE import (m, n: node) : node ;
1243 name: Name ;
1244 r : node ;
1245 BEGIN
1246 assert (isDef (m) OR isModule (m) OR isImp (m)) ;
1247 name := getSymName (n) ;
1248 checkGccType (n) ;
1249 checkCDataTypes (n) ;
1250 r := lookupInScope (m, name) ;
1251 IF r=NIL
1252 THEN
1253 CASE m^.kind OF
1255 def : putSymKey (m^.defF.decls.symbols, name, n) |
1256 imp : putSymKey (m^.impF.decls.symbols, name, n) |
1257 module: putSymKey (m^.moduleF.decls.symbols, name, n)
1259 END ;
1260 importEnumFields (m, n) ;
1261 RETURN n
1262 END ;
1263 RETURN r
1264 END import ;
1268 isZtype - returns TRUE if, n, is the Z type.
1271 PROCEDURE isZtype (n: node) : BOOLEAN ;
1272 BEGIN
1273 RETURN n = ztypeN
1274 END isZtype ;
1278 isRtype - returns TRUE if, n, is the R type.
1281 PROCEDURE isRtype (n: node) : BOOLEAN ;
1282 BEGIN
1283 RETURN n = rtypeN
1284 END isRtype ;
1288 isComplex - returns TRUE if, n, is the complex type.
1291 PROCEDURE isComplex (n: node) : BOOLEAN ;
1292 BEGIN
1293 RETURN n = complexN
1294 END isComplex ;
1298 isLongComplex - returns TRUE if, n, is the longcomplex type.
1301 PROCEDURE isLongComplex (n: node) : BOOLEAN ;
1302 BEGIN
1303 RETURN n = longcomplexN
1304 END isLongComplex ;
1308 isShortComplex - returns TRUE if, n, is the shortcomplex type.
1311 PROCEDURE isShortComplex (n: node) : BOOLEAN ;
1312 BEGIN
1313 RETURN n = shortcomplexN
1314 END isShortComplex ;
1318 isLiteral - returns TRUE if, n, is a literal.
1321 PROCEDURE isLiteral (n: node) : BOOLEAN ;
1322 BEGIN
1323 assert (n # NIL) ;
1324 RETURN n^.kind = literal
1325 END isLiteral ;
1329 isConstSet - returns TRUE if, n, is a constant set.
1332 PROCEDURE isConstSet (n: node) : BOOLEAN ;
1333 BEGIN
1334 assert (n # NIL) ;
1335 IF isLiteral (n) OR isConst (n)
1336 THEN
1337 RETURN isSet (skipType (getType (n)))
1338 END ;
1339 RETURN FALSE
1340 END isConstSet ;
1344 isEnumerationField - returns TRUE if, n, is an enumeration field.
1347 PROCEDURE isEnumerationField (n: node) : BOOLEAN ;
1348 BEGIN
1349 assert (n # NIL) ;
1350 RETURN n^.kind = enumerationfield
1351 END isEnumerationField ;
1355 isUnbounded - returns TRUE if, n, is an unbounded array.
1358 PROCEDURE isUnbounded (n: node) : BOOLEAN ;
1359 BEGIN
1360 assert (n # NIL) ;
1361 RETURN (n^.kind = array) AND (n^.arrayF.isUnbounded)
1362 END isUnbounded ;
1366 isParameter - returns TRUE if, n, is a parameter.
1369 PROCEDURE isParameter (n: node) : BOOLEAN ;
1370 BEGIN
1371 assert (n # NIL) ;
1372 RETURN (n^.kind = param) OR (n^.kind = varparam)
1373 END isParameter ;
1377 isVarParam - returns TRUE if, n, is a var parameter.
1380 PROCEDURE isVarParam (n: node) : BOOLEAN ;
1381 BEGIN
1382 assert (n # NIL) ;
1383 RETURN n^.kind = varparam
1384 END isVarParam ;
1388 isParam - returns TRUE if, n, is a non var parameter.
1391 PROCEDURE isParam (n: node) : BOOLEAN ;
1392 BEGIN
1393 assert (n # NIL) ;
1394 RETURN n^.kind = param
1395 END isParam ;
1399 isNonVarParam - is an alias to isParam.
1402 PROCEDURE isNonVarParam (n: node) : BOOLEAN ;
1403 BEGIN
1404 RETURN isParam (n)
1405 END isNonVarParam ;
1409 isRecord - returns TRUE if, n, is a record.
1412 PROCEDURE isRecord (n: node) : BOOLEAN ;
1413 BEGIN
1414 assert (n # NIL) ;
1415 RETURN n^.kind = record
1416 END isRecord ;
1420 isRecordField - returns TRUE if, n, is a record field.
1423 PROCEDURE isRecordField (n: node) : BOOLEAN ;
1424 BEGIN
1425 assert (n # NIL) ;
1426 RETURN n^.kind = recordfield
1427 END isRecordField ;
1431 isArray - returns TRUE if, n, is an array.
1434 PROCEDURE isArray (n: node) : BOOLEAN ;
1435 BEGIN
1436 assert (n # NIL) ;
1437 RETURN n^.kind = array
1438 END isArray ;
1442 isProcType - returns TRUE if, n, is a procedure type.
1445 PROCEDURE isProcType (n: node) : BOOLEAN ;
1446 BEGIN
1447 assert (n # NIL) ;
1448 RETURN n^.kind = proctype
1449 END isProcType ;
1453 isAProcType - returns TRUE if, n, is a proctype or proc node.
1456 PROCEDURE isAProcType (n: node) : BOOLEAN ;
1457 BEGIN
1458 assert (n # NIL) ;
1459 RETURN isProcType (n) OR (n = procN)
1460 END isAProcType ;
1464 isProcedure - returns TRUE if, n, is a procedure.
1467 PROCEDURE isProcedure (n: node) : BOOLEAN ;
1468 BEGIN
1469 assert (n # NIL) ;
1470 RETURN n^.kind = procedure
1471 END isProcedure ;
1475 isPointer - returns TRUE if, n, is a pointer.
1478 PROCEDURE isPointer (n: node) : BOOLEAN ;
1479 BEGIN
1480 assert (n # NIL) ;
1481 RETURN n^.kind = pointer
1482 END isPointer ;
1486 isVarient - returns TRUE if, n, is a varient record.
1489 PROCEDURE isVarient (n: node) : BOOLEAN ;
1490 BEGIN
1491 assert (n # NIL) ;
1492 RETURN n^.kind = varient
1493 END isVarient ;
1497 isVarientField - returns TRUE if, n, is a varient field.
1500 PROCEDURE isVarientField (n: node) : BOOLEAN ;
1501 BEGIN
1502 assert (n # NIL) ;
1503 RETURN n^.kind = varientfield
1504 END isVarientField ;
1508 isSet - returns TRUE if, n, is a set type.
1511 PROCEDURE isSet (n: node) : BOOLEAN ;
1512 BEGIN
1513 assert (n # NIL) ;
1514 RETURN n^.kind = set
1515 END isSet ;
1519 isSubrange - returns TRUE if, n, is a subrange type.
1522 PROCEDURE isSubrange (n: node) : BOOLEAN ;
1523 BEGIN
1524 assert (n # NIL) ;
1525 RETURN n^.kind = subrange
1526 END isSubrange ;
1530 isMainModule - return TRUE if node, n, is the main module specified
1531 by the source file. This might be a definition,
1532 implementation or program module.
1535 PROCEDURE isMainModule (n: node) : BOOLEAN ;
1536 BEGIN
1537 assert (n#NIL) ;
1538 RETURN n = mainModule
1539 END isMainModule ;
1543 setMainModule - sets node, n, as the main module to be compiled.
1546 PROCEDURE setMainModule (n: node) ;
1547 BEGIN
1548 assert (n#NIL) ;
1549 mainModule := n
1550 END setMainModule ;
1554 getMainModule - returns the main module node.
1557 PROCEDURE getMainModule () : node ;
1558 BEGIN
1559 RETURN mainModule
1560 END getMainModule ;
1564 setCurrentModule - sets node, n, as the current module being compiled.
1567 PROCEDURE setCurrentModule (n: node) ;
1568 BEGIN
1569 assert (n#NIL) ;
1570 currentModule := n
1571 END setCurrentModule ;
1575 getCurrentModule - returns the current module being compiled.
1578 PROCEDURE getCurrentModule () : node ;
1579 BEGIN
1580 RETURN currentModule
1581 END getCurrentModule ;
1585 initFixupInfo - initialize the fixupInfo record.
1588 PROCEDURE initFixupInfo () : fixupInfo ;
1590 f: fixupInfo ;
1591 BEGIN
1592 f.count := 0 ;
1593 f.info := InitIndex (1) ;
1594 RETURN f
1595 END initFixupInfo ;
1599 makeDef - returns a definition module node named, n.
1602 PROCEDURE makeDef (n: Name) : node ;
1604 d: node ;
1605 BEGIN
1606 d := newNode (def) ;
1607 WITH d^ DO
1608 defF.name := n ;
1609 defF.source := NulName ;
1610 defF.hasHidden := FALSE ;
1611 defF.forC := FALSE ;
1612 defF.unqualified := FALSE ;
1613 defF.exported := InitIndex (1) ;
1614 defF.importedModules := InitIndex (1) ;
1615 defF.constFixup := initFixupInfo () ;
1616 defF.enumFixup := initFixupInfo () ;
1617 initDecls (defF.decls) ;
1618 defF.enumsComplete := FALSE ;
1619 defF.constsComplete := FALSE ;
1620 defF.visited := FALSE ;
1621 initPair (defF.com)
1622 END ;
1623 RETURN d
1624 END makeDef ;
1628 makeImp - returns an implementation module node named, n.
1631 PROCEDURE makeImp (n: Name) : node ;
1633 d: node ;
1634 BEGIN
1635 d := newNode (imp) ;
1636 WITH d^ DO
1637 impF.name := n ;
1638 impF.source := NulName ;
1639 impF.importedModules := InitIndex (1) ;
1640 impF.constFixup := initFixupInfo () ;
1641 impF.enumFixup := initFixupInfo () ;
1642 initDecls (impF.decls) ;
1643 impF.beginStatements := NIL ;
1644 impF.finallyStatements := NIL ;
1645 impF.definitionModule := NIL ;
1646 impF.enumsComplete := FALSE ;
1647 impF.constsComplete := FALSE ;
1648 impF.visited := FALSE ;
1649 initPair (impF.com)
1650 END ;
1651 RETURN d
1652 END makeImp ;
1656 makeModule - returns a module node named, n.
1659 PROCEDURE makeModule (n: Name) : node ;
1661 d: node ;
1662 BEGIN
1663 d := newNode (module) ;
1664 WITH d^ DO
1665 moduleF.name := n ;
1666 moduleF.source := NulName ;
1667 moduleF.importedModules := InitIndex (1) ;
1668 moduleF.constFixup := initFixupInfo () ;
1669 moduleF.enumFixup := initFixupInfo () ;
1670 initDecls (moduleF.decls) ;
1671 moduleF.beginStatements := NIL ;
1672 moduleF.finallyStatements := NIL ;
1673 moduleF.enumsComplete := FALSE ;
1674 moduleF.constsComplete := FALSE ;
1675 moduleF.visited := FALSE ;
1676 initPair (moduleF.com)
1677 END ;
1678 RETURN d
1679 END makeModule ;
1683 putDefForC - the definition module was defined FOR "C".
1686 PROCEDURE putDefForC (n: node) ;
1687 BEGIN
1688 assert (isDef (n)) ;
1689 n^.defF.forC := TRUE
1690 END putDefForC ;
1694 isDefForC - returns TRUE if the definition module was defined FOR "C".
1697 PROCEDURE isDefForC (n: node) : BOOLEAN ;
1698 BEGIN
1699 RETURN isDef (n) AND n^.defF.forC
1700 END isDefForC ;
1704 putDefUnqualified - the definition module uses unqualified.
1707 PROCEDURE putDefUnqualified (n: node) ;
1708 BEGIN
1709 assert (isDef (n)) ;
1710 (* Currently (and this is a temporary development restriction to
1711 reduce any search space for bugs) the only module which can be
1712 export unqualified is gcctypes. *)
1713 IF n^.defF.name = makeKey ('gcctypes')
1714 THEN
1715 n^.defF.unqualified := TRUE
1717 END putDefUnqualified ;
1721 isDefUnqualified - returns TRUE if the definition module uses unqualified.
1724 PROCEDURE isDefUnqualified (n: node) : BOOLEAN ;
1725 BEGIN
1726 RETURN isDef (n) AND n^.defF.unqualified
1727 END isDefUnqualified ;
1731 lookupDef - returns a definition module node named, n.
1734 PROCEDURE lookupDef (n: Name) : node ;
1736 d: node ;
1737 BEGIN
1738 d := getSymKey (defUniverse, n) ;
1739 IF d=NIL
1740 THEN
1741 d := makeDef (n) ;
1742 putSymKey (defUniverse, n, d) ;
1743 IncludeIndiceIntoIndex (defUniverseI, d)
1744 END ;
1745 RETURN d
1746 END lookupDef ;
1750 lookupImp - returns an implementation module node named, n.
1753 PROCEDURE lookupImp (n: Name) : node ;
1755 m: node ;
1756 BEGIN
1757 m := getSymKey (modUniverse, n) ;
1758 IF m=NIL
1759 THEN
1760 m := makeImp (n) ;
1761 putSymKey (modUniverse, n, m) ;
1762 IncludeIndiceIntoIndex (modUniverseI, m)
1763 END ;
1764 assert (NOT isModule (m)) ;
1765 RETURN m
1766 END lookupImp ;
1770 lookupModule - returns a module node named, n.
1773 PROCEDURE lookupModule (n: Name) : node ;
1775 m: node ;
1776 BEGIN
1777 m := getSymKey (modUniverse, n) ;
1778 IF m=NIL
1779 THEN
1780 m := makeModule (n) ;
1781 putSymKey (modUniverse, n, m) ;
1782 IncludeIndiceIntoIndex (modUniverseI, m)
1783 END ;
1784 assert (NOT isImp (m)) ;
1785 RETURN m
1786 END lookupModule ;
1790 setSource - sets the source filename for module, n, to s.
1793 PROCEDURE setSource (n: node; s: Name) ;
1794 BEGIN
1795 WITH n^ DO
1796 CASE kind OF
1798 def : defF.source := s |
1799 module: moduleF.source := s |
1800 imp : impF.source := s
1804 END setSource ;
1808 getSource - returns the source filename for module, n.
1811 PROCEDURE getSource (n: node) : Name ;
1812 BEGIN
1813 WITH n^ DO
1814 CASE kind OF
1816 def : RETURN defF.source |
1817 module: RETURN moduleF.source |
1818 imp : RETURN impF.source
1822 END getSource ;
1826 initDecls - initialize the decls, scopeT.
1829 PROCEDURE initDecls (VAR decls: scopeT) ;
1830 BEGIN
1831 decls.symbols := initTree () ;
1832 decls.constants := InitIndex (1) ;
1833 decls.types := InitIndex (1) ;
1834 decls.procedures := InitIndex (1) ;
1835 decls.variables := InitIndex (1)
1836 END initDecls ;
1840 enterScope - pushes symbol, n, to the scope stack.
1843 PROCEDURE enterScope (n: node) ;
1844 BEGIN
1845 IF IsIndiceInIndex (scopeStack, n)
1846 THEN
1847 HALT
1848 ELSE
1849 IncludeIndiceIntoIndex (scopeStack, n)
1850 END ;
1851 IF debugScopes
1852 THEN
1853 printf ("enter scope\n") ;
1854 dumpScopes
1856 END enterScope ;
1860 leaveScope - removes the top level scope.
1863 PROCEDURE leaveScope ;
1865 i: CARDINAL ;
1866 n: node ;
1867 BEGIN
1868 i := HighIndice (scopeStack) ;
1869 n := GetIndice (scopeStack, i) ;
1870 RemoveIndiceFromIndex (scopeStack, n) ;
1871 IF debugScopes
1872 THEN
1873 printf ("leave scope\n") ;
1874 dumpScopes
1876 END leaveScope ;
1880 getDeclScope - returns the node representing the
1881 current declaration scope.
1884 PROCEDURE getDeclScope () : node ;
1886 i: CARDINAL ;
1887 BEGIN
1888 i := HighIndice (scopeStack) ;
1889 RETURN GetIndice (scopeStack, i)
1890 END getDeclScope ;
1894 addTo - adds node, d, to scope decls and returns, d.
1895 It stores, d, in the symbols tree associated with decls.
1898 PROCEDURE addTo (VAR decls: scopeT; d: node) : node ;
1900 n: Name ;
1901 BEGIN
1902 n := getSymName (d) ;
1903 IF n#NulName
1904 THEN
1905 IF getSymKey (decls.symbols, n)=NIL
1906 THEN
1907 putSymKey (decls.symbols, n, d)
1908 ELSE
1909 metaError1 ('{%1DMad} was declared', d) ;
1910 metaError1 ('{%1k} and is being declared again', n)
1912 END ;
1913 IF isConst (d)
1914 THEN
1915 IncludeIndiceIntoIndex (decls.constants, d)
1916 ELSIF isVar (d)
1917 THEN
1918 IncludeIndiceIntoIndex (decls.variables, d)
1919 ELSIF isType (d)
1920 THEN
1921 IncludeIndiceIntoIndex (decls.types, d)
1922 ELSIF isProcedure (d)
1923 THEN
1924 IncludeIndiceIntoIndex (decls.procedures, d) ;
1925 IF debugDecl
1926 THEN
1927 printf ("%d procedures on the dynamic array\n",
1928 HighIndice (decls.procedures))
1930 END ;
1931 RETURN d
1932 END addTo ;
1936 export - export node, n, from definition module, d.
1939 PROCEDURE export (d, n: node) ;
1940 BEGIN
1941 assert (isDef (d)) ;
1942 IncludeIndiceIntoIndex (d^.defF.exported, n)
1943 END export ;
1947 addToScope - adds node, n, to the current scope and returns, n.
1950 PROCEDURE addToScope (n: node) : node ;
1952 s: node ;
1953 i: CARDINAL ;
1954 BEGIN
1955 i := HighIndice (scopeStack) ;
1956 s := GetIndice (scopeStack, i) ;
1957 IF isProcedure (s)
1958 THEN
1959 IF debugDecl
1960 THEN
1961 outText (doP, "adding ") ;
1962 doNameC (doP, n) ;
1963 outText (doP, " to procedure\n")
1964 END ;
1965 RETURN addTo (s^.procedureF.decls, n)
1966 ELSIF isModule (s)
1967 THEN
1968 IF debugDecl
1969 THEN
1970 outText (doP, "adding ") ;
1971 doNameC (doP, n) ;
1972 outText (doP, " to module\n")
1973 END ;
1974 RETURN addTo (s^.moduleF.decls, n)
1975 ELSIF isDef (s)
1976 THEN
1977 IF debugDecl
1978 THEN
1979 outText (doP, "adding ") ;
1980 doNameC (doP, n) ;
1981 outText (doP, " to definition module\n")
1982 END ;
1983 export (s, n) ;
1984 RETURN addTo (s^.defF.decls, n)
1985 ELSIF isImp (s)
1986 THEN
1987 IF debugDecl
1988 THEN
1989 outText (doP, "adding ") ;
1990 doNameC (doP, n) ;
1991 outText (doP, " to implementation module\n")
1992 END ;
1993 RETURN addTo (s^.impF.decls, n)
1994 END ;
1995 HALT
1996 END addToScope ;
2000 addModuleToScope - adds module, i, to module, m, scope.
2003 PROCEDURE addModuleToScope (m, i: node) ;
2004 BEGIN
2005 assert (getDeclScope () = m) ;
2006 IF lookupSym (getSymName (i))=NIL
2007 THEN
2008 i := addToScope (i)
2010 END addModuleToScope ;
2014 addImportedModule - add module, i, to be imported by, m.
2015 If scoped then module, i, is added to the
2016 module, m, scope.
2019 PROCEDURE addImportedModule (m, i: node; scoped: BOOLEAN) ;
2020 BEGIN
2021 assert (isDef (i) OR isModule (i)) ;
2022 IF isDef (m)
2023 THEN
2024 IncludeIndiceIntoIndex (m^.defF.importedModules, i)
2025 ELSIF isImp (m)
2026 THEN
2027 IncludeIndiceIntoIndex (m^.impF.importedModules, i)
2028 ELSIF isModule (m)
2029 THEN
2030 IncludeIndiceIntoIndex (m^.moduleF.importedModules, i)
2031 ELSE
2032 HALT
2033 END ;
2034 IF scoped
2035 THEN
2036 addModuleToScope (m, i)
2038 END addImportedModule ;
2042 completedEnum - assign boolean enumsComplete to TRUE if a definition,
2043 implementation or module symbol.
2046 PROCEDURE completedEnum (n: node) ;
2047 BEGIN
2048 assert (isDef (n) OR isImp (n) OR isModule (n)) ;
2049 IF isDef (n)
2050 THEN
2051 n^.defF.enumsComplete := TRUE
2052 ELSIF isImp (n)
2053 THEN
2054 n^.impF.enumsComplete := TRUE
2055 ELSIF isModule (n)
2056 THEN
2057 n^.moduleF.enumsComplete := TRUE
2059 END completedEnum ;
2063 setUnary - sets a unary node to contain, arg, a, and type, t.
2066 PROCEDURE setUnary (u: node; k: nodeT; a, t: node) ;
2067 BEGIN
2068 CASE k OF
2070 constexp,
2071 deref,
2072 chr,
2073 cap,
2074 abs,
2075 float,
2076 trunc,
2077 ord,
2078 high,
2079 throw,
2082 not,
2083 neg,
2084 adr,
2085 size,
2086 tsize,
2087 min,
2088 max : u^.kind := k ;
2089 u^.unaryF.arg := a ;
2090 u^.unaryF.resultType := t
2093 END setUnary ;
2097 makeConst - create, initialise and return a const node.
2100 PROCEDURE makeConst (n: Name) : node ;
2102 d: node ;
2103 BEGIN
2104 d := newNode (const) ;
2105 WITH d^ DO
2106 constF.name := n ;
2107 constF.type := NIL ;
2108 constF.scope := getDeclScope () ;
2109 constF.value := NIL
2110 END ;
2111 RETURN addToScope (d)
2112 END makeConst ;
2116 makeType - create, initialise and return a type node.
2119 PROCEDURE makeType (n: Name) : node ;
2121 d: node ;
2122 BEGIN
2123 d := newNode (type) ;
2124 WITH d^ DO
2125 typeF.name := n ;
2126 typeF.type := NIL ;
2127 typeF.scope := getDeclScope () ;
2128 typeF.isOpaque := FALSE ;
2129 typeF.isHidden := FALSE ;
2130 typeF.isInternal := FALSE
2131 END ;
2132 RETURN addToScope (d)
2133 END makeType ;
2137 makeTypeImp - lookup a type in the definition module
2138 and return it. Otherwise create a new type.
2141 PROCEDURE makeTypeImp (n: Name) : node ;
2143 d: node ;
2144 BEGIN
2145 d := lookupSym (n) ;
2146 IF d#NIL
2147 THEN
2148 d^.typeF.isHidden := FALSE ;
2149 RETURN addToScope (d)
2150 ELSE
2151 d := newNode (type) ;
2152 WITH d^ DO
2153 typeF.name := n ;
2154 typeF.type := NIL ;
2155 typeF.scope := getDeclScope () ;
2156 typeF.isOpaque := FALSE ;
2157 typeF.isHidden := FALSE
2158 END ;
2159 RETURN addToScope (d)
2161 END makeTypeImp ;
2165 makeVar - create, initialise and return a var node.
2168 PROCEDURE makeVar (n: Name) : node ;
2170 d: node ;
2171 BEGIN
2172 d := newNode (var) ;
2173 WITH d^ DO
2174 varF.name := n ;
2175 varF.type := NIL ;
2176 varF.decl := NIL ;
2177 varF.scope := getDeclScope () ;
2178 varF.isInitialised := FALSE ;
2179 varF.isParameter := FALSE ;
2180 varF.isVarParameter := FALSE ;
2181 initCname (varF.cname)
2182 END ;
2183 RETURN addToScope (d)
2184 END makeVar ;
2188 putVar - places, type, as the type for var.
2191 PROCEDURE putVar (var, type, decl: node) ;
2192 BEGIN
2193 assert (var#NIL) ;
2194 assert (isVar (var)) ;
2195 var^.varF.type := type ;
2196 var^.varF.decl := decl ;
2197 initNodeOpaqueState (var) ;
2198 END putVar ;
2202 putVarBool - assigns the four booleans associated with a variable.
2205 PROCEDURE putVarBool (v: node; init, param, isvar, isused: BOOLEAN) ;
2206 BEGIN
2207 assert (isVar (v)) ;
2208 v^.varF.isInitialised := init ;
2209 v^.varF.isParameter := param ;
2210 v^.varF.isVarParameter := isvar ;
2211 v^.varF.isUsed := isused
2212 END putVarBool ;
2216 checkPtr - in C++ we need to create a typedef for a pointer
2217 in case we need to use reinterpret_cast.
2220 PROCEDURE checkPtr (n: node) : node ;
2222 s: String ;
2223 p: node ;
2224 BEGIN
2225 IF lang = ansiCP
2226 THEN
2227 IF isPointer (n)
2228 THEN
2229 s := tempName () ;
2230 p := makeType (makekey (DynamicStrings.string (s))) ;
2231 putType (p, n) ;
2232 s := KillString (s) ;
2233 RETURN p
2235 END ;
2236 RETURN n
2237 END checkPtr ;
2241 makeVarDecl - create a vardecl node and create a shadow variable in the
2242 current scope.
2245 PROCEDURE makeVarDecl (i: node; type: node) : node ;
2247 d, v: node ;
2248 j, n: CARDINAL ;
2249 BEGIN
2250 type := checkPtr (type) ;
2251 d := newNode (vardecl) ;
2252 WITH d^ DO
2253 vardeclF.names := i^.identlistF.names ;
2254 vardeclF.type := type ;
2255 vardeclF.scope := getDeclScope ()
2256 END ;
2257 n := wlists.noOfItemsInList (d^.vardeclF.names) ;
2258 j := 1 ;
2259 WHILE j<=n DO
2260 v := lookupSym (wlists.getItemFromList (d^.vardeclF.names, j)) ;
2261 assert (isVar (v)) ;
2262 putVar (v, type, d) ;
2263 INC (j)
2264 END ;
2265 RETURN d
2266 END makeVarDecl ;
2270 isVarDecl - returns TRUE if, n, is a vardecl node.
2273 PROCEDURE isVarDecl (n: node) : BOOLEAN ;
2274 BEGIN
2275 RETURN n^.kind = vardecl
2276 END isVarDecl ;
2280 makeVariablesFromParameters - creates variables which are really parameters.
2283 PROCEDURE makeVariablesFromParameters (proc, id, type: node; isvar, isused: BOOLEAN) ;
2285 v : node ;
2286 i, n: CARDINAL ;
2287 m : Name ;
2288 s : String ;
2289 BEGIN
2290 assert (isProcedure (proc)) ;
2291 assert (isIdentList (id)) ;
2292 i := 1 ;
2293 n := wlists.noOfItemsInList (id^.identlistF.names) ;
2294 WHILE i<=n DO
2295 m := wlists.getItemFromList (id^.identlistF.names, i) ;
2296 v := makeVar (m) ;
2297 putVar (v, type, NIL) ;
2298 putVarBool (v, TRUE, TRUE, isvar, isused) ;
2299 IF debugScopes
2300 THEN
2301 printf ("adding parameter variable into top scope\n") ;
2302 dumpScopes ;
2303 printf (" variable name is: ") ;
2304 s := InitStringCharStar (keyToCharStar (m)) ;
2305 IF KillString (WriteS (StdOut, s))=NIL
2306 THEN
2307 END ;
2308 printf ("\n")
2309 END ;
2310 INC (i)
2312 END makeVariablesFromParameters ;
2316 addProcedureToScope - add a procedure name n and node d to the
2317 current scope.
2320 PROCEDURE addProcedureToScope (d: node; n: Name) : node ;
2322 m: node ;
2323 i: CARDINAL ;
2324 BEGIN
2325 i := HighIndice (scopeStack) ;
2326 m := GetIndice (scopeStack, i) ;
2327 IF isDef (m) AND
2328 (getSymName (m) = makeKey ('M2RTS')) AND
2329 (getSymName (d) = makeKey ('HALT'))
2330 THEN
2331 haltN := d ;
2332 putSymKey (baseSymbols, n, haltN)
2333 END ;
2334 RETURN addToScope (d)
2335 END addProcedureToScope ;
2339 makeProcedure - create, initialise and return a procedure node.
2342 PROCEDURE makeProcedure (n: Name) : node ;
2344 d: node ;
2345 BEGIN
2346 d := lookupSym (n) ;
2347 IF d=NIL
2348 THEN
2349 d := newNode (procedure) ;
2350 WITH d^ DO
2351 procedureF.name := n ;
2352 initDecls (procedureF.decls) ;
2353 procedureF.scope := getDeclScope () ;
2354 procedureF.parameters := InitIndex (1) ;
2355 procedureF.isForC := isDefForCNode (getDeclScope ()) ;
2356 procedureF.built := FALSE ;
2357 procedureF.returnopt := FALSE ;
2358 procedureF.optarg := NIL ;
2359 procedureF.noreturnused := FALSE ;
2360 procedureF.noreturn := FALSE ;
2361 procedureF.vararg := FALSE ;
2362 procedureF.checking := FALSE ;
2363 procedureF.paramcount := 0 ;
2364 procedureF.returnType := NIL ;
2365 procedureF.beginStatements := NIL ;
2366 initCname (procedureF.cname) ;
2367 procedureF.defComment := NIL ;
2368 procedureF.modComment := NIL ;
2370 END ;
2371 RETURN addProcedureToScope (d, n)
2372 END makeProcedure ;
2376 putCommentDefProcedure - remembers the procedure comment (if it exists) as a
2377 definition module procedure heading. NIL is placed
2378 if there is no procedure comment available.
2381 PROCEDURE putCommentDefProcedure (n: node) ;
2382 BEGIN
2383 assert (isProcedure (n)) ;
2384 IF isProcedureComment (lastcomment)
2385 THEN
2386 n^.procedureF.defComment := lastcomment
2388 END putCommentDefProcedure ;
2392 putCommentModProcedure - remembers the procedure comment (if it exists) as an
2393 implementation/program module procedure heading. NIL is placed
2394 if there is no procedure comment available.
2397 PROCEDURE putCommentModProcedure (n: node) ;
2398 BEGIN
2399 assert (isProcedure (n)) ;
2400 IF isProcedureComment (lastcomment)
2401 THEN
2402 n^.procedureF.modComment := lastcomment
2404 END putCommentModProcedure ;
2408 paramEnter - reset the parameter count.
2411 PROCEDURE paramEnter (n: node) ;
2412 BEGIN
2413 assert (isProcedure (n)) ;
2414 n^.procedureF.paramcount := 0
2415 END paramEnter ;
2419 paramLeave - set paramater checking to TRUE from now onwards.
2422 PROCEDURE paramLeave (n: node) ;
2423 BEGIN
2424 assert (isProcedure (n)) ;
2425 n^.procedureF.checking := TRUE ;
2426 IF isImp (currentModule) OR isModule (currentModule)
2427 THEN
2428 n^.procedureF.built := TRUE
2430 END paramLeave ;
2434 putReturnType - sets the return type of procedure or proctype proc to type.
2437 PROCEDURE putReturnType (proc, type: node) ;
2438 BEGIN
2439 assert (isProcedure (proc) OR isProcType (proc)) ;
2440 IF isProcedure (proc)
2441 THEN
2442 proc^.procedureF.returnType := type
2443 ELSE
2444 proc^.proctypeF.returnType := type
2445 END ;
2446 initNodeOpaqueState (proc)
2447 END putReturnType ;
2451 putOptReturn - sets, proctype or procedure, proc, to have an optional return type.
2454 PROCEDURE putOptReturn (proc: node) ;
2455 BEGIN
2456 assert (isProcedure (proc) OR isProcType (proc)) ;
2457 IF isProcedure (proc)
2458 THEN
2459 proc^.procedureF.returnopt := TRUE
2460 ELSE
2461 proc^.proctypeF.returnopt := TRUE
2463 END putOptReturn ;
2467 makeProcType - returns a proctype node.
2470 PROCEDURE makeProcType () : node ;
2472 d: node ;
2473 BEGIN
2474 d := newNode (proctype) ;
2475 WITH d^ DO
2476 proctypeF.scope := getDeclScope () ;
2477 proctypeF.parameters := InitIndex (1) ;
2478 proctypeF.returnopt := FALSE ;
2479 proctypeF.optarg := NIL ;
2480 proctypeF.vararg := FALSE ;
2481 proctypeF.returnType := NIL ;
2482 END ;
2483 initNodeOpaqueState (d) ;
2484 RETURN d
2485 END makeProcType ;
2489 putProcTypeReturn - sets the return type of, proc, to, type.
2492 PROCEDURE putProcTypeReturn (proc, type: node) ;
2493 BEGIN
2494 assert (isProcType (proc)) ;
2495 proc^.proctypeF.returnType := type ;
2496 initNodeOpaqueState (proc)
2497 END putProcTypeReturn ;
2501 putProcTypeOptReturn - sets, proc, to have an optional return type.
2504 PROCEDURE putProcTypeOptReturn (proc: node) ;
2505 BEGIN
2506 assert (isProcType (proc)) ;
2507 proc^.proctypeF.returnopt := TRUE
2508 END putProcTypeOptReturn ;
2512 makeNonVarParameter - returns a non var parameter node with, name: type.
2515 PROCEDURE makeNonVarParameter (l: node; type, proc: node; isused: BOOLEAN) : node ;
2517 d: node ;
2518 BEGIN
2519 assert ((l=NIL) OR isIdentList (l)) ;
2520 d := newNode (param) ;
2521 d^.paramF.namelist := l ;
2522 d^.paramF.type := type ;
2523 d^.paramF.scope := proc ;
2524 d^.paramF.isUnbounded := FALSE ;
2525 d^.paramF.isForC := isDefForCNode (proc) ;
2526 d^.paramF.isUsed := isused ;
2527 initNodeOpaqueState (d) ;
2528 RETURN d
2529 END makeNonVarParameter ;
2533 makeVarParameter - returns a var parameter node with, name: type.
2536 PROCEDURE makeVarParameter (l: node; type, proc: node; isused: BOOLEAN) : node ;
2538 d: node ;
2539 BEGIN
2540 assert ((l=NIL) OR isIdentList (l)) ;
2541 d := newNode (varparam) ;
2542 d^.varparamF.namelist := l ;
2543 d^.varparamF.type := type ;
2544 d^.varparamF.scope := proc ;
2545 d^.varparamF.isUnbounded := FALSE ;
2546 d^.varparamF.isForC := isDefForCNode (proc) ;
2547 d^.varparamF.isUsed := isused ;
2548 initNodeOpaqueState (d) ;
2549 RETURN d
2550 END makeVarParameter ;
2554 makeVarargs - returns a varargs node.
2557 PROCEDURE makeVarargs () : node ;
2559 d: node ;
2560 BEGIN
2561 d := newNode (varargs) ;
2562 d^.varargsF.scope := NIL ;
2563 RETURN d
2564 END makeVarargs ;
2568 isVarargs - returns TRUE if, n, is a varargs node.
2571 PROCEDURE isVarargs (n: node) : BOOLEAN ;
2572 BEGIN
2573 RETURN n^.kind = varargs
2574 END isVarargs ;
2578 addParameter - adds a parameter, param, to procedure or proctype, proc.
2581 PROCEDURE addParameter (proc, param: node) ;
2582 BEGIN
2583 assert (isVarargs (param) OR isParam (param) OR isVarParam (param) OR isOptarg (param)) ;
2584 CASE proc^.kind OF
2586 procedure: IncludeIndiceIntoIndex (proc^.procedureF.parameters, param) ;
2587 IF isVarargs (param)
2588 THEN
2589 proc^.procedureF.vararg := TRUE
2590 END ;
2591 IF isOptarg (param)
2592 THEN
2593 proc^.procedureF.optarg := param
2594 END |
2595 proctype : IncludeIndiceIntoIndex (proc^.proctypeF.parameters, param) ;
2596 IF isVarargs (param)
2597 THEN
2598 proc^.proctypeF.vararg := TRUE
2599 END ;
2600 IF isOptarg (param)
2601 THEN
2602 proc^.proctypeF.optarg := param
2606 END addParameter ;
2610 isOptarg - returns TRUE if, n, is an optarg.
2613 PROCEDURE isOptarg (n: node) : BOOLEAN ;
2614 BEGIN
2615 RETURN n^.kind = optarg
2616 END isOptarg ;
2620 makeOptParameter - creates and returns an optarg.
2623 PROCEDURE makeOptParameter (l, type, init: node) : node ;
2625 n: node ;
2626 BEGIN
2627 n := newNode (optarg) ;
2628 n^.optargF.namelist := l ;
2629 n^.optargF.type := type ;
2630 n^.optargF.init := init ;
2631 n^.optargF.scope := NIL ;
2632 RETURN n
2633 END makeOptParameter ;
2637 addOptParameter - returns an optarg which has been created and added to
2638 procedure node, proc. It has a name, id, and, type,
2639 and an initial value, init.
2642 PROCEDURE addOptParameter (proc: node; id: Name; type, init: node) : node ;
2644 p, l: node ;
2645 BEGIN
2646 assert (isProcedure (proc)) ;
2647 l := makeIdentList () ;
2648 assert (putIdent (l, id)) ;
2649 checkMakeVariables (proc, l, type, FALSE, TRUE) ;
2650 IF NOT proc^.procedureF.checking
2651 THEN
2652 p := makeOptParameter (l, type, init) ;
2653 addParameter (proc, p)
2654 END ;
2655 RETURN p
2656 END addOptParameter ;
2660 globalNode: node ;
2664 setwatch - assign the globalNode to n.
2667 PROCEDURE setwatch (n: node) : BOOLEAN ;
2668 BEGIN
2669 globalNode := n ;
2670 RETURN TRUE
2671 END setwatch ;
2675 runwatch - set the globalNode to an identlist.
2678 PROCEDURE runwatch () : BOOLEAN ;
2679 BEGIN
2680 RETURN globalNode^.kind = identlist
2681 END runwatch ;
2685 makeIdentList - returns a node which will be used to maintain an ident list.
2688 PROCEDURE makeIdentList () : node ;
2690 n: node ;
2691 BEGIN
2692 n := newNode (identlist) ;
2693 n^.identlistF.names := wlists.initList () ;
2694 n^.identlistF.cnamed := FALSE ;
2695 RETURN n
2696 END makeIdentList ;
2700 isIdentList - returns TRUE if, n, is an identlist.
2703 PROCEDURE isIdentList (n: node) : BOOLEAN ;
2704 BEGIN
2705 RETURN n^.kind = identlist
2706 END isIdentList ;
2710 putIdent - places ident, i, into identlist, n. It returns TRUE if
2711 ident, i, is unique.
2714 PROCEDURE putIdent (n: node; i: Name) : BOOLEAN ;
2715 BEGIN
2716 assert (isIdentList (n)) ;
2717 IF wlists.isItemInList (n^.identlistF.names, i)
2718 THEN
2719 RETURN FALSE
2720 ELSE
2721 wlists.putItemIntoList (n^.identlistF.names, i) ;
2722 RETURN TRUE
2724 END putIdent ;
2728 identListLen - returns the length of identlist.
2731 PROCEDURE identListLen (n: node) : CARDINAL ;
2732 BEGIN
2733 IF n=NIL
2734 THEN
2735 RETURN 0
2736 ELSE
2737 assert (isIdentList (n)) ;
2738 RETURN wlists.noOfItemsInList (n^.identlistF.names)
2740 END identListLen ;
2744 checkParameters - placeholder for future parameter checking.
2747 PROCEDURE checkParameters (p: node; i: node; type: node; isvar, isused: BOOLEAN) ;
2748 BEGIN
2749 (* do check. *)
2750 disposeNode (i)
2751 END checkParameters ;
2755 avoidCnames - checks each name in, n, against C reserved
2756 keywords and macros.
2759 PROCEDURE avoidCnames (n: node) ;
2761 i, j: CARDINAL ;
2762 BEGIN
2763 assert (isIdentList (n)) ;
2764 IF NOT n^.identlistF.cnamed
2765 THEN
2766 n^.identlistF.cnamed := TRUE ;
2767 j := wlists.noOfItemsInList (n^.identlistF.names) ;
2768 i := 1 ;
2769 WHILE i<=j DO
2770 wlists.replaceItemInList (n^.identlistF.names,
2772 keyc.cnamen (wlists.getItemFromList (n^.identlistF.names, i), FALSE)) ;
2773 INC (i)
2776 END avoidCnames ;
2781 checkMakeVariables - create shadow local variables for parameters providing that
2782 procedure n has not already been built and we are compiling
2783 a module or an implementation module.
2786 PROCEDURE checkMakeVariables (n, i, type: node; isvar, isused: BOOLEAN) ;
2787 BEGIN
2788 IF (isImp (currentModule) OR isModule (currentModule)) AND
2789 (NOT n^.procedureF.built)
2790 THEN
2791 makeVariablesFromParameters (n, i, type, isvar, isused)
2792 END ;
2793 END checkMakeVariables ;
2797 addVarParameters - adds the identlist, i, of, type, to be VAR parameters
2798 in procedure, n.
2801 PROCEDURE addVarParameters (n: node; i: node; type: node; isused: BOOLEAN) ;
2803 p: node ;
2804 BEGIN
2805 assert (isIdentList (i)) ;
2806 assert (isProcedure (n)) ;
2807 checkMakeVariables (n, i, type, TRUE, isused) ;
2808 IF n^.procedureF.checking
2809 THEN
2810 checkParameters (n, i, type, TRUE, isused) (* will destroy, i. *)
2811 ELSE
2812 p := makeVarParameter (i, type, n, isused) ;
2813 IncludeIndiceIntoIndex (n^.procedureF.parameters, p) ;
2814 END ;
2815 END addVarParameters ;
2819 addNonVarParameters - adds the identlist, i, of, type, to be parameters
2820 in procedure, n.
2823 PROCEDURE addNonVarParameters (n: node; i: node; type: node; isused: BOOLEAN) ;
2825 p: node ;
2826 BEGIN
2827 assert (isIdentList (i)) ;
2828 assert (isProcedure (n)) ;
2829 checkMakeVariables (n, i, type, FALSE, isused) ;
2830 IF n^.procedureF.checking
2831 THEN
2832 checkParameters (n, i, type, FALSE, isused) (* will destroy, i. *)
2833 ELSE
2834 p := makeNonVarParameter (i, type, n, isused) ;
2835 IncludeIndiceIntoIndex (n^.procedureF.parameters, p)
2836 END ;
2837 END addNonVarParameters ;
2841 makeSubrange - returns a subrange node, built from range: low..high.
2844 PROCEDURE makeSubrange (low, high: node) : node ;
2846 n: node ;
2847 BEGIN
2848 n := newNode (subrange) ;
2849 n^.subrangeF.low := low ;
2850 n^.subrangeF.high := high ;
2851 n^.subrangeF.type := NIL ;
2852 n^.subrangeF.scope := getDeclScope () ;
2853 RETURN n
2854 END makeSubrange ;
2858 putSubrangeType - assigns, type, to the subrange type, sub.
2861 PROCEDURE putSubrangeType (sub, type: node) ;
2862 BEGIN
2863 assert (isSubrange (sub)) ;
2864 sub^.subrangeF.type := type
2865 END putSubrangeType ;
2869 makeSet - returns a set of, type, node.
2872 PROCEDURE makeSet (type: node) : node ;
2874 n: node ;
2875 BEGIN
2876 n := newNode (set) ;
2877 n^.setF.type := type ;
2878 n^.setF.scope := getDeclScope () ;
2879 RETURN n
2880 END makeSet ;
2884 makeSetValue - creates and returns a setvalue node.
2887 PROCEDURE makeSetValue () : node ;
2889 n: node ;
2890 BEGIN
2891 n := newNode (setvalue) ;
2892 n^.setvalueF.type := bitsetN ;
2893 n^.setvalueF.values := InitIndex (1) ;
2894 RETURN n
2895 END makeSetValue ;
2899 isSetValue - returns TRUE if, n, is a setvalue node.
2902 PROCEDURE isSetValue (n: node) : BOOLEAN ;
2903 BEGIN
2904 assert (n # NIL) ;
2905 RETURN n^.kind = setvalue
2906 END isSetValue ;
2910 putSetValue - assigns the type, t, to the set value, n. The
2911 node, n, is returned.
2914 PROCEDURE putSetValue (n, t: node) : node ;
2915 BEGIN
2916 assert (isSetValue (n)) ;
2917 n^.setvalueF.type := t ;
2918 RETURN n
2919 END putSetValue ;
2923 includeSetValue - includes the range l..h into the setvalue.
2924 h might be NIL indicating that a single element
2925 is to be included into the set.
2926 n is returned.
2929 PROCEDURE includeSetValue (n: node; l, h: node) : node ;
2930 BEGIN
2931 assert (isSetValue (n)) ;
2932 IncludeIndiceIntoIndex (n^.setvalueF.values, l) ;
2933 RETURN n
2934 END includeSetValue ;
2938 makePointer - returns a pointer of, type, node.
2941 PROCEDURE makePointer (type: node) : node ;
2943 n: node ;
2944 BEGIN
2945 n := newNode (pointer) ;
2946 n^.pointerF.type := type ;
2947 n^.pointerF.scope := getDeclScope () ;
2948 RETURN n
2949 END makePointer ;
2953 makeArray - returns a node representing ARRAY subr OF type.
2956 PROCEDURE makeArray (subr, type: node) : node ;
2958 n, s: node ;
2959 BEGIN
2960 s := skipType (subr) ;
2961 assert (isSubrange (s) OR isOrdinal (s) OR isEnumeration (s)) ;
2962 n := newNode (array) ;
2963 n^.arrayF.subr := subr ;
2964 n^.arrayF.type := type ;
2965 n^.arrayF.scope := getDeclScope () ;
2966 n^.arrayF.isUnbounded := FALSE ;
2967 RETURN n
2968 END makeArray ;
2972 makeRecord - creates and returns a record node.
2975 PROCEDURE makeRecord () : node ;
2977 n: node ;
2978 BEGIN
2979 n := newNode (record) ;
2980 n^.recordF.localSymbols := initTree () ;
2981 n^.recordF.listOfSons := InitIndex (1) ;
2982 n^.recordF.scope := getDeclScope () ;
2983 RETURN n
2984 END makeRecord ;
2988 addFieldsToRecord - adds fields, i, of type, t, into a record, r.
2989 It returns, r.
2992 PROCEDURE addFieldsToRecord (r, v, i, t: node) : node ;
2994 p, fj: node ;
2995 j, n : CARDINAL ;
2996 fn : Name ;
2997 BEGIN
2998 IF isRecord (r)
2999 THEN
3000 p := r ;
3001 v := NIL
3002 ELSE
3003 p := getRecord (getParent (r)) ;
3004 assert (isVarientField (r)) ;
3005 assert (isVarient (v)) ;
3006 putFieldVarient (r, v)
3007 END ;
3008 n := wlists.noOfItemsInList (i^.identlistF.names) ;
3009 j := 1 ;
3010 WHILE j<=n DO
3011 fn := wlists.getItemFromList (i^.identlistF.names, j) ;
3012 fj := getSymKey (p^.recordF.localSymbols, n) ;
3013 IF fj=NIL
3014 THEN
3015 fj := putFieldRecord (r, fn, t, v)
3016 ELSE
3017 metaErrors2 ('record field {%1ad} has already been declared inside a {%2Dd} {%2a}',
3018 'attempting to declare a duplicate record field', fj, p)
3019 END ;
3020 INC (j)
3021 END ;
3022 RETURN r;
3023 END addFieldsToRecord ;
3027 makeVarient - creates a new symbol, a varient symbol for record or varient field
3028 symbol, r.
3031 PROCEDURE makeVarient (r: node) : node ;
3033 n: node ;
3034 BEGIN
3035 n := newNode (varient) ;
3036 WITH n^ DO
3037 varientF.listOfSons := InitIndex (1) ;
3038 (* do we need to remember our parent (r) ? *)
3039 (* if so use this n^.varientF.parent := r *)
3040 IF isRecord (r)
3041 THEN
3042 varientF.varient := NIL
3043 ELSE
3044 varientF.varient := r
3045 END ;
3046 varientF.tag := NIL ;
3047 varientF.scope := getDeclScope () ;
3048 END ;
3049 (* now add, n, to the record/varient, r, field list *)
3050 WITH r^ DO
3051 CASE kind OF
3053 record : IncludeIndiceIntoIndex (recordF.listOfSons, n) |
3054 varientfield: IncludeIndiceIntoIndex (varientfieldF.listOfSons, n)
3057 END ;
3058 RETURN n
3059 END makeVarient ;
3063 buildVarientFieldRecord - builds a varient field into a varient symbol, v.
3064 The varient field is returned.
3067 PROCEDURE buildVarientFieldRecord (v: node; p: node) : node ;
3069 f: node ;
3070 BEGIN
3071 assert (isVarient (v)) ;
3072 f := makeVarientField (v, p) ;
3073 assert (isVarientField (f)) ;
3074 putFieldVarient (f, v) ;
3075 RETURN f
3076 END buildVarientFieldRecord ;
3080 makeVarientField - create a varient field within varient, v,
3081 The new varient field is returned.
3084 PROCEDURE makeVarientField (v: node; p: node) : node ;
3086 n: node ;
3087 BEGIN
3088 n := newNode (varientfield) ;
3089 WITH n^.varientfieldF DO
3090 name := NulName ;
3091 parent := p ;
3092 varient := v ;
3093 simple := FALSE ;
3094 listOfSons := InitIndex (1) ;
3095 scope := getDeclScope ()
3096 END ;
3097 RETURN n
3098 END makeVarientField ;
3102 putFieldVarient - places the field varient, f, as a brother to, the
3103 varient symbol, v, and also tells, f, that its varient
3104 parent is, v.
3107 PROCEDURE putFieldVarient (f, v: node) ;
3108 BEGIN
3109 assert (isVarient (v)) ;
3110 assert (isVarientField (f)) ;
3111 WITH v^ DO
3112 CASE kind OF
3114 varient: IncludeIndiceIntoIndex (varientF.listOfSons, f)
3117 END ;
3118 WITH f^ DO
3119 CASE kind OF
3121 varientfield: varientfieldF.varient := v
3125 END putFieldVarient ;
3129 putFieldRecord - create a new recordfield and place it into record r.
3130 The new field has a tagname and type and can have a
3131 variant field v.
3134 PROCEDURE putFieldRecord (r: node; tag: Name; type, v: node) : node ;
3136 f, n, p: node ;
3137 BEGIN
3138 n := newNode (recordfield) ;
3139 WITH r^ DO
3140 CASE kind OF
3142 record: IncludeIndiceIntoIndex (recordF.listOfSons, n) ;
3143 (* ensure that field, n, is in the parents Local Symbols. *)
3144 IF tag#NulName
3145 THEN
3146 IF getSymKey (recordF.localSymbols, tag) = NulKey
3147 THEN
3148 putSymKey (recordF.localSymbols, tag, n)
3149 ELSE
3150 f := getSymKey (recordF.localSymbols, tag) ;
3151 metaErrors1 ('field record {%1Dad} has already been declared',
3152 'field record duplicate', f)
3154 END |
3155 varientfield: IncludeIndiceIntoIndex (varientfieldF.listOfSons, n) ;
3156 p := getParent (r) ;
3157 assert (p^.kind=record) ;
3158 IF tag#NulName
3159 THEN
3160 putSymKey (p^.recordF.localSymbols, tag, n)
3164 END ;
3165 (* fill in, n. *)
3166 n^.recordfieldF.type := type ;
3167 n^.recordfieldF.name := tag ;
3168 n^.recordfieldF.parent := r ;
3169 n^.recordfieldF.varient := v ;
3170 n^.recordfieldF.tag := FALSE ;
3171 n^.recordfieldF.scope := NIL ;
3172 initCname (n^.recordfieldF.cname) ;
3174 IF r^.kind=record
3175 THEN
3176 doRecordM2 (doP, r)
3177 END ;
3179 RETURN n
3180 END putFieldRecord ;
3184 buildVarientSelector - builds a field of name, tag, of, type onto:
3185 record or varient field, r.
3186 varient, v.
3189 PROCEDURE buildVarientSelector (r, v: node; tag: Name; type: node) ;
3191 f: node ;
3192 BEGIN
3193 assert (isRecord (r) OR isVarientField (r)) ;
3194 IF isRecord (r) OR isVarientField (r)
3195 THEN
3196 IF (type=NIL) AND (tag=NulName)
3197 THEN
3198 metaError1 ('expecting a tag field in the declaration of a varient record {%1Ua}', r)
3199 ELSIF type=NIL
3200 THEN
3201 f := lookupSym (tag) ;
3202 putVarientTag (v, f)
3203 ELSE
3204 f := putFieldRecord (r, tag, type, v) ;
3205 assert (isRecordField (f)) ;
3206 f^.recordfieldF.tag := TRUE ;
3207 putVarientTag (v, f)
3210 END buildVarientSelector ;
3214 ensureOrder - ensures that, a, and, b, exist in, i, and also
3215 ensure that, a, is before, b.
3218 PROCEDURE ensureOrder (i: Index; a, b: node) ;
3219 BEGIN
3220 assert (IsIndiceInIndex (i, a)) ;
3221 assert (IsIndiceInIndex (i, b)) ;
3222 RemoveIndiceFromIndex (i, a) ;
3223 RemoveIndiceFromIndex (i, b) ;
3224 IncludeIndiceIntoIndex (i, a) ;
3225 IncludeIndiceIntoIndex (i, b) ;
3226 assert (IsIndiceInIndex (i, a)) ;
3227 assert (IsIndiceInIndex (i, b))
3228 END ensureOrder ;
3232 putVarientTag - places tag into variant v.
3235 PROCEDURE putVarientTag (v: node; tag: node) ;
3237 p: node ;
3238 BEGIN
3239 assert (isVarient (v)) ;
3240 CASE v^.kind OF
3242 varient: v^.varientF.tag := tag
3245 END putVarientTag ;
3249 getParent - returns the parent field of recordfield or varientfield symbol, n.
3252 PROCEDURE getParent (n: node) : node ;
3253 BEGIN
3254 CASE n^.kind OF
3256 recordfield: RETURN n^.recordfieldF.parent |
3257 varientfield: RETURN n^.varientfieldF.parent
3260 END getParent ;
3264 getRecord - returns the record associated with node, n.
3265 (Parental record).
3268 PROCEDURE getRecord (n: node) : node ;
3269 BEGIN
3270 assert (n^.kind # varient) ; (* if this fails then we need to add parent field to varient. *)
3271 CASE n^.kind OF
3273 record : RETURN n |
3274 varientfield: RETURN getRecord (getParent (n))
3277 END getRecord ;
3281 putUnbounded - sets array, n, as unbounded.
3284 PROCEDURE putUnbounded (n: node) ;
3285 BEGIN
3286 assert (n^.kind = array) ;
3287 n^.arrayF.isUnbounded := TRUE
3288 END putUnbounded ;
3292 isConstExp - return TRUE if the node kind is a constexp.
3295 PROCEDURE isConstExp (c: node) : BOOLEAN ;
3296 BEGIN
3297 assert (c#NIL) ;
3298 RETURN c^.kind = constexp
3299 END isConstExp ;
3303 addEnumToModule - adds enumeration type, e, into the list of enums
3304 in module, m.
3307 PROCEDURE addEnumToModule (m, e: node) ;
3308 BEGIN
3309 assert (isEnumeration (e) OR isEnumerationField (e)) ;
3310 assert (isModule (m) OR isDef (m) OR isImp (m)) ;
3311 IF isModule (m)
3312 THEN
3313 IncludeIndiceIntoIndex (m^.moduleF.enumFixup.info, e)
3314 ELSIF isDef (m)
3315 THEN
3316 IncludeIndiceIntoIndex (m^.defF.enumFixup.info, e)
3317 ELSIF isImp (m)
3318 THEN
3319 IncludeIndiceIntoIndex (m^.impF.enumFixup.info, e)
3321 END addEnumToModule ;
3325 getNextFixup - return the next fixup from from f.
3328 PROCEDURE getNextFixup (VAR f: fixupInfo) : node ;
3329 BEGIN
3330 INC (f.count) ;
3331 RETURN GetIndice (f.info, f.count)
3332 END getNextFixup ;
3336 getNextEnum - returns the next enumeration node.
3339 PROCEDURE getNextEnum () : node ;
3341 n: node ;
3342 BEGIN
3343 n := NIL ;
3344 assert (isDef (currentModule) OR isImp (currentModule) OR isModule (currentModule)) ;
3345 WITH currentModule^ DO
3346 IF isDef (currentModule)
3347 THEN
3348 n := getNextFixup (defF.enumFixup)
3349 ELSIF isImp (currentModule)
3350 THEN
3351 n := getNextFixup (impF.enumFixup)
3352 ELSIF isModule (currentModule)
3353 THEN
3354 n := getNextFixup (moduleF.enumFixup)
3356 END ;
3357 assert (n # NIL) ;
3358 assert (isEnumeration (n) OR isEnumerationField (n)) ;
3359 RETURN n
3360 END getNextEnum ;
3364 resetEnumPos - resets the index into the saved list of enums inside
3365 module, n.
3368 PROCEDURE resetEnumPos (n: node) ;
3369 BEGIN
3370 assert (isDef (n) OR isImp (n) OR isModule (n)) ;
3371 IF isDef (n)
3372 THEN
3373 n^.defF.enumFixup.count := 0
3374 ELSIF isImp (n)
3375 THEN
3376 n^.impF.enumFixup.count := 0
3377 ELSIF isModule (n)
3378 THEN
3379 n^.moduleF.enumFixup.count := 0
3381 END resetEnumPos ;
3385 getEnumsComplete - gets the field from the def or imp or module, n.
3388 PROCEDURE getEnumsComplete (n: node) : BOOLEAN ;
3389 BEGIN
3390 CASE n^.kind OF
3392 def : RETURN n^.defF.enumsComplete |
3393 imp : RETURN n^.impF.enumsComplete |
3394 module: RETURN n^.moduleF.enumsComplete
3397 END getEnumsComplete ;
3401 setEnumsComplete - sets the field inside the def or imp or module, n.
3404 PROCEDURE setEnumsComplete (n: node) ;
3405 BEGIN
3406 CASE n^.kind OF
3408 def : n^.defF.enumsComplete := TRUE |
3409 imp : n^.impF.enumsComplete := TRUE |
3410 module: n^.moduleF.enumsComplete := TRUE
3413 END setEnumsComplete ;
3417 doMakeEnum - create an enumeration type and add it to the current module.
3420 PROCEDURE doMakeEnum () : node ;
3422 e: node ;
3423 BEGIN
3424 e := newNode (enumeration) ;
3425 WITH e^ DO
3426 enumerationF.noOfElements := 0 ;
3427 enumerationF.localSymbols := initTree () ;
3428 enumerationF.scope := getDeclScope () ;
3429 enumerationF.listOfSons := InitIndex (1) ;
3430 enumerationF.low := NIL ;
3431 enumerationF.high := NIL ;
3432 END ;
3433 addEnumToModule (currentModule, e) ;
3434 RETURN e
3435 END doMakeEnum ;
3439 makeEnum - creates an enumerated type and returns the node.
3442 PROCEDURE makeEnum () : node ;
3443 BEGIN
3444 IF (currentModule#NIL) AND getEnumsComplete (currentModule)
3445 THEN
3446 RETURN getNextEnum ()
3447 ELSE
3448 RETURN doMakeEnum ()
3450 END makeEnum ;
3454 doMakeEnumField - create an enumeration field name and add it to enumeration e.
3455 Return the new field.
3458 PROCEDURE doMakeEnumField (e: node; n: Name) : node ;
3460 f: node ;
3461 BEGIN
3462 assert (isEnumeration (e)) ;
3463 f := lookupSym (n) ;
3464 IF f=NIL
3465 THEN
3466 f := newNode (enumerationfield) ;
3467 putSymKey (e^.enumerationF.localSymbols, n, f) ;
3468 IncludeIndiceIntoIndex (e^.enumerationF.listOfSons, f) ;
3469 WITH f^ DO
3470 enumerationfieldF.name := n ;
3471 enumerationfieldF.type := e ;
3472 enumerationfieldF.scope := getDeclScope () ;
3473 enumerationfieldF.value := e^.enumerationF.noOfElements ;
3474 initCname (enumerationfieldF.cname)
3475 END ;
3476 INC (e^.enumerationF.noOfElements) ;
3477 assert (GetIndice (e^.enumerationF.listOfSons, e^.enumerationF.noOfElements) = f) ;
3478 addEnumToModule (currentModule, f) ;
3479 IF e^.enumerationF.low = NIL
3480 THEN
3481 e^.enumerationF.low := f
3482 END ;
3483 e^.enumerationF.high := f ;
3484 RETURN addToScope (f)
3485 ELSE
3486 metaErrors2 ('cannot create enumeration field {%1k} as the name is already in use',
3487 '{%2DMad} was declared elsewhere', n, f)
3488 END ;
3489 RETURN f
3490 END doMakeEnumField ;
3494 makeEnumField - returns an enumeration field, named, n.
3497 PROCEDURE makeEnumField (e: node; n: Name) : node ;
3498 BEGIN
3499 IF (currentModule#NIL) AND getEnumsComplete (currentModule)
3500 THEN
3501 RETURN getNextEnum ()
3502 ELSE
3503 RETURN doMakeEnumField (e, n)
3505 END makeEnumField ;
3509 isEnumeration - returns TRUE if node, n, is an enumeration type.
3512 PROCEDURE isEnumeration (n: node) : BOOLEAN ;
3513 BEGIN
3514 assert (n#NIL) ;
3515 RETURN n^.kind = enumeration
3516 END isEnumeration ;
3520 makeExpList - creates and returns an expList node.
3523 PROCEDURE makeExpList () : node ;
3525 n: node ;
3526 BEGIN
3527 n := newNode (explist) ;
3528 n^.explistF.exp := InitIndex (1) ;
3529 RETURN n
3530 END makeExpList ;
3534 isExpList - returns TRUE if, n, is an explist node.
3537 PROCEDURE isExpList (n: node) : BOOLEAN ;
3538 BEGIN
3539 assert (n # NIL) ;
3540 RETURN n^.kind = explist
3541 END isExpList ;
3545 putExpList - places, expression, e, within the explist, n.
3548 PROCEDURE putExpList (n: node; e: node) ;
3549 BEGIN
3550 assert (n # NIL) ;
3551 assert (isExpList (n)) ;
3552 PutIndice (n^.explistF.exp, HighIndice (n^.explistF.exp) + 1, e)
3553 END putExpList ;
3557 getExpList - returns the, n, th argument in an explist.
3560 PROCEDURE getExpList (p: node; n: CARDINAL) : node ;
3561 BEGIN
3562 assert (p#NIL) ;
3563 assert (isExpList (p)) ;
3564 assert (n <= HighIndice (p^.explistF.exp)) ;
3565 RETURN GetIndice (p^.explistF.exp, n)
3566 END getExpList ;
3570 expListLen - returns the length of explist, p.
3573 PROCEDURE expListLen (p: node) : CARDINAL ;
3574 BEGIN
3575 IF p = NIL
3576 THEN
3577 RETURN 0
3578 ELSE
3579 assert (isExpList (p)) ;
3580 RETURN HighIndice (p^.explistF.exp)
3582 END expListLen ;
3586 getConstExpComplete - gets the field from the def or imp or module, n.
3589 PROCEDURE getConstExpComplete (n: node) : BOOLEAN ;
3590 BEGIN
3591 CASE n^.kind OF
3593 def : RETURN n^.defF.constsComplete |
3594 imp : RETURN n^.impF.constsComplete |
3595 module: RETURN n^.moduleF.constsComplete
3598 END getConstExpComplete ;
3602 setConstExpComplete - sets the field inside the def or imp or module, n.
3605 PROCEDURE setConstExpComplete (n: node) ;
3606 BEGIN
3607 CASE n^.kind OF
3609 def : n^.defF.constsComplete := TRUE |
3610 imp : n^.impF.constsComplete := TRUE |
3611 module: n^.moduleF.constsComplete := TRUE
3614 END setConstExpComplete ;
3618 getNextConstExp - returns the next constexp node.
3621 PROCEDURE getNextConstExp () : node ;
3622 BEGIN
3623 assert (isDef (currentModule) OR isImp (currentModule) OR isModule (currentModule)) ;
3624 WITH currentModule^ DO
3625 IF isDef (currentModule)
3626 THEN
3627 RETURN getNextFixup (defF.constFixup)
3628 ELSIF isImp (currentModule)
3629 THEN
3630 RETURN getNextFixup (impF.constFixup)
3631 ELSE
3632 assert (isModule (currentModule)) ;
3633 RETURN getNextFixup (moduleF.constFixup)
3636 END getNextConstExp ;
3640 resetConstExpPos - resets the index into the saved list of constexps inside
3641 module, n.
3644 PROCEDURE resetConstExpPos (n: node) ;
3645 BEGIN
3646 assert (isDef (n) OR isImp (n) OR isModule (n)) ;
3647 IF isDef (n)
3648 THEN
3649 n^.defF.constFixup.count := 0
3650 ELSIF isImp (n)
3651 THEN
3652 n^.impF.constFixup.count := 0
3653 ELSIF isModule (n)
3654 THEN
3655 n^.moduleF.constFixup.count := 0
3657 END resetConstExpPos ;
3661 addConstToModule - adds const exp, e, into the list of constant
3662 expressions in module, m.
3665 PROCEDURE addConstToModule (m, e: node) ;
3666 BEGIN
3667 assert (isModule (m) OR isDef (m) OR isImp (m)) ;
3668 IF isModule (m)
3669 THEN
3670 IncludeIndiceIntoIndex (m^.moduleF.constFixup.info, e)
3671 ELSIF isDef (m)
3672 THEN
3673 IncludeIndiceIntoIndex (m^.defF.constFixup.info, e)
3674 ELSIF isImp (m)
3675 THEN
3676 IncludeIndiceIntoIndex (m^.impF.constFixup.info, e)
3678 END addConstToModule ;
3682 doMakeConstExp - create a constexp node and add it to the current module.
3685 PROCEDURE doMakeConstExp () : node ;
3687 c: node ;
3688 BEGIN
3689 c := makeUnary (constexp, NIL, NIL) ;
3690 addConstToModule (currentModule, c) ;
3691 RETURN c
3692 END doMakeConstExp ;
3696 makeConstExp - returns a constexp node.
3699 PROCEDURE makeConstExp () : node ;
3700 BEGIN
3701 IF (currentModule#NIL) AND getConstExpComplete (currentModule)
3702 THEN
3703 RETURN getNextConstExp ()
3704 ELSE
3705 RETURN doMakeConstExp ()
3707 END makeConstExp ;
3711 fixupConstExp - assign fixup expression, e, into the argument of, c.
3714 PROCEDURE fixupConstExp (c, e: node) : node ;
3715 BEGIN
3716 assert (isConstExp (c)) ;
3717 c^.unaryF.arg := e ;
3718 RETURN c
3719 END fixupConstExp ;
3723 isAnyType - return TRUE if node n is any type kind.
3726 PROCEDURE isAnyType (n: node) : BOOLEAN ;
3727 BEGIN
3728 assert (n # NIL) ;
3729 CASE n^.kind OF
3731 address,
3732 loc,
3733 byte,
3734 word,
3735 char,
3736 cardinal,
3737 longcard,
3738 shortcard,
3739 integer,
3740 longint,
3741 shortint,
3742 complex,
3743 longcomplex,
3744 shortcomplex,
3745 bitset,
3746 boolean,
3747 proc,
3748 type : RETURN TRUE
3750 ELSE
3751 RETURN FALSE
3753 END isAnyType ;
3757 makeVal - creates a VAL (type, expression) node.
3760 PROCEDURE makeVal (params: node) : node ;
3761 BEGIN
3762 assert (isExpList (params)) ;
3763 IF expListLen (params) = 2
3764 THEN
3765 RETURN makeBinary (val,
3766 getExpList (params, 1),
3767 getExpList (params, 2),
3768 getExpList (params, 1))
3769 ELSE
3770 HALT
3772 END makeVal ;
3776 makeCast - creates a cast node TYPENAME (expr).
3779 PROCEDURE makeCast (c, p: node) : node ;
3780 BEGIN
3781 assert (isExpList (p)) ;
3782 IF expListLen (p) = 1
3783 THEN
3784 RETURN makeBinary (cast, c, getExpList (p, 1), c)
3785 ELSE
3786 HALT
3788 END makeCast ;
3792 makeIntrisicProc - create an intrinsic node.
3795 PROCEDURE makeIntrinsicProc (k: nodeT; noArgs: CARDINAL; p: node) : node ;
3797 f: node ;
3798 BEGIN
3799 f := newNode (k) ;
3800 f^.intrinsicF.args := p ;
3801 f^.intrinsicF.noArgs := noArgs ;
3802 f^.intrinsicF.type := NIL ;
3803 f^.intrinsicF.postUnreachable := (k = halt) ;
3804 initPair (f^.intrinsicF.intrinsicComment) ;
3805 RETURN f
3806 END makeIntrinsicProc ;
3810 makeIntrinsicUnaryType - create an intrisic unary type.
3813 PROCEDURE makeIntrinsicUnaryType (k: nodeT; paramList: node; returnType: node) : node ;
3814 BEGIN
3815 RETURN makeUnary (k, getExpList (paramList, 1), returnType)
3816 END makeIntrinsicUnaryType ;
3820 makeIntrinsicBinaryType - create an intrisic binary type.
3823 PROCEDURE makeIntrinsicBinaryType (k: nodeT; paramList: node; returnType: node) : node ;
3824 BEGIN
3825 RETURN makeBinary (k, getExpList (paramList, 1), getExpList (paramList, 2), returnType)
3826 END makeIntrinsicBinaryType ;
3830 checkIntrinsic - checks to see if the function call to, c, with
3831 parameter list, n, is really an intrinic. If it
3832 is an intrinic then an intrinic node is created
3833 and returned. Otherwise NIL is returned.
3836 PROCEDURE checkIntrinsic (c, n: node) : node ;
3837 BEGIN
3838 IF isAnyType (c)
3839 THEN
3840 RETURN makeCast (c, n)
3841 ELSIF c = maxN
3842 THEN
3843 RETURN makeIntrinsicUnaryType (max, n, NIL)
3844 ELSIF c = minN
3845 THEN
3846 RETURN makeIntrinsicUnaryType (min, n, NIL)
3847 ELSIF c = haltN
3848 THEN
3849 RETURN makeIntrinsicProc (halt, expListLen (n), n)
3850 ELSIF c = valN
3851 THEN
3852 RETURN makeVal (n)
3853 ELSIF c = adrN
3854 THEN
3855 RETURN makeIntrinsicUnaryType (adr, n, addressN)
3856 ELSIF c = sizeN
3857 THEN
3858 RETURN makeIntrinsicUnaryType (size, n, cardinalN)
3859 ELSIF c = tsizeN
3860 THEN
3861 RETURN makeIntrinsicUnaryType (tsize, n, cardinalN)
3862 ELSIF c = floatN
3863 THEN
3864 RETURN makeIntrinsicUnaryType (float, n, realN)
3865 ELSIF c = truncN
3866 THEN
3867 RETURN makeIntrinsicUnaryType (trunc, n, integerN)
3868 ELSIF c = ordN
3869 THEN
3870 RETURN makeIntrinsicUnaryType (ord, n, cardinalN)
3871 ELSIF c = chrN
3872 THEN
3873 RETURN makeIntrinsicUnaryType (chr, n, charN)
3874 ELSIF c = capN
3875 THEN
3876 RETURN makeIntrinsicUnaryType (cap, n, charN)
3877 ELSIF c = absN
3878 THEN
3879 RETURN makeIntrinsicUnaryType (abs, n, NIL)
3880 ELSIF c = imN
3881 THEN
3882 RETURN makeIntrinsicUnaryType (im, n, NIL)
3883 ELSIF c = reN
3884 THEN
3885 RETURN makeIntrinsicUnaryType (re, n, NIL)
3886 ELSIF c = cmplxN
3887 THEN
3888 RETURN makeIntrinsicBinaryType (cmplx, n, NIL)
3889 ELSIF c = highN
3890 THEN
3891 RETURN makeIntrinsicUnaryType (high, n, cardinalN)
3892 ELSIF c = incN
3893 THEN
3894 RETURN makeIntrinsicProc (inc, expListLen (n), n)
3895 ELSIF c = decN
3896 THEN
3897 RETURN makeIntrinsicProc (dec, expListLen (n), n)
3898 ELSIF c = inclN
3899 THEN
3900 RETURN makeIntrinsicProc (incl, expListLen (n), n)
3901 ELSIF c = exclN
3902 THEN
3903 RETURN makeIntrinsicProc (excl, expListLen (n), n)
3904 ELSIF c = newN
3905 THEN
3906 RETURN makeIntrinsicProc (new, 1, n)
3907 ELSIF c = disposeN
3908 THEN
3909 RETURN makeIntrinsicProc (dispose, 1, n)
3910 ELSIF c = lengthN
3911 THEN
3912 RETURN makeIntrinsicUnaryType (length, n, cardinalN)
3913 ELSIF c = throwN
3914 THEN
3915 keyc.useThrow ;
3916 RETURN makeIntrinsicProc (throw, 1, n)
3917 END ;
3918 RETURN NIL
3919 END checkIntrinsic ;
3923 checkCHeaders - check to see if the function is a C system function and
3924 requires a header file included.
3927 PROCEDURE checkCHeaders (c: node) ;
3929 name: Name ;
3930 s : node ;
3931 BEGIN
3932 IF isProcedure (c)
3933 THEN
3934 s := getScope (c) ;
3935 IF getSymName (s) = makeKey ('libc')
3936 THEN
3937 name := getSymName (c) ;
3938 IF (name = makeKey ('read')) OR
3939 (name = makeKey ('write')) OR
3940 (name = makeKey ('open')) OR
3941 (name = makeKey ('close'))
3942 THEN
3943 keyc.useUnistd
3947 END checkCHeaders ;
3951 makeFuncCall - builds a function call to c with param list, n.
3954 PROCEDURE makeFuncCall (c, n: node) : node ;
3956 f: node ;
3957 BEGIN
3958 assert ((n=NIL) OR isExpList (n)) ;
3959 IF (c = haltN) AND
3960 (getMainModule () # lookupDef (makeKey ('M2RTS'))) AND
3961 (getMainModule () # lookupImp (makeKey ('M2RTS')))
3962 THEN
3963 addImportedModule (getMainModule (), lookupDef (makeKey ('M2RTS')), FALSE)
3964 END ;
3965 f := checkIntrinsic (c, n) ;
3966 checkCHeaders (c) ;
3967 IF f = NIL
3968 THEN
3969 f := newNode (funccall) ;
3970 f^.funccallF.function := c ;
3971 f^.funccallF.args := n ;
3972 f^.funccallF.type := getType (c) ;
3973 initPair (f^.funccallF.funccallComment) ;
3974 initNodeOpaqueState (f)
3975 END ;
3976 RETURN f
3977 END makeFuncCall ;
3981 isFuncCall - returns TRUE if, n, is a function/procedure call.
3984 PROCEDURE isFuncCall (n: node) : BOOLEAN ;
3985 BEGIN
3986 assert (n # NIL) ;
3987 RETURN n^.kind = funccall
3988 END isFuncCall ;
3992 putType - places, exp, as the type alias to des.
3993 TYPE des = exp ;
3996 PROCEDURE putType (des, exp: node) ;
3997 BEGIN
3998 assert (des#NIL) ;
3999 assert (isType (des)) ;
4000 des^.typeF.type := exp
4001 END putType ;
4005 putTypeHidden - marks type, des, as being a hidden type.
4006 TYPE des ;
4009 PROCEDURE putTypeHidden (des: node) ;
4011 s: node ;
4012 BEGIN
4013 assert (des#NIL) ;
4014 assert (isType (des)) ;
4015 des^.typeF.isHidden := TRUE ;
4016 s := getScope (des) ;
4017 assert (isDef (s)) ;
4018 s^.defF.hasHidden := TRUE
4019 END putTypeHidden ;
4023 isTypeHidden - returns TRUE if type, n, is hidden.
4026 PROCEDURE isTypeHidden (n: node) : BOOLEAN ;
4027 BEGIN
4028 assert (n#NIL) ;
4029 assert (isType (n)) ;
4030 RETURN n^.typeF.isHidden
4031 END isTypeHidden ;
4035 hasHidden - returns TRUE if module, n, has a hidden type.
4038 PROCEDURE hasHidden (n: node) : BOOLEAN ;
4039 BEGIN
4040 assert (isDef (n)) ;
4041 RETURN n^.defF.hasHidden
4042 END hasHidden ;
4046 putTypeOpaque - marks type, des, as being an opaque type.
4047 TYPE des ;
4050 PROCEDURE putTypeOpaque (des: node) ;
4052 s: node ;
4053 BEGIN
4054 assert (des#NIL) ;
4055 assert (isType (des)) ;
4056 des^.typeF.isOpaque := TRUE
4057 END putTypeOpaque ;
4061 isTypeOpaque - returns TRUE if type, n, is an opaque type.
4064 PROCEDURE isTypeOpaque (n: node) : BOOLEAN ;
4065 BEGIN
4066 assert (n#NIL) ;
4067 assert (isType (n)) ;
4068 RETURN n^.typeF.isOpaque
4069 END isTypeOpaque ;
4073 putTypeInternal - marks type, des, as being an internally generated type.
4076 PROCEDURE putTypeInternal (des: node) ;
4077 BEGIN
4078 assert (des#NIL) ;
4079 assert (isType (des)) ;
4080 des^.typeF.isInternal := TRUE
4081 END putTypeInternal ;
4085 isTypeInternal - returns TRUE if type, n, is internal.
4088 PROCEDURE isTypeInternal (n: node) : BOOLEAN ;
4089 BEGIN
4090 assert (n#NIL) ;
4091 assert (isType (n)) ;
4092 RETURN n^.typeF.isInternal
4093 END isTypeInternal ;
4097 putConst - places value, v, into node, n.
4100 PROCEDURE putConst (n: node; v: node) ;
4101 BEGIN
4102 assert (isConst (n)) ;
4103 n^.constF.value := v
4104 END putConst ;
4108 makeLiteralInt - creates and returns a literal node based on an integer type.
4111 PROCEDURE makeLiteralInt (n: Name) : node ;
4113 m: node ;
4114 s: String ;
4115 BEGIN
4116 m := newNode (literal) ;
4117 s := InitStringCharStar (keyToCharStar (n)) ;
4118 WITH m^ DO
4119 literalF.name := n ;
4120 IF DynamicStrings.char (s, -1)='C'
4121 THEN
4122 literalF.type := charN
4123 ELSE
4124 literalF.type := ztypeN
4126 END ;
4127 s := KillString (s) ;
4128 RETURN m
4129 END makeLiteralInt ;
4133 makeLiteralReal - creates and returns a literal node based on a real type.
4136 PROCEDURE makeLiteralReal (n: Name) : node ;
4138 m: node ;
4139 BEGIN
4140 m := newNode (literal) ;
4141 WITH m^ DO
4142 literalF.name := n ;
4143 literalF.type := rtypeN
4144 END ;
4145 RETURN m
4146 END makeLiteralReal ;
4150 makeString - creates and returns a node containing string, n.
4153 PROCEDURE makeString (n: Name) : node ;
4155 m: node ;
4156 BEGIN
4157 m := newNode (string) ;
4158 WITH m^ DO
4159 stringF.name := n ;
4160 stringF.length := lengthKey (n) ;
4161 stringF.isCharCompatible := (stringF.length <= 3) ;
4162 stringF.cstring := toCstring (n) ;
4163 stringF.clength := lenCstring (stringF.cstring) ;
4164 IF stringF.isCharCompatible
4165 THEN
4166 stringF.cchar := toCchar (n)
4167 ELSE
4168 stringF.cchar := NIL
4170 END ;
4171 RETURN m
4172 END makeString ;
4176 getBuiltinConst - creates and returns a builtin const if available.
4179 PROCEDURE getBuiltinConst (n: Name) : node ;
4180 BEGIN
4181 IF n=makeKey ('BITS_PER_UNIT')
4182 THEN
4183 RETURN bitsperunitN
4184 ELSIF n=makeKey ('BITS_PER_WORD')
4185 THEN
4186 RETURN bitsperwordN
4187 ELSIF n=makeKey ('BITS_PER_CHAR')
4188 THEN
4189 RETURN bitspercharN
4190 ELSIF n=makeKey ('UNITS_PER_WORD')
4191 THEN
4192 RETURN unitsperwordN
4193 ELSE
4194 RETURN NIL
4196 END getBuiltinConst ;
4200 lookupInScope - looks up a symbol named, n, from, scope.
4203 PROCEDURE lookupInScope (scope: node; n: Name) : node ;
4204 BEGIN
4205 CASE scope^.kind OF
4207 def : RETURN getSymKey (scope^.defF.decls.symbols, n) |
4208 module : RETURN getSymKey (scope^.moduleF.decls.symbols, n) |
4209 imp : RETURN getSymKey (scope^.impF.decls.symbols, n) |
4210 procedure: RETURN getSymKey (scope^.procedureF.decls.symbols, n) |
4211 record : RETURN getSymKey (scope^.recordF.localSymbols, n)
4214 END lookupInScope ;
4218 lookupBase - return node named n from the base symbol scope.
4221 PROCEDURE lookupBase (n: Name) : node ;
4223 m: node ;
4224 BEGIN
4225 m := getSymKey (baseSymbols, n) ;
4226 IF m=procN
4227 THEN
4228 keyc.useProc
4229 ELSIF (m=complexN) OR (m=longcomplexN) OR (m=shortcomplexN)
4230 THEN
4231 keyc.useComplex
4232 END ;
4233 RETURN m
4234 END lookupBase ;
4238 dumpScopes - display the names of all the scopes stacked.
4241 PROCEDURE dumpScopes ;
4243 h: CARDINAL ;
4244 s: node ;
4245 BEGIN
4246 h := HighIndice (scopeStack) ;
4247 printf ("total scopes stacked %d\n", h);
4249 WHILE h>=1 DO
4250 s := GetIndice (scopeStack, h) ;
4251 out2 (" scope [%d] is %s\n", h, s) ;
4252 DEC (h)
4254 END dumpScopes ;
4258 out0 - write string a to StdOut.
4261 PROCEDURE out0 (a: ARRAY OF CHAR) ;
4263 m: String ;
4264 BEGIN
4265 m := Sprintf0 (InitString (a)) ;
4266 m := KillString (WriteS (StdOut, m))
4267 END out0 ;
4271 out1 - write string a to StdOut using format specifier a.
4274 PROCEDURE out1 (a: ARRAY OF CHAR; s: node) ;
4276 m: String ;
4277 d: CARDINAL ;
4278 BEGIN
4279 m := getFQstring (s) ;
4280 IF EqualArray (m, '')
4281 THEN
4282 d := VAL (CARDINAL, VAL (LONGCARD, s)) ;
4283 m := KillString (m) ;
4284 m := Sprintf1 (InitString ('[%d]'), d)
4285 END ;
4286 m := Sprintf1 (InitString (a), m) ;
4287 m := KillString (WriteS (StdOut, m))
4288 END out1 ;
4292 out2 - write string a to StdOut using format specifier a.
4295 PROCEDURE out2 (a: ARRAY OF CHAR; c: CARDINAL; s: node) ;
4297 m, m1: String ;
4298 BEGIN
4299 m1 := getString (s) ;
4300 m := Sprintf2 (InitString (a), c, m1) ;
4301 m := KillString (WriteS (StdOut, m)) ;
4302 m1 := KillString (m1)
4303 END out2 ;
4307 out3 - write string a to StdOut using format specifier a.
4310 PROCEDURE out3 (a: ARRAY OF CHAR; l: CARDINAL; n: Name; s: node) ;
4312 m, m1, m2: String ;
4313 BEGIN
4314 m1 := InitStringCharStar (keyToCharStar (n)) ;
4315 m2 := getString (s) ;
4316 m := Sprintf3 (InitString (a), l, m1, m2) ;
4317 m := KillString (WriteS (StdOut, m)) ;
4318 m1 := KillString (m1) ;
4319 m2 := KillString (m2)
4320 END out3 ;
4324 lookupSym - returns the symbol named, n, from the scope stack.
4327 PROCEDURE lookupSym (n: Name) : node ;
4329 s, m: node ;
4330 l, h: CARDINAL ;
4331 BEGIN
4332 l := LowIndice (scopeStack) ;
4333 h := HighIndice (scopeStack) ;
4335 WHILE h>=l DO
4336 s := GetIndice (scopeStack, h) ;
4337 m := lookupInScope (s, n) ;
4338 IF debugScopes AND (m=NIL)
4339 THEN
4340 out3 (" [%d] search for symbol name %s in scope %s\n", h, n, s)
4341 END ;
4342 IF m#NIL
4343 THEN
4344 IF debugScopes
4345 THEN
4346 out3 (" [%d] search for symbol name %s in scope %s (found)\n", h, n, s)
4347 END ;
4348 RETURN m
4349 END ;
4350 DEC (h)
4351 END ;
4352 RETURN lookupBase (n)
4353 END lookupSym ;
4357 getSymName - returns the name of symbol, n.
4360 PROCEDURE getSymName (n: node) : Name ;
4361 BEGIN
4362 WITH n^ DO
4363 CASE kind OF
4365 new : RETURN makeKey ('NEW') |
4366 dispose : RETURN makeKey ('DISPOSE') |
4367 length : RETURN makeKey ('LENGTH') |
4368 inc : RETURN makeKey ('INC') |
4369 dec : RETURN makeKey ('DEC') |
4370 incl : RETURN makeKey ('INCL') |
4371 excl : RETURN makeKey ('EXCL') |
4372 nil : RETURN makeKey ('NIL') |
4373 true : RETURN makeKey ('TRUE') |
4374 false : RETURN makeKey ('FALSE') |
4375 address : RETURN makeKey ('ADDRESS') |
4376 loc : RETURN makeKey ('LOC') |
4377 byte : RETURN makeKey ('BYTE') |
4378 word : RETURN makeKey ('WORD') |
4379 csizet : RETURN makeKey ('CSIZE_T') |
4380 cssizet : RETURN makeKey ('CSSIZE_T') |
4381 (* base types. *)
4382 boolean : RETURN makeKey ('BOOLEAN') |
4383 proc : RETURN makeKey ('PROC') |
4384 char : RETURN makeKey ('CHAR') |
4385 cardinal : RETURN makeKey ('CARDINAL') |
4386 longcard : RETURN makeKey ('LONGCARD') |
4387 shortcard : RETURN makeKey ('SHORTCARD') |
4388 integer : RETURN makeKey ('INTEGER') |
4389 longint : RETURN makeKey ('LONGINT') |
4390 shortint : RETURN makeKey ('SHORTINT') |
4391 real : RETURN makeKey ('REAL') |
4392 longreal : RETURN makeKey ('LONGREAL') |
4393 shortreal : RETURN makeKey ('SHORTREAL') |
4394 bitset : RETURN makeKey ('BITSET') |
4395 ztype : RETURN makeKey ('_ZTYPE') |
4396 rtype : RETURN makeKey ('_RTYPE') |
4397 complex : RETURN makeKey ('COMPLEX') |
4398 longcomplex : RETURN makeKey ('LONGCOMPLEX') |
4399 shortcomplex : RETURN makeKey ('SHORTCOMPLEX') |
4401 (* language features and compound type attributes. *)
4402 type : RETURN typeF.name |
4403 record : RETURN NulName |
4404 varient : RETURN NulName |
4405 var : RETURN varF.name |
4406 enumeration : RETURN NulName |
4407 subrange : RETURN NulName |
4408 pointer : RETURN NulName |
4409 array : RETURN NulName |
4410 string : RETURN stringF.name |
4411 const : RETURN constF.name |
4412 literal : RETURN literalF.name |
4413 varparam : RETURN NulName |
4414 param : RETURN NulName |
4415 optarg : RETURN NulName |
4416 recordfield : RETURN recordfieldF.name |
4417 varientfield : RETURN varientfieldF.name |
4418 enumerationfield: RETURN enumerationfieldF.name |
4419 set : RETURN NulName |
4420 proctype : RETURN NulName |
4421 subscript : RETURN NulName |
4422 (* blocks. *)
4423 procedure : RETURN procedureF.name |
4424 def : RETURN defF.name |
4425 imp : RETURN impF.name |
4426 module : RETURN moduleF.name |
4427 (* statements. *)
4428 loop,
4429 while,
4430 for,
4431 repeat,
4433 elsif,
4434 assignment : RETURN NulName |
4435 (* expressions. *)
4436 constexp,
4437 deref,
4438 arrayref,
4439 componentref,
4440 cast,
4441 val,
4442 plus,
4443 sub,
4444 div,
4445 mod,
4446 mult,
4447 divide,
4449 neg,
4450 equal,
4451 notequal,
4452 less,
4453 greater,
4454 greequal,
4455 lessequal : RETURN NulName |
4456 adr : RETURN makeKey ('ADR') |
4457 size : RETURN makeKey ('SIZE') |
4458 tsize : RETURN makeKey ('TSIZE') |
4459 chr : RETURN makeKey ('CHR') |
4460 abs : RETURN makeKey ('ABS') |
4461 ord : RETURN makeKey ('ORD') |
4462 float : RETURN makeKey ('FLOAT') |
4463 trunc : RETURN makeKey ('TRUNC') |
4464 high : RETURN makeKey ('HIGH') |
4465 throw : RETURN makeKey ('THROW') |
4466 unreachable : RETURN makeKey ('builtin_unreachable') |
4467 cmplx : RETURN makeKey ('CMPLX') |
4468 re : RETURN makeKey ('RE') |
4469 im : RETURN makeKey ('IM') |
4470 max : RETURN makeKey ('MAX') |
4471 min : RETURN makeKey ('MIN') |
4472 pointerref : RETURN NulName |
4473 funccall : RETURN NulName |
4474 identlist : RETURN NulName
4476 ELSE
4477 HALT
4480 END getSymName ;
4484 isUnary - returns TRUE if, n, is an unary node.
4487 PROCEDURE isUnary (n: node) : BOOLEAN ;
4488 BEGIN
4489 assert (n # NIL) ;
4490 CASE n^.kind OF
4492 length,
4495 deref,
4496 high,
4497 chr,
4498 cap,
4499 abs,
4500 ord,
4501 float,
4502 trunc,
4503 constexp,
4504 not,
4505 neg,
4506 adr,
4507 size,
4508 tsize,
4509 min,
4510 max : RETURN TRUE
4512 ELSE
4513 RETURN FALSE
4515 END isUnary ;
4519 isBinary - returns TRUE if, n, is an binary node.
4522 PROCEDURE isBinary (n: node) : BOOLEAN ;
4523 BEGIN
4524 assert (n # NIL) ;
4525 CASE n^.kind OF
4527 cmplx,
4528 and,
4530 equal,
4531 notequal,
4532 less,
4533 greater,
4534 greequal,
4535 lessequal,
4536 val,
4537 cast,
4538 plus,
4539 sub,
4540 div,
4541 mod,
4542 mult,
4543 divide,
4544 in : RETURN TRUE
4546 ELSE
4547 RETURN FALSE
4549 END isBinary ;
4553 makeUnary - create a unary expression node with, e, as the argument
4554 and res as the return type.
4557 PROCEDURE makeUnary (k: nodeT; e: node; res: node) : node ;
4559 n: node ;
4560 BEGIN
4561 IF k=plus
4562 THEN
4563 RETURN e
4564 ELSE
4565 n := newNode (k) ;
4566 WITH n^ DO
4567 CASE kind OF
4569 min,
4570 max,
4571 throw,
4574 deref,
4575 high,
4576 chr,
4577 cap,
4578 abs,
4579 ord,
4580 float,
4581 trunc,
4582 length,
4583 constexp,
4584 not,
4585 neg,
4586 adr,
4587 size,
4588 tsize: WITH unaryF DO
4589 arg := e ;
4590 resultType := res
4595 END ;
4596 RETURN n
4597 END makeUnary ;
4601 isLeafString - returns TRUE if n is a leaf node which is a string constant.
4604 PROCEDURE isLeafString (n: node) : BOOLEAN ;
4605 BEGIN
4606 RETURN isString (n) OR
4607 (isLiteral (n) AND (getType (n) = charN)) OR
4608 (isConst (n) AND (getExprType (n) = charN))
4609 END isLeafString ;
4613 getLiteralStringContents - return the contents of a literal node as a string.
4616 PROCEDURE getLiteralStringContents (n: node) : String ;
4618 number,
4619 content,
4620 s : String ;
4621 BEGIN
4622 assert (n^.kind = literal) ;
4623 s := InitStringCharStar (keyToCharStar (n^.literalF.name)) ;
4624 content := NIL ;
4625 IF n^.literalF.type = charN
4626 THEN
4627 IF DynamicStrings.char (s, -1) = 'C'
4628 THEN
4629 IF DynamicStrings.Length (s) > 1
4630 THEN
4631 number := DynamicStrings.Slice (s, 0, -1) ;
4632 content := DynamicStrings.InitStringChar (VAL (CHAR, ostoc (number))) ;
4633 number := DynamicStrings.KillString (number)
4634 ELSE
4635 content := DynamicStrings.InitStringChar ('C')
4637 ELSE
4638 content := DynamicStrings.Dup (s)
4640 ELSE
4641 metaError1 ('cannot obtain string contents from {%1k}', n^.literalF.name)
4642 END ;
4643 s := DynamicStrings.KillString (s) ;
4644 RETURN content
4645 END getLiteralStringContents ;
4649 getStringContents - return the string contents of a constant, literal,
4650 string or a constexp node.
4653 PROCEDURE getStringContents (n: node) : String ;
4654 BEGIN
4655 IF isConst (n)
4656 THEN
4657 RETURN getStringContents (n^.constF.value)
4658 ELSIF isLiteral (n)
4659 THEN
4660 RETURN getLiteralStringContents (n)
4661 ELSIF isString (n)
4662 THEN
4663 RETURN getString (n)
4664 ELSIF isConstExp (n)
4665 THEN
4666 RETURN getStringContents (n^.unaryF.arg)
4667 END ;
4668 HALT
4669 END getStringContents ;
4673 addNames -
4676 PROCEDURE addNames (a, b: node) : Name ;
4678 sa, sb: String ;
4679 n : Name ;
4680 BEGIN
4681 sa := DynamicStrings.InitStringCharStar (keyToCharStar (getSymName (a))) ;
4682 sb := DynamicStrings.InitStringCharStar (keyToCharStar (getSymName (b))) ;
4683 sa := ConCat (sa, sb) ;
4684 n := makekey (DynamicStrings.string (sa)) ;
4685 sa := KillString (sa) ;
4686 sb := KillString (sb) ;
4687 RETURN n
4688 END addNames ;
4692 resolveString -
4695 PROCEDURE resolveString (n: node) : node ;
4696 BEGIN
4697 WHILE isConst (n) OR isConstExp (n) DO
4698 IF isConst (n)
4699 THEN
4700 n := n^.constF.value
4701 ELSE
4702 n := n^.unaryF.arg
4704 END ;
4705 IF n^.kind = plus
4706 THEN
4707 n := makeString (addNames (resolveString (n^.binaryF.left),
4708 resolveString (n^.binaryF.right)))
4709 END ;
4710 RETURN n
4711 END resolveString ;
4715 foldBinary -
4718 PROCEDURE foldBinary (k: nodeT; l, r: node; res: node) : node ;
4720 n : node ;
4722 rs: String ;
4723 BEGIN
4724 n := NIL ;
4725 IF (k = plus) AND isLeafString (l) AND isLeafString (r)
4726 THEN
4727 ls := getStringContents (l) ;
4728 rs := getStringContents (r) ;
4729 ls := DynamicStrings.Add (ls, rs) ;
4730 n := makeString (makekey (DynamicStrings.string (ls))) ;
4731 ls := DynamicStrings.KillString (ls) ;
4732 rs := DynamicStrings.KillString (rs)
4733 END ;
4734 RETURN n
4735 END foldBinary ;
4739 makeBinary - create a binary node with left/right/result type: l, r and resultType.
4742 PROCEDURE makeBinary (k: nodeT; l, r: node; resultType: node) : node ;
4744 n: node ;
4745 BEGIN
4746 n := foldBinary (k, l, r, resultType) ;
4747 IF n = NIL
4748 THEN
4749 n := doMakeBinary (k, l, r, resultType)
4750 END ;
4751 RETURN n
4752 END makeBinary ;
4756 doMakeBinary - returns a binary node containing left/right/result values
4757 l, r, res, with a node operator, k.
4760 PROCEDURE doMakeBinary (k: nodeT; l, r: node; res: node) : node ;
4762 n: node ;
4763 BEGIN
4764 n := newNode (k) ;
4765 WITH n^ DO
4766 CASE kind OF
4768 cmplx,
4769 equal,
4770 notequal,
4771 less,
4772 greater,
4773 greequal,
4774 lessequal,
4775 and,
4777 cast,
4778 val,
4779 plus,
4780 sub,
4781 div,
4782 mod,
4783 mult,
4784 divide,
4785 in : WITH binaryF DO
4786 left := l ;
4787 right := r ;
4788 resultType := res
4792 END ;
4793 RETURN n
4794 END doMakeBinary ;
4798 doMakeComponentRef -
4801 PROCEDURE doMakeComponentRef (rec, field: node) : node ;
4803 n: node ;
4804 BEGIN
4805 n := newNode (componentref) ;
4806 n^.componentrefF.rec := rec ;
4807 n^.componentrefF.field := field ;
4808 n^.componentrefF.resultType := getType (field) ;
4809 initNodeOpaqueState (n) ;
4810 RETURN n
4811 END doMakeComponentRef ;
4815 makeComponentRef - build a componentref node which accesses, field,
4816 within, record, rec.
4819 PROCEDURE makeComponentRef (rec, field: node) : node ;
4821 n, a: node ;
4822 BEGIN
4824 n := getLastOp (rec) ;
4825 IF (n#NIL) AND (isDeref (n) OR isPointerRef (n)) AND
4826 (skipType (getType (rec)) = skipType (getType (n)))
4827 THEN
4828 a := n^.unaryF.arg ;
4829 n^.kind := pointerref ;
4830 n^.pointerrefF.ptr := a ;
4831 n^.pointerrefF.field := field ;
4832 n^.pointerrefF.resultType := getType (field) ;
4833 RETURN n
4834 ELSE
4835 RETURN doMakeComponentRef (rec, field)
4838 IF isDeref (rec)
4839 THEN
4840 a := rec^.unaryF.arg ;
4841 rec^.kind := pointerref ;
4842 rec^.pointerrefF.ptr := a ;
4843 rec^.pointerrefF.field := field ;
4844 rec^.pointerrefF.resultType := getType (field) ;
4845 initNodeOpaqueState (rec) ;
4846 RETURN rec
4847 ELSE
4848 RETURN doMakeComponentRef (rec, field)
4850 END makeComponentRef ;
4854 isComponentRef -
4857 PROCEDURE isComponentRef (n: node) : BOOLEAN ;
4858 BEGIN
4859 assert (n # NIL) ;
4860 RETURN n^.kind = componentref
4861 END isComponentRef ;
4865 makePointerRef - build a pointerref node which accesses, field,
4866 within, pointer to record, ptr.
4869 PROCEDURE makePointerRef (ptr, field: node) : node ;
4871 n: node ;
4872 BEGIN
4873 n := newNode (pointerref) ;
4874 n^.pointerrefF.ptr := ptr ;
4875 n^.pointerrefF.field := field ;
4876 n^.pointerrefF.resultType := getType (field) ;
4877 initNodeOpaqueState (n) ;
4878 RETURN n
4879 END makePointerRef ;
4883 isPointerRef - returns TRUE if, n, is a pointerref node.
4886 PROCEDURE isPointerRef (n: node) : BOOLEAN ;
4887 BEGIN
4888 assert (n # NIL) ;
4889 RETURN n^.kind = pointerref
4890 END isPointerRef ;
4894 makeArrayRef - build an arrayref node which access element,
4895 index, in, array. array is a variable/expression/constant
4896 which has a type array.
4899 PROCEDURE makeArrayRef (array, index: node) : node ;
4901 n, t: node ;
4902 i, j: CARDINAL ;
4903 BEGIN
4904 n := newNode (arrayref) ;
4905 n^.arrayrefF.array := array ;
4906 n^.arrayrefF.index := index ;
4907 t := array ;
4908 j := expListLen (index) ;
4909 i := 1 ;
4910 t := skipType (getType (t)) ;
4911 REPEAT
4912 IF isArray (t)
4913 THEN
4914 t := skipType (getType (t))
4915 ELSE
4916 metaError2 ('cannot access {%1N} dimension of array {%2a}', i, t)
4917 END ;
4918 INC (i)
4919 UNTIL i > j ;
4920 n^.arrayrefF.resultType := t ;
4921 RETURN n
4922 END makeArrayRef ;
4926 isArrayRef - returns TRUE if the node was an arrayref.
4929 PROCEDURE isArrayRef (n: node) : BOOLEAN ;
4930 BEGIN
4931 assert (n # NIL) ;
4932 RETURN n^.kind = arrayref
4933 END isArrayRef ;
4937 makeDeRef - dereferences the pointer defined by, n.
4940 PROCEDURE makeDeRef (n: node) : node ;
4942 t: node ;
4943 BEGIN
4944 t := skipType (getType (n)) ;
4945 assert (isPointer (t)) ;
4946 RETURN makeUnary (deref, n, getType (t))
4947 END makeDeRef ;
4951 isDeref - returns TRUE if, n, is a deref node.
4954 PROCEDURE isDeref (n: node) : BOOLEAN ;
4955 BEGIN
4956 assert (n # NIL) ;
4957 RETURN n^.kind = deref
4958 END isDeref ;
4962 makeBase - create a base type or constant.
4963 It only supports the base types and constants
4964 enumerated below.
4967 PROCEDURE makeBase (k: nodeT) : node ;
4969 n: node ;
4970 BEGIN
4971 n := newNode (k) ;
4972 WITH n^ DO
4973 CASE k OF
4975 new,
4976 dispose,
4977 length,
4978 inc,
4979 dec,
4980 incl,
4981 excl,
4982 nil,
4983 true,
4984 false,
4985 address,
4986 loc,
4987 byte,
4988 word,
4989 csizet,
4990 cssizet,
4991 char,
4992 cardinal,
4993 longcard,
4994 shortcard,
4995 integer,
4996 longint,
4997 shortint,
4998 real,
4999 longreal,
5000 shortreal,
5001 bitset,
5002 boolean,
5003 proc,
5004 ztype,
5005 rtype,
5006 complex,
5007 longcomplex,
5008 shortcomplex,
5009 adr,
5010 chr,
5011 cap,
5012 abs,
5013 float,
5014 trunc,
5015 ord,
5016 high,
5017 throw,
5020 cmplx,
5021 size,
5022 tsize,
5023 val,
5024 min,
5025 max : (* legal kind. *) |
5027 ELSE
5028 HALT
5030 END ;
5031 RETURN n
5032 END makeBase ;
5036 makeBinaryTok - creates and returns a boolean type node with,
5037 l, and, r, nodes.
5040 PROCEDURE makeBinaryTok (op: toktype; l, r: node) : node ;
5041 BEGIN
5042 IF op=equaltok
5043 THEN
5044 RETURN makeBinary (equal, l, r, booleanN)
5045 ELSIF (op=hashtok) OR (op=lessgreatertok)
5046 THEN
5047 RETURN makeBinary (notequal, l, r, booleanN)
5048 ELSIF op=lesstok
5049 THEN
5050 RETURN makeBinary (less, l, r, booleanN)
5051 ELSIF op=greatertok
5052 THEN
5053 RETURN makeBinary (greater, l, r, booleanN)
5054 ELSIF op=greaterequaltok
5055 THEN
5056 RETURN makeBinary (greequal, l, r, booleanN)
5057 ELSIF op=lessequaltok
5058 THEN
5059 RETURN makeBinary (lessequal, l, r, booleanN)
5060 ELSIF op=andtok
5061 THEN
5062 RETURN makeBinary (and, l, r, booleanN)
5063 ELSIF op=ortok
5064 THEN
5065 RETURN makeBinary (or, l, r, booleanN)
5066 ELSIF op=plustok
5067 THEN
5068 RETURN makeBinary (plus, l, r, NIL)
5069 ELSIF op=minustok
5070 THEN
5071 RETURN makeBinary (sub, l, r, NIL)
5072 ELSIF op=divtok
5073 THEN
5074 RETURN makeBinary (div, l, r, NIL)
5075 ELSIF op=timestok
5076 THEN
5077 RETURN makeBinary (mult, l, r, NIL)
5078 ELSIF op=modtok
5079 THEN
5080 RETURN makeBinary (mod, l, r, NIL)
5081 ELSIF op=intok
5082 THEN
5083 RETURN makeBinary (in, l, r, NIL)
5084 ELSIF op=dividetok
5085 THEN
5086 RETURN makeBinary (divide, l, r, NIL)
5087 ELSE
5088 HALT (* most likely op needs a clause as above. *)
5090 END makeBinaryTok ;
5094 makeUnaryTok - creates and returns a boolean type node with,
5095 e, node.
5098 PROCEDURE makeUnaryTok (op: toktype; e: node) : node ;
5099 BEGIN
5100 IF op=nottok
5101 THEN
5102 RETURN makeUnary (not, e, booleanN)
5103 ELSIF op=plustok
5104 THEN
5105 RETURN makeUnary (plus, e, NIL)
5106 ELSIF op=minustok
5107 THEN
5108 RETURN makeUnary (neg, e, NIL)
5109 ELSE
5110 HALT (* most likely op needs a clause as above. *)
5112 END makeUnaryTok ;
5116 isOrdinal - returns TRUE if, n, is an ordinal type.
5119 PROCEDURE isOrdinal (n: node) : BOOLEAN ;
5120 BEGIN
5121 CASE n^.kind OF
5123 address,
5124 loc,
5125 byte,
5126 word,
5127 csizet,
5128 cssizet,
5129 char,
5130 integer,
5131 longint,
5132 shortint,
5133 cardinal,
5134 longcard,
5135 shortcard,
5136 bitset : RETURN TRUE
5138 ELSE
5139 RETURN FALSE
5141 END isOrdinal ;
5145 getType - returns the type associated with node, n.
5148 PROCEDURE getType (n: node) : node ;
5149 BEGIN
5150 WITH n^ DO
5151 CASE kind OF
5153 new,
5154 dispose : RETURN NIL |
5155 length : RETURN cardinalN |
5156 inc,
5157 dec,
5158 incl,
5159 excl : RETURN NIL |
5160 nil : RETURN addressN |
5161 true,
5162 false : RETURN booleanN |
5163 address : RETURN n |
5164 loc : RETURN n |
5165 byte : RETURN n |
5166 word : RETURN n |
5167 csizet : RETURN n |
5168 cssizet : RETURN n |
5169 (* base types. *)
5170 boolean : RETURN n |
5171 proc : RETURN n |
5172 char : RETURN n |
5173 cardinal : RETURN n |
5174 longcard : RETURN n |
5175 shortcard : RETURN n |
5176 integer : RETURN n |
5177 longint : RETURN n |
5178 shortint : RETURN n |
5179 real : RETURN n |
5180 longreal : RETURN n |
5181 shortreal : RETURN n |
5182 bitset : RETURN n |
5183 ztype : RETURN n |
5184 rtype : RETURN n |
5185 complex : RETURN n |
5186 longcomplex : RETURN n |
5187 shortcomplex : RETURN n |
5189 (* language features and compound type attributes. *)
5190 type : RETURN typeF.type |
5191 record : RETURN n |
5192 varient : RETURN n |
5193 var : RETURN varF.type |
5194 enumeration : RETURN n |
5195 subrange : RETURN subrangeF.type |
5196 array : RETURN arrayF.type |
5197 string : RETURN charN |
5198 const : RETURN constF.type |
5199 literal : RETURN literalF.type |
5200 varparam : RETURN varparamF.type |
5201 param : RETURN paramF.type |
5202 optarg : RETURN optargF.type |
5203 pointer : RETURN pointerF.type |
5204 recordfield : RETURN recordfieldF.type |
5205 varientfield : RETURN n |
5206 enumerationfield: RETURN enumerationfieldF.type |
5207 set : RETURN setF.type |
5208 proctype : RETURN proctypeF.returnType |
5209 subscript : RETURN subscriptF.type |
5210 (* blocks. *)
5211 procedure : RETURN procedureF.returnType |
5212 throw : RETURN NIL |
5213 unreachable : RETURN NIL |
5214 def,
5215 imp,
5216 module,
5217 (* statements. *)
5218 loop,
5219 while,
5220 for,
5221 repeat,
5223 elsif,
5224 assignment : HALT |
5225 (* expressions. *)
5226 cmplx,
5227 cast,
5228 val,
5229 plus,
5230 sub,
5231 div,
5232 mod,
5233 mult,
5234 divide : RETURN binaryF.resultType |
5235 in : RETURN booleanN |
5236 max,
5237 min,
5240 abs,
5241 constexp,
5242 deref,
5243 neg,
5244 adr,
5245 size,
5246 tsize : RETURN unaryF.resultType |
5247 and,
5249 not,
5250 equal,
5251 notequal,
5252 less,
5253 greater,
5254 greequal,
5255 lessequal : RETURN booleanN |
5256 trunc : RETURN integerN |
5257 float : RETURN realN |
5258 high : RETURN cardinalN |
5259 ord : RETURN cardinalN |
5260 chr : RETURN charN |
5261 cap : RETURN charN |
5262 arrayref : RETURN arrayrefF.resultType |
5263 componentref : RETURN componentrefF.resultType |
5264 pointerref : RETURN pointerrefF.resultType |
5265 funccall : RETURN funccallF.type |
5266 setvalue : RETURN setvalueF.type
5269 END ;
5270 HALT
5271 END getType ;
5275 mixTypes -
5278 PROCEDURE mixTypes (a, b: node) : node ;
5279 BEGIN
5280 IF (a = addressN) OR (b = addressN)
5281 THEN
5282 RETURN addressN
5283 END ;
5284 RETURN a
5285 END mixTypes ;
5289 doSetExprType -
5292 PROCEDURE doSetExprType (VAR t: node; n: node) : node ;
5293 BEGIN
5294 IF t = NIL
5295 THEN
5296 t := n
5297 END ;
5298 RETURN t
5299 END doSetExprType ;
5303 getMaxMinType -
5306 PROCEDURE getMaxMinType (n: node) : node ;
5307 BEGIN
5308 IF isVar (n) OR isConst (n)
5309 THEN
5310 RETURN getType (n)
5311 ELSIF isConstExp (n)
5312 THEN
5313 n := getExprType (n^.unaryF.arg) ;
5314 IF n = bitsetN
5315 THEN
5316 RETURN ztypeN
5317 ELSE
5318 RETURN n
5320 ELSE
5321 RETURN n
5323 END getMaxMinType ;
5327 doGetFuncType -
5330 PROCEDURE doGetFuncType (n: node) : node ;
5332 result: node ;
5333 BEGIN
5334 assert (isFuncCall (n)) ;
5335 result := doSetExprType (n^.funccallF.type, getType (n^.funccallF.function)) ;
5336 initNodeOpaqueState (n) ; (* Update now that the return type is known. *)
5337 RETURN result
5338 END doGetFuncType ;
5342 doGetExprType - works out the type which is associated with node, n.
5345 PROCEDURE doGetExprType (n: node) : node ;
5346 BEGIN
5347 WITH n^ DO
5348 CASE kind OF
5350 max,
5351 min : RETURN getMaxMinType (n^.unaryF.arg) |
5352 cast,
5353 val : RETURN doSetExprType (n^.binaryF.resultType, n^.binaryF.left) |
5354 halt,
5355 new,
5356 dispose : RETURN NIL |
5357 inc,
5358 dec,
5359 incl,
5360 excl : RETURN NIL |
5361 nil : RETURN addressN |
5362 true,
5363 false : RETURN booleanN |
5364 address : RETURN n |
5365 loc : RETURN n |
5366 byte : RETURN n |
5367 word : RETURN n |
5368 csizet : RETURN n |
5369 cssizet : RETURN n |
5370 (* base types. *)
5371 boolean : RETURN n |
5372 proc : RETURN n |
5373 char : RETURN n |
5374 cardinal : RETURN n |
5375 longcard : RETURN n |
5376 shortcard : RETURN n |
5377 integer : RETURN n |
5378 longint : RETURN n |
5379 shortint : RETURN n |
5380 real : RETURN n |
5381 longreal : RETURN n |
5382 shortreal : RETURN n |
5383 bitset : RETURN n |
5384 ztype : RETURN n |
5385 rtype : RETURN n |
5386 complex : RETURN n |
5387 longcomplex : RETURN n |
5388 shortcomplex : RETURN n |
5390 (* language features and compound type attributes. *)
5391 type : RETURN typeF.type |
5392 record : RETURN n |
5393 varient : RETURN n |
5394 var : RETURN varF.type |
5395 enumeration : RETURN n |
5396 subrange : RETURN subrangeF.type |
5397 array : RETURN arrayF.type |
5398 string : RETURN charN |
5399 const : RETURN doSetExprType (constF.type, getExprType (constF.value)) |
5400 literal : RETURN literalF.type |
5401 varparam : RETURN varparamF.type |
5402 param : RETURN paramF.type |
5403 optarg : RETURN optargF.type |
5404 pointer : RETURN pointerF.type |
5405 recordfield : RETURN recordfieldF.type |
5406 varientfield : RETURN n |
5407 enumerationfield: RETURN enumerationfieldF.type |
5408 set : RETURN setF.type |
5409 proctype : RETURN proctypeF.returnType |
5410 subscript : RETURN subscriptF.type |
5411 (* blocks. *)
5412 procedure : RETURN procedureF.returnType |
5413 throw : RETURN NIL |
5414 unreachable : RETURN NIL |
5415 def,
5416 imp,
5417 module,
5418 (* statements. *)
5419 loop,
5420 while,
5421 for,
5422 repeat,
5424 elsif,
5425 assignment : HALT |
5426 (* expressions. *)
5427 plus,
5428 sub,
5429 div,
5430 mod,
5431 mult,
5432 divide : RETURN doSetExprType (binaryF.resultType, mixTypes (getExprType (binaryF.left), getExprType (binaryF.right))) |
5434 and,
5436 equal,
5437 notequal,
5438 less,
5439 greater,
5440 greequal,
5441 lessequal : RETURN doSetExprType (binaryF.resultType, booleanN) |
5442 cmplx : RETURN doSetExprType (binaryF.resultType, complexN) |
5443 abs,
5444 constexp,
5445 deref,
5446 neg : RETURN doSetExprType (unaryF.resultType, getExprType (unaryF.arg)) |
5447 adr : RETURN doSetExprType (unaryF.resultType, addressN) |
5448 size,
5449 tsize : RETURN doSetExprType (unaryF.resultType, cardinalN) |
5450 high,
5451 ord : RETURN doSetExprType (unaryF.resultType, cardinalN) |
5452 float : RETURN doSetExprType (unaryF.resultType, realN) |
5453 trunc : RETURN doSetExprType (unaryF.resultType, integerN) |
5454 chr : RETURN doSetExprType (unaryF.resultType, charN) |
5455 cap : RETURN doSetExprType (unaryF.resultType, charN) |
5456 not : RETURN doSetExprType (unaryF.resultType, booleanN) |
5457 re : RETURN doSetExprType (unaryF.resultType, realN) |
5458 im : RETURN doSetExprType (unaryF.resultType, realN) |
5459 arrayref : RETURN arrayrefF.resultType |
5460 componentref : RETURN componentrefF.resultType |
5461 pointerref : RETURN pointerrefF.resultType |
5462 funccall : RETURN doSetExprType (funccallF.type, doGetFuncType (n)) |
5463 setvalue : RETURN setvalueF.type
5466 END ;
5467 HALT
5468 END doGetExprType ;
5472 getExprType - return the expression type.
5475 PROCEDURE getExprType (n: node) : node ;
5477 t: node ;
5478 BEGIN
5479 IF isFuncCall (n) AND (getType (n) # NIL) AND isProcType (skipType (getType (n)))
5480 THEN
5481 RETURN getType (skipType (getType (n)))
5482 END ;
5483 t := getType (n) ;
5484 IF t = NIL
5485 THEN
5486 t := doGetExprType (n)
5487 END ;
5488 RETURN t
5489 END getExprType ;
5493 skipType - skips over type aliases.
5496 PROCEDURE skipType (n: node) : node ;
5497 BEGIN
5498 WHILE (n#NIL) AND isType (n) AND (NOT isCDataType (n)) DO
5499 IF getType (n) = NIL
5500 THEN
5501 (* this will occur if, n, is an opaque type. *)
5502 RETURN n
5503 END ;
5504 n := getType (n)
5505 END ;
5506 RETURN n
5507 END skipType ;
5511 getScope - returns the scope associated with node, n.
5514 PROCEDURE getScope (n: node) : node ;
5515 BEGIN
5516 WITH n^ DO
5517 CASE kind OF
5519 stmtseq,
5520 exit,
5521 return,
5522 comment,
5523 identlist,
5524 setvalue,
5525 halt,
5526 new,
5527 dispose,
5528 length,
5529 inc,
5530 dec,
5531 incl,
5532 excl,
5533 nil,
5534 true,
5535 false : RETURN NIL |
5536 address,
5537 loc,
5538 byte,
5539 word,
5540 csizet,
5541 cssizet : RETURN systemN |
5542 (* base types. *)
5543 boolean,
5544 proc,
5545 char,
5546 cardinal,
5547 longcard,
5548 shortcard,
5549 integer,
5550 longint,
5551 shortint,
5552 real,
5553 longreal,
5554 shortreal,
5555 bitset,
5556 ztype,
5557 rtype,
5558 complex,
5559 longcomplex,
5560 shortcomplex : RETURN NIL |
5561 (* language features and compound type attributes. *)
5562 type : RETURN typeF.scope |
5563 record : RETURN recordF.scope |
5564 varient : RETURN varientF.scope |
5565 var : RETURN varF.scope |
5566 enumeration : RETURN enumerationF.scope |
5567 subrange : RETURN subrangeF.scope |
5568 array : RETURN arrayF.scope |
5569 string : RETURN NIL |
5570 const : RETURN constF.scope |
5571 literal : RETURN NIL |
5572 varparam : RETURN varparamF.scope |
5573 param : RETURN paramF.scope |
5574 optarg : RETURN optargF.scope |
5575 pointer : RETURN pointerF.scope |
5576 recordfield : RETURN recordfieldF.scope |
5577 varientfield : RETURN varientfieldF.scope |
5578 enumerationfield: RETURN enumerationfieldF.scope |
5579 set : RETURN setF.scope |
5580 proctype : RETURN proctypeF.scope |
5581 subscript : RETURN NIL |
5582 (* blocks. *)
5583 procedure : RETURN procedureF.scope |
5584 def,
5585 imp,
5586 module,
5587 (* statements. *)
5588 case,
5589 loop,
5590 while,
5591 for,
5592 repeat,
5594 elsif,
5595 assignment : RETURN NIL |
5596 (* expressions. *)
5597 componentref,
5598 pointerref,
5599 arrayref,
5600 chr,
5601 cap,
5602 ord,
5603 float,
5604 trunc,
5605 high,
5606 cast,
5607 val,
5608 plus,
5609 sub,
5610 div,
5611 mod,
5612 mult,
5613 divide,
5614 in : RETURN NIL |
5615 neg : RETURN NIL |
5616 lsl,
5617 lsr,
5618 lor,
5619 land,
5620 lnot,
5621 lxor,
5622 and,
5624 not,
5625 constexp,
5626 deref,
5627 equal,
5628 notequal,
5629 less,
5630 greater,
5631 greequal,
5632 lessequal : RETURN NIL |
5633 adr,
5634 size,
5635 tsize,
5636 throw : RETURN systemN |
5637 unreachable,
5638 cmplx, re, im,
5639 min,
5640 max : RETURN NIL |
5641 vardecl : RETURN vardeclF.scope |
5642 funccall : RETURN NIL |
5643 explist : RETURN NIL |
5644 caselabellist : RETURN NIL |
5645 caselist : RETURN NIL |
5646 range : RETURN NIL |
5647 varargs : RETURN varargsF.scope
5651 END getScope ;
5655 foreachDefModuleDo - foreach definition node, n, in the module universe,
5656 call p (n).
5659 PROCEDURE foreachDefModuleDo (p: performOperation) ;
5660 BEGIN
5661 ForeachIndiceInIndexDo (defUniverseI, p)
5662 END foreachDefModuleDo ;
5666 foreachModModuleDo - foreach implementation or module node, n, in the module universe,
5667 call p (n).
5670 PROCEDURE foreachModModuleDo (p: performOperation) ;
5671 BEGIN
5672 ForeachIndiceInIndexDo (modUniverseI, p)
5673 END foreachModModuleDo ;
5677 openOutput -
5680 PROCEDURE openOutput ;
5682 s: String ;
5683 BEGIN
5684 s := getOutputFile () ;
5685 IF EqualArray (s, '-')
5686 THEN
5687 outputFile := StdOut
5688 ELSE
5689 outputFile := OpenToWrite (s)
5690 END ;
5691 mcStream.setDest (outputFile)
5692 END openOutput ;
5696 closeOutput -
5699 PROCEDURE closeOutput ;
5701 s: String ;
5702 BEGIN
5703 s := getOutputFile () ;
5704 outputFile := mcStream.combine () ;
5705 IF NOT EqualArray (s, '-')
5706 THEN
5707 Close (outputFile)
5709 END closeOutput ;
5713 write - outputs a single char, ch.
5716 PROCEDURE write (ch: CHAR) ;
5717 BEGIN
5718 WriteChar (outputFile, ch) ;
5719 FlushBuffer (outputFile)
5720 END write ;
5724 writeln -
5727 PROCEDURE writeln ;
5728 BEGIN
5729 WriteLine (outputFile) ;
5730 FlushBuffer (outputFile)
5731 END writeln ;
5735 doIncludeC - include header file for definition module, n.
5738 PROCEDURE doIncludeC (n: node) ;
5740 s: String ;
5741 BEGIN
5742 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
5743 IF getExtendedOpaque ()
5744 THEN
5745 (* no include in this case. *)
5746 ELSIF isDef (n)
5747 THEN
5748 print (doP, '# include "') ;
5749 prints (doP, getHPrefix ()) ;
5750 prints (doP, s) ;
5751 print (doP, '.h"\n') ;
5752 foreachNodeDo (n^.defF.decls.symbols, addDoneDef)
5753 END ;
5754 s := KillString (s)
5755 END doIncludeC ;
5759 getSymScope - returns the scope where node, n, was declared.
5762 PROCEDURE getSymScope (n: node) : node ;
5763 BEGIN
5764 WITH n^ DO
5765 CASE kind OF
5767 const : RETURN constF.scope |
5768 type : RETURN typeF.scope |
5769 var : RETURN varF.scope |
5770 procedure: RETURN procedureF.scope
5773 END ;
5774 HALT
5775 END getSymScope ;
5779 isQualifiedForced - should the node be written with a module prefix?
5782 PROCEDURE isQualifiedForced (n: node) : BOOLEAN ;
5783 BEGIN
5784 RETURN (forceQualified AND
5785 (isType (n) OR isRecord (n) OR isArray (n) OR isEnumeration (n) OR isEnumerationField (n)))
5786 END isQualifiedForced ;
5790 getFQstring -
5793 PROCEDURE getFQstring (n: node) : String ;
5795 i, s: String ;
5796 BEGIN
5797 IF (getScope (n) = NIL) OR (isDefUnqualified (getScope (n)))
5798 THEN
5799 RETURN InitStringCharStar (keyToCharStar (getSymName (n)))
5800 ELSIF isQualifiedForced (n)
5801 THEN
5802 i := InitStringCharStar (keyToCharStar (getSymName (n))) ;
5803 s := InitStringCharStar (keyToCharStar (getSymName (getScope (n)))) ;
5804 RETURN Sprintf2 (InitString ("%s_%s"), s, i)
5805 ELSIF (NOT isExported (n)) OR getIgnoreFQ () OR (isDefUnqualified (getScope (n)))
5806 THEN
5807 RETURN InitStringCharStar (keyToCharStar (getSymName (n)))
5808 ELSE
5809 i := InitStringCharStar (keyToCharStar (getSymName (n))) ;
5810 s := InitStringCharStar (keyToCharStar (getSymName (getScope (n)))) ;
5811 RETURN Sprintf2 (InitString ("%s_%s"), s, i)
5813 END getFQstring ;
5817 getFQDstring -
5820 PROCEDURE getFQDstring (n: node; scopes: BOOLEAN) : String ;
5822 i, s: String ;
5823 BEGIN
5824 IF (getScope (n) = NIL) OR (isDefUnqualified (getScope (n)))
5825 THEN
5826 RETURN InitStringCharStar (keyToCharStar (getDName (n, scopes)))
5827 ELSIF isQualifiedForced (n)
5828 THEN
5829 (* we assume a qualified name will never conflict. *)
5830 i := InitStringCharStar (keyToCharStar (getSymName (n))) ;
5831 s := InitStringCharStar (keyToCharStar (getSymName (getScope (n)))) ;
5832 RETURN Sprintf2 (InitString ("%s_%s"), s, i)
5833 ELSIF (NOT isExported (n)) OR getIgnoreFQ () OR (isDefUnqualified (getScope (n)))
5834 THEN
5835 RETURN InitStringCharStar (keyToCharStar (getDName (n, scopes)))
5836 ELSE
5837 (* we assume a qualified name will never conflict. *)
5838 i := InitStringCharStar (keyToCharStar (getSymName (n))) ;
5839 s := InitStringCharStar (keyToCharStar (getSymName (getScope (n)))) ;
5840 RETURN Sprintf2 (InitString ("%s_%s"), s, i)
5842 END getFQDstring ;
5846 getString - returns the name as a string.
5849 PROCEDURE getString (n: node) : String ;
5850 BEGIN
5851 IF getSymName (n) = NulName
5852 THEN
5853 RETURN InitString ('')
5854 ELSE
5855 RETURN InitStringCharStar (keyToCharStar (getSymName (n)))
5857 END getString ;
5861 getCardinal - returns the cardinal type node.
5864 PROCEDURE getCardinal () : node ;
5865 BEGIN
5866 RETURN cardinalN
5867 END getCardinal ;
5871 doNone - call HALT.
5874 PROCEDURE doNone (n: node) ;
5875 BEGIN
5876 HALT
5877 END doNone ;
5881 doNothing - does nothing!
5884 PROCEDURE doNothing (n: node) ;
5885 BEGIN
5886 END doNothing ;
5890 doConstC -
5893 PROCEDURE doConstC (n: node) ;
5894 BEGIN
5895 IF NOT alists.isItemInList (globalGroup^.doneQ, n)
5896 THEN
5897 print (doP, "# define ") ;
5898 doFQNameC (doP, n) ;
5899 setNeedSpace (doP) ;
5900 doExprC (doP, n^.constF.value) ;
5901 print (doP, '\n') ;
5902 alists.includeItemIntoList (globalGroup^.doneQ, n)
5904 END doConstC ;
5908 needsParen - returns TRUE if expression, n, needs to be enclosed in ().
5911 PROCEDURE needsParen (n: node) : BOOLEAN ;
5912 BEGIN
5913 assert (n#NIL) ;
5914 WITH n^ DO
5915 CASE kind OF
5917 nil,
5918 true,
5919 false : RETURN FALSE |
5920 constexp : RETURN needsParen (unaryF.arg) |
5921 neg : RETURN needsParen (unaryF.arg) |
5922 not : RETURN needsParen (unaryF.arg) |
5923 adr,
5924 size,
5925 tsize,
5926 ord,
5927 float,
5928 trunc,
5929 chr,
5930 cap,
5931 high : RETURN FALSE |
5932 deref : RETURN FALSE |
5933 equal,
5934 notequal,
5935 less,
5936 greater,
5937 greequal,
5938 lessequal : RETURN TRUE |
5939 componentref : RETURN FALSE |
5940 pointerref : RETURN FALSE |
5941 cast : RETURN TRUE |
5942 val : RETURN TRUE |
5943 abs : RETURN FALSE |
5944 plus,
5945 sub,
5946 div,
5947 mod,
5948 mult,
5949 divide,
5950 in : RETURN TRUE |
5951 literal,
5952 const,
5953 enumerationfield,
5954 string : RETURN FALSE |
5955 max : RETURN TRUE |
5956 min : RETURN TRUE |
5957 var : RETURN FALSE |
5958 arrayref : RETURN FALSE |
5959 and,
5960 or : RETURN TRUE |
5961 funccall : RETURN TRUE |
5962 recordfield : RETURN FALSE |
5963 loc,
5964 byte,
5965 word,
5966 type,
5967 char,
5968 cardinal,
5969 longcard,
5970 shortcard,
5971 integer,
5972 longint,
5973 shortint,
5974 real,
5975 longreal,
5976 shortreal,
5977 complex,
5978 longcomplex,
5979 shortcomplex,
5980 bitset,
5981 boolean,
5982 proc : RETURN FALSE |
5983 setvalue : RETURN FALSE |
5984 address : RETURN TRUE |
5985 procedure : RETURN FALSE |
5986 length,
5987 cmplx, re, im : RETURN TRUE
5990 END ;
5991 RETURN TRUE
5992 END needsParen ;
5996 doUnary -
5999 PROCEDURE doUnary (p: pretty; op: ARRAY OF CHAR; expr, type: node; l, r: BOOLEAN) ;
6000 BEGIN
6001 IF l
6002 THEN
6003 setNeedSpace (p)
6004 END ;
6005 print (p, op) ;
6006 IF r
6007 THEN
6008 setNeedSpace (p)
6009 END ;
6010 IF needsParen (expr)
6011 THEN
6012 outText (p, '(') ;
6013 doExprC (p, expr) ;
6014 outText (p, ')')
6015 ELSE
6016 doExprC (p, expr)
6018 END doUnary ;
6022 doSetSub - perform l & (~ r)
6025 PROCEDURE doSetSub (p: pretty; left, right: node) ;
6026 BEGIN
6027 IF needsParen (left)
6028 THEN
6029 outText (p, '(') ;
6030 doExprC (p, left) ;
6031 outText (p, ')')
6032 ELSE
6033 doExprC (p, left)
6034 END ;
6035 setNeedSpace (p) ;
6036 outText (p, '&') ;
6037 setNeedSpace (p) ;
6038 IF needsParen (right)
6039 THEN
6040 outText (p, '(~(') ;
6041 doExprC (p, right) ;
6042 outText (p, '))')
6043 ELSE
6044 outText (p, '(~') ;
6045 doExprC (p, right) ;
6046 outText (p, ')')
6048 END doSetSub ;
6052 doPolyBinary -
6055 PROCEDURE doPolyBinary (p: pretty; op: nodeT; left, right: node; l, r: BOOLEAN) ;
6057 lt, rt: node ;
6058 BEGIN
6059 lt := skipType (getExprType (left)) ;
6060 rt := skipType (getExprType (right)) ;
6061 IF ((lt # NIL) AND (isSet (lt) OR isBitset (lt))) OR
6062 ((rt # NIL) AND (isSet (rt) OR isBitset (rt)))
6063 THEN
6064 CASE op OF
6066 plus : doBinary (p, '|', left, right, l, r, FALSE) |
6067 sub : doSetSub (p, left, right) |
6068 mult : doBinary (p, '&', left, right, l, r, FALSE) |
6069 divide : doBinary (p, '^', left, right, l, r, FALSE)
6072 ELSE
6073 CASE op OF
6075 plus : doBinary (p, '+', left, right, l, r, FALSE) |
6076 sub : doBinary (p, '-', left, right, l, r, FALSE) |
6077 mult : doBinary (p, '*', left, right, l, r, FALSE) |
6078 divide : doBinary (p, '/', left, right, l, r, FALSE)
6082 END doPolyBinary ;
6086 doBinary -
6089 PROCEDURE doBinary (p: pretty; op: ARRAY OF CHAR; left, right: node; l, r, unpackProc: BOOLEAN) ;
6090 BEGIN
6091 IF needsParen (left)
6092 THEN
6093 outText (p, '(') ;
6094 left := doExprCup (p, left, unpackProc, FALSE) ;
6095 outText (p, ')')
6096 ELSE
6097 left := doExprCup (p, left, unpackProc, FALSE)
6098 END ;
6099 IF l
6100 THEN
6101 setNeedSpace (p)
6102 END ;
6103 outText (p, op) ;
6104 IF r
6105 THEN
6106 setNeedSpace (p)
6107 END ;
6108 IF needsParen (right)
6109 THEN
6110 outText (p, '(') ;
6111 right := doExprCup (p, right, unpackProc, FALSE) ;
6112 outText (p, ')')
6113 ELSE
6114 right := doExprCup (p, right, unpackProc, FALSE)
6116 END doBinary ;
6120 doPostUnary -
6123 PROCEDURE doPostUnary (p: pretty; op: ARRAY OF CHAR; expr: node) ;
6124 BEGIN
6125 doExprC (p, expr) ;
6126 outText (p, op)
6127 END doPostUnary ;
6131 doDeRefC -
6134 PROCEDURE doDeRefC (p: pretty; expr: node) : node ;
6135 BEGIN
6136 outText (p, '(*') ;
6137 expr := castOpaque (p, expr, FALSE) ;
6138 outText (p, ')') ;
6139 RETURN expr
6140 END doDeRefC ;
6144 doGetLastOp - returns, a, if b is a terminal otherwise walk right.
6147 PROCEDURE doGetLastOp (a, b: node) : node ;
6148 BEGIN
6149 WITH b^ DO
6150 CASE kind OF
6152 nil : RETURN a |
6153 true : RETURN a |
6154 false : RETURN a |
6155 constexp : RETURN doGetLastOp (b, unaryF.arg) |
6156 neg : RETURN doGetLastOp (b, unaryF.arg) |
6157 not : RETURN doGetLastOp (b, unaryF.arg) |
6158 adr : RETURN doGetLastOp (b, unaryF.arg) |
6159 size : RETURN doGetLastOp (b, unaryF.arg) |
6160 tsize : RETURN doGetLastOp (b, unaryF.arg) |
6161 ord : RETURN doGetLastOp (b, unaryF.arg) |
6162 float,
6163 trunc : RETURN doGetLastOp (b, unaryF.arg) |
6164 chr : RETURN doGetLastOp (b, unaryF.arg) |
6165 cap : RETURN doGetLastOp (b, unaryF.arg) |
6166 high : RETURN doGetLastOp (b, unaryF.arg) |
6167 deref : RETURN doGetLastOp (b, unaryF.arg) |
6169 im : RETURN doGetLastOp (b, unaryF.arg) |
6170 equal : RETURN doGetLastOp (b, binaryF.right) |
6171 notequal : RETURN doGetLastOp (b, binaryF.right) |
6172 less : RETURN doGetLastOp (b, binaryF.right) |
6173 greater : RETURN doGetLastOp (b, binaryF.right) |
6174 greequal : RETURN doGetLastOp (b, binaryF.right) |
6175 lessequal : RETURN doGetLastOp (b, binaryF.right) |
6176 componentref : RETURN doGetLastOp (b, componentrefF.field) |
6177 pointerref : RETURN doGetLastOp (b, pointerrefF.field) |
6178 cast : RETURN doGetLastOp (b, binaryF.right) |
6179 val : RETURN doGetLastOp (b, binaryF.right) |
6180 plus : RETURN doGetLastOp (b, binaryF.right) |
6181 sub : RETURN doGetLastOp (b, binaryF.right) |
6182 div : RETURN doGetLastOp (b, binaryF.right) |
6183 mod : RETURN doGetLastOp (b, binaryF.right) |
6184 mult : RETURN doGetLastOp (b, binaryF.right) |
6185 divide : RETURN doGetLastOp (b, binaryF.right) |
6186 in : RETURN doGetLastOp (b, binaryF.right) |
6187 and : RETURN doGetLastOp (b, binaryF.right) |
6188 or : RETURN doGetLastOp (b, binaryF.right) |
6189 cmplx : RETURN doGetLastOp (b, binaryF.right) |
6190 literal : RETURN a |
6191 const : RETURN a |
6192 enumerationfield: RETURN a |
6193 string : RETURN a |
6194 max : RETURN doGetLastOp (b, unaryF.arg) |
6195 min : RETURN doGetLastOp (b, unaryF.arg) |
6196 var : RETURN a |
6197 arrayref : RETURN a |
6198 funccall : RETURN a |
6199 procedure : RETURN a |
6200 recordfield : RETURN a
6204 END doGetLastOp ;
6208 getLastOp - return the right most non leaf node.
6211 PROCEDURE getLastOp (n: node) : node ;
6212 BEGIN
6213 RETURN doGetLastOp (n, n)
6214 END getLastOp ;
6218 doComponentRefC -
6221 PROCEDURE doComponentRefC (p: pretty; l, r: node) ;
6222 BEGIN
6223 flushOpaque (p, l, FALSE) ;
6224 outText (p, '.') ;
6225 doExprC (p, r)
6226 END doComponentRefC ;
6230 doPointerRefC -
6233 PROCEDURE doPointerRefC (p: pretty; l, r: node) ;
6234 BEGIN
6235 flushOpaque (p, l, FALSE) ;
6236 outText (p, '->') ;
6237 doExprC (p, r)
6238 END doPointerRefC ;
6242 doPreBinary -
6245 PROCEDURE doPreBinary (p: pretty; op: ARRAY OF CHAR; left, right: node; l, r: BOOLEAN) ;
6246 BEGIN
6247 IF l
6248 THEN
6249 setNeedSpace (p)
6250 END ;
6251 outText (p, op) ;
6252 IF r
6253 THEN
6254 setNeedSpace (p)
6255 END ;
6256 outText (p, '(') ;
6257 doExprC (p, left) ;
6258 outText (p, ',') ;
6259 setNeedSpace (p) ;
6260 doExprC (p, right) ;
6261 outText (p, ')')
6262 END doPreBinary ;
6266 doConstExpr -
6269 PROCEDURE doConstExpr (p: pretty; n: node) ;
6270 BEGIN
6271 doFQNameC (p, n)
6272 END doConstExpr ;
6276 doEnumerationField -
6279 PROCEDURE doEnumerationField (p: pretty; n: node) ;
6280 BEGIN
6281 doFQDNameC (p, n, FALSE)
6282 END doEnumerationField ;
6286 isZero - returns TRUE if node, n, is zero.
6289 PROCEDURE isZero (n: node) : BOOLEAN ;
6290 BEGIN
6291 IF isConstExp (n)
6292 THEN
6293 RETURN isZero (n^.unaryF.arg)
6294 END ;
6295 RETURN getSymName (n)=makeKey ('0')
6296 END isZero ;
6300 doArrayRef - perform an array reference. If constCast
6301 then an unbounded array access will be const_cast
6302 (the constCast should be TRUE if an assignment to
6303 the array is required).
6306 PROCEDURE doArrayRef (p: pretty; n: node; constCast: BOOLEAN) ;
6308 type,
6309 v : node ;
6310 i, c: CARDINAL ;
6311 BEGIN
6312 assert (n # NIL) ;
6313 assert (isArrayRef (n)) ;
6314 type := skipType (getType (n^.arrayrefF.array)) ;
6315 IF isUnbounded (type)
6316 THEN
6317 v := n^.arrayrefF.array ;
6318 IF constCast AND isVar (n^.arrayrefF.array) AND
6319 (v^.varF.isParameter OR v^.varF.isVarParameter)
6320 THEN
6321 outText (p, "const_cast<") ;
6322 doTypeNameC (p, getType (v)) ;
6323 outText (p, ">(") ;
6324 outTextN (p, getSymName (n^.arrayrefF.array)) ;
6325 outText (p, ")")
6326 ELSE
6327 outTextN (p, getSymName (n^.arrayrefF.array))
6329 ELSE
6330 doExprC (p, n^.arrayrefF.array) ;
6331 assert (isArray (type)) ;
6332 outText (p, '.array')
6333 END ;
6334 outText (p, '[') ;
6335 i := 1 ;
6336 c := expListLen (n^.arrayrefF.index) ;
6337 WHILE i<=c DO
6338 doExprC (p, getExpList (n^.arrayrefF.index, i)) ;
6339 IF isUnbounded (type)
6340 THEN
6341 assert (c = 1)
6342 ELSE
6343 doSubtractC (p, getMin (type^.arrayF.subr)) ;
6344 IF i<c
6345 THEN
6346 assert (isArray (type)) ;
6347 outText (p, '].array[') ;
6348 type := skipType (getType (type))
6350 END ;
6351 INC (i)
6352 END ;
6353 outText (p, ']')
6354 END doArrayRef ;
6358 doProcedure -
6361 PROCEDURE doProcedure (p: pretty; n: node) ;
6362 BEGIN
6363 assert (isProcedure (n)) ;
6364 doFQDNameC (p, n, TRUE)
6365 END doProcedure ;
6369 doRecordfield -
6372 PROCEDURE doRecordfield (p: pretty; n: node) ;
6373 BEGIN
6374 doDNameC (p, n, FALSE)
6375 END doRecordfield ;
6379 doCastC -
6382 PROCEDURE doCastC (p: pretty; t, e: node) ;
6384 et: node ;
6385 BEGIN
6386 outText (p, '(') ;
6387 doTypeNameC (p, t) ;
6388 outText (p, ')') ;
6389 setNeedSpace (p) ;
6390 et := skipType (getType (e)) ;
6391 IF (et # NIL) AND isAProcType (et) AND isAProcType (skipType (t))
6392 THEN
6393 outText (p, '{(') ;
6394 doFQNameC (p, t) ;
6395 outText (p, '_t)') ;
6396 setNeedSpace (p) ;
6397 doExprC (p, e) ;
6398 outText (p, '.proc}')
6399 ELSE
6400 outText (p, '(') ;
6401 doExprC (p, e) ;
6402 outText (p, ')')
6404 END doCastC ;
6408 doSetValueC -
6411 PROCEDURE doSetValueC (p: pretty; n: node) ;
6413 lo : node ;
6414 i, h: CARDINAL ;
6415 BEGIN
6416 assert (isSetValue (n)) ;
6417 lo := getSetLow (n) ;
6418 IF n^.setvalueF.type # NIL
6419 THEN
6420 outText (p, '(') ;
6421 doTypeNameC (p, n^.setvalueF.type) ;
6422 noSpace (p) ;
6423 outText (p, ')') ;
6424 setNeedSpace (p)
6425 END ;
6426 IF HighIndice (n^.setvalueF.values) = 0
6427 THEN
6428 outText (p, '0')
6429 ELSE
6430 i := LowIndice (n^.setvalueF.values) ;
6431 h := HighIndice (n^.setvalueF.values) ;
6432 outText (p, '(') ;
6433 WHILE i<=h DO
6434 outText (p, '(1') ;
6435 setNeedSpace (p) ;
6436 outText (p, '<<') ;
6437 setNeedSpace (p) ;
6438 outText (p, '(') ;
6439 doExprC (p, GetIndice (n^.setvalueF.values, i)) ;
6440 doSubtractC (p, lo) ;
6441 outText (p, ')') ;
6442 outText (p, ')') ;
6443 IF i<h
6444 THEN
6445 setNeedSpace (p) ;
6446 outText (p, '|') ;
6447 setNeedSpace (p)
6448 END ;
6449 INC (i)
6450 END ;
6451 outText (p, ')')
6453 END doSetValueC ;
6457 getSetLow - returns the low value of the set type from
6458 expression, n.
6461 PROCEDURE getSetLow (n: node) : node ;
6463 type: node ;
6464 BEGIN
6465 IF getType (n) = NIL
6466 THEN
6467 RETURN makeLiteralInt (makeKey ('0'))
6468 ELSE
6469 type := skipType (getType (n)) ;
6470 IF isSet (type)
6471 THEN
6472 RETURN getMin (skipType (getType (type)))
6473 ELSE
6474 RETURN makeLiteralInt (makeKey ('0'))
6477 END getSetLow ;
6481 doInC - performs (((1 << (l)) & (r)) != 0)
6484 PROCEDURE doInC (p: pretty; l, r: node) ;
6486 lo: node ;
6487 BEGIN
6488 lo := getSetLow (r) ;
6489 outText (p, '(((1') ;
6490 setNeedSpace (p) ;
6491 outText (p, '<<') ;
6492 setNeedSpace (p) ;
6493 outText (p, '(') ;
6494 doExprC (p, l) ;
6495 doSubtractC (p, lo) ;
6496 outText (p, '))') ;
6497 setNeedSpace (p) ;
6498 outText (p, '&') ;
6499 setNeedSpace (p) ;
6500 outText (p, '(') ;
6501 doExprC (p, r) ;
6502 outText (p, '))') ;
6503 setNeedSpace (p) ;
6504 outText (p, '!=') ;
6505 setNeedSpace (p) ;
6506 outText (p, '0)')
6507 END doInC ;
6511 doThrowC -
6514 PROCEDURE doThrowC (p: pretty; n: node) ;
6515 BEGIN
6516 assert (isIntrinsic (n)) ;
6517 outText (p, "throw") ;
6518 setNeedSpace (p) ;
6519 outText (p, '(') ;
6520 IF expListLen (n^.intrinsicF.args) = 1
6521 THEN
6522 doExprC (p, getExpList (n^.intrinsicF.args, 1))
6523 END ;
6524 outText (p, ')')
6525 END doThrowC ;
6529 doUnreachableC -
6532 PROCEDURE doUnreachableC (p: pretty; n: node) ;
6533 BEGIN
6534 assert (isIntrinsic (n)) ;
6535 outText (p, "__builtin_unreachable") ;
6536 setNeedSpace (p) ;
6537 outText (p, '(') ;
6538 assert (expListLen (n^.intrinsicF.args) = 0) ;
6539 outText (p, ')')
6540 END doUnreachableC ;
6544 outNull -
6547 PROCEDURE outNull (p: pretty) ;
6548 BEGIN
6549 keyc.useNull ;
6550 outText (p, 'NULL')
6551 END outNull ;
6555 outTrue -
6558 PROCEDURE outTrue (p: pretty) ;
6559 BEGIN
6560 keyc.useTrue ;
6561 IF useBool () AND (lang = ansiCP)
6562 THEN
6563 outText (p, 'true')
6564 ELSE
6565 outText (p, 'TRUE')
6567 END outTrue ;
6571 outFalse -
6574 PROCEDURE outFalse (p: pretty) ;
6575 BEGIN
6576 keyc.useFalse ;
6577 IF useBool () AND (lang = ansiCP)
6578 THEN
6579 outText (p, 'false')
6580 ELSE
6581 outText (p, 'FALSE')
6583 END outFalse ;
6587 doExprC -
6590 PROCEDURE doExprC (p: pretty; n: node) ;
6592 t: node ;
6593 BEGIN
6594 assert (n#NIL) ;
6595 t := getExprType (n) ;
6596 WITH n^ DO
6597 CASE kind OF
6599 nil : outNull (p) |
6600 true : outTrue (p) |
6601 false : outFalse (p) |
6602 constexp : doUnary (p, '', unaryF.arg, unaryF.resultType, FALSE, FALSE) |
6603 neg : doUnary (p, '-', unaryF.arg, unaryF.resultType, FALSE, FALSE) |
6604 not : doUnary (p, '!', unaryF.arg, unaryF.resultType, FALSE, TRUE) |
6605 val : doValC (p, n) |
6606 adr : doAdrC (p, n) |
6607 size,
6608 tsize : doSizeC (p, n) |
6609 float : doConvertSC (p, n, getCRealType ()) |
6610 trunc : doConvertC (p, n, "int") |
6611 ord : doConvertC (p, n, "unsigned int") |
6612 chr : doConvertC (p, n, "char") |
6613 cap : doCapC (p, n) |
6614 abs : doAbsC (p, n) |
6615 high : doFuncHighC (p, n^.unaryF.arg) |
6616 length : doLengthC (p, n) |
6617 min : doMinC (p, n) |
6618 max : doMaxC (p, n) |
6619 throw : doThrowC (p, n) |
6620 unreachable : doUnreachableC (p, n) |
6621 re : doReC (p, n) |
6622 im : doImC (p, n) |
6623 cmplx : doCmplx (p, n) |
6625 deref : unaryF.arg := doDeRefC (p, unaryF.arg) |
6626 equal : doBinary (p, '==', binaryF.left, binaryF.right, TRUE, TRUE, TRUE) |
6627 notequal : doBinary (p, '!=', binaryF.left, binaryF.right, TRUE, TRUE, TRUE) |
6628 less : doBinary (p, '<', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6629 greater : doBinary (p, '>', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6630 greequal : doBinary (p, '>=', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6631 lessequal : doBinary (p, '<=', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6632 componentref : doComponentRefC (p, componentrefF.rec, componentrefF.field) |
6633 pointerref : doPointerRefC (p, pointerrefF.ptr, pointerrefF.field) |
6634 cast : doCastC (p, binaryF.left, binaryF.right) |
6635 plus : doPolyBinary (p, plus, binaryF.left, binaryF.right, FALSE, FALSE) |
6636 sub : doPolyBinary (p, sub, binaryF.left, binaryF.right, FALSE, FALSE) |
6637 div : doBinary (p, '/', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6638 mod : doBinary (p, '%', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6639 mult : doPolyBinary (p, mult, binaryF.left, binaryF.right, FALSE, FALSE) |
6640 divide : doPolyBinary (p, divide, binaryF.left, binaryF.right, FALSE, FALSE) |
6641 in : doInC (p, binaryF.left, binaryF.right) |
6642 and : doBinary (p, '&&', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6643 or : doBinary (p, '||', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6644 literal : doLiteralC (p, n) |
6645 const : doConstExpr (p, n) |
6646 enumerationfield: doEnumerationField (p, n) |
6647 string : doStringC (p, n) |
6648 var : doVar (p, n) |
6649 arrayref : doArrayRef (p, n, FALSE) |
6650 funccall : doFuncExprC (p, n) |
6651 procedure : doProcedure (p, n) |
6652 recordfield : doRecordfield (p, n) |
6653 setvalue : doSetValueC (p, n) |
6654 char,
6655 cardinal,
6656 longcard,
6657 shortcard,
6658 integer,
6659 longint,
6660 shortint,
6661 complex,
6662 longcomplex,
6663 shortcomplex,
6664 real,
6665 longreal,
6666 shortreal,
6667 bitset,
6668 boolean,
6669 proc : doBaseC (p, n) |
6670 address,
6671 loc,
6672 byte,
6673 word,
6674 csizet,
6675 cssizet : doSystemC (p, n) |
6676 type : doTypeNameC (p, n) |
6677 pointer : doTypeNameC (p, n)
6681 END doExprC ;
6685 doExprCup -
6688 PROCEDURE doExprCup (p: pretty; n: node;
6689 unpackProc, uncastConst: BOOLEAN) : node ;
6691 type: node ;
6692 BEGIN
6693 IF uncastConst AND isArrayRef (n)
6694 THEN
6695 doArrayRef (p, n, TRUE)
6696 ELSE
6697 doExprC (p, n) ;
6698 IF unpackProc
6699 THEN
6700 type := skipType (getExprType (n)) ;
6701 IF (type # NIL) AND isAProcType (type)
6702 THEN
6703 outText (p, '.proc')
6706 END ;
6707 RETURN n
6708 END doExprCup ;
6712 doExprM2 -
6715 PROCEDURE doExprM2 (p: pretty; n: node) ;
6716 BEGIN
6717 assert (n#NIL) ;
6718 WITH n^ DO
6719 CASE kind OF
6721 nil : outText (p, 'NIL') |
6722 true : outText (p, 'TRUE') |
6723 false : outText (p, 'FALSE') |
6724 constexp : doUnary (p, '', unaryF.arg, unaryF.resultType, FALSE, FALSE) |
6725 neg : doUnary (p, '-', unaryF.arg, unaryF.resultType, FALSE, FALSE) |
6726 not : doUnary (p, 'NOT', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6727 adr : doUnary (p, 'ADR', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6728 size : doUnary (p, 'SIZE', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6729 tsize : doUnary (p, 'TSIZE', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6730 float : doUnary (p, 'FLOAT', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6731 trunc : doUnary (p, 'TRUNC', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6732 ord : doUnary (p, 'ORD', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6733 chr : doUnary (p, 'CHR', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6734 cap : doUnary (p, 'CAP', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6735 high : doUnary (p, 'HIGH', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6736 re : doUnary (p, 'RE', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6737 im : doUnary (p, 'IM', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6738 deref : doPostUnary (p, '^', unaryF.arg) |
6739 equal : doBinary (p, '=', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6740 notequal : doBinary (p, '#', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6741 less : doBinary (p, '<', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6742 greater : doBinary (p, '>', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6743 greequal : doBinary (p, '>=', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6744 lessequal : doBinary (p, '<=', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6745 componentref : doBinary (p, '.', componentrefF.rec, componentrefF.field, FALSE, FALSE, FALSE) |
6746 pointerref : doBinary (p, '^.', pointerrefF.ptr, pointerrefF.field, FALSE, FALSE, FALSE) |
6747 cast : doPreBinary (p, 'CAST', binaryF.left, binaryF.right, TRUE, TRUE) |
6748 val : doPreBinary (p, 'VAL', binaryF.left, binaryF.right, TRUE, TRUE) |
6749 cmplx : doPreBinary (p, 'CMPLX', binaryF.left, binaryF.right, TRUE, TRUE) |
6750 plus : doBinary (p, '+', binaryF.left, binaryF.right, FALSE, FALSE, FALSE) |
6751 sub : doBinary (p, '-', binaryF.left, binaryF.right, FALSE, FALSE, FALSE) |
6752 div : doBinary (p, 'DIV', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6753 mod : doBinary (p, 'MOD', binaryF.left, binaryF.right, TRUE, TRUE, FALSE) |
6754 mult : doBinary (p, '*', binaryF.left, binaryF.right, FALSE, FALSE, FALSE) |
6755 divide : doBinary (p, '/', binaryF.left, binaryF.right, FALSE, FALSE, FALSE) |
6756 literal : doLiteral (p, n) |
6757 const : doConstExpr (p, n) |
6758 enumerationfield: doEnumerationField (p, n) |
6759 string : doString (p, n) |
6760 max : doUnary (p, 'MAX', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6761 min : doUnary (p, 'MIN', unaryF.arg, unaryF.resultType, TRUE, TRUE) |
6762 var : doVar (p, n)
6766 END doExprM2 ;
6770 doVar -
6773 PROCEDURE doVar (p: pretty; n: node) ;
6774 BEGIN
6775 assert (isVar (n)) ;
6776 IF n^.varF.isVarParameter
6777 THEN
6778 outText (p, '(*') ;
6779 doFQDNameC (p, n, TRUE) ;
6780 outText (p, ')')
6781 ELSE
6782 doFQDNameC (p, n, TRUE)
6784 END doVar ;
6788 doLiteralC -
6791 PROCEDURE doLiteralC (p: pretty; n: node) ;
6793 s: String ;
6794 BEGIN
6795 assert (isLiteral (n)) ;
6796 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
6797 IF n^.literalF.type=charN
6798 THEN
6799 IF DynamicStrings.char (s, -1)='C'
6800 THEN
6801 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1) ;
6802 IF DynamicStrings.char (s, 0)#'0'
6803 THEN
6804 s := DynamicStrings.ConCat (InitString('0'), DynamicStrings.Mark (s))
6806 END ;
6807 outText (p, "(char)") ;
6808 setNeedSpace (p)
6809 ELSIF DynamicStrings.char (s, -1) = 'H'
6810 THEN
6811 outText (p, "0x") ;
6812 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1)
6813 ELSIF DynamicStrings.char (s, -1) = 'B'
6814 THEN
6815 outText (p, "0") ;
6816 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1)
6817 END ;
6818 outTextS (p, s) ;
6819 s := KillString (s)
6820 END doLiteralC ;
6824 doLiteral -
6827 PROCEDURE doLiteral (p: pretty; n: node) ;
6829 s: String ;
6830 BEGIN
6831 assert (isLiteral (n)) ;
6832 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
6833 IF n^.literalF.type=charN
6834 THEN
6835 IF DynamicStrings.char (s, -1)='C'
6836 THEN
6837 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1) ;
6838 IF DynamicStrings.char (s, 0)#'0'
6839 THEN
6840 s := DynamicStrings.ConCat (InitString('0'), DynamicStrings.Mark (s))
6842 END ;
6843 outText (p, "(char)") ;
6844 setNeedSpace (p)
6845 END ;
6846 outTextS (p, s) ;
6847 s := KillString (s)
6848 END doLiteral ;
6852 isString - returns TRUE if node, n, is a string.
6855 PROCEDURE isString (n: node) : BOOLEAN ;
6856 BEGIN
6857 assert (n#NIL) ;
6858 RETURN n^.kind=string
6859 END isString ;
6863 doString -
6866 PROCEDURE doString (p: pretty; n: node) ;
6868 s: String ;
6869 BEGIN
6870 assert (isString (n)) ;
6871 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
6872 outTextS (p, s) ;
6873 s := KillString (s)
6874 ; HALT
6876 IF DynamicStrings.Index (s, '"', 0)=-1
6877 THEN
6878 outText (p, '"') ;
6879 outTextS (p, s) ;
6880 outText (p, '"')
6881 ELSIF DynamicStrings.Index (s, "'", 0)=-1
6882 THEN
6883 outText (p, '"') ;
6884 outTextS (p, s) ;
6885 outText (p, '"')
6886 ELSE
6887 metaError1 ('illegal string {%1k}', n)
6890 END doString ;
6894 replaceChar - replace every occurance of, ch, by, a and return modified string, s.
6897 PROCEDURE replaceChar (s: String; ch: CHAR; a: ARRAY OF CHAR) : String ;
6899 i: INTEGER ;
6900 BEGIN
6901 i := 0 ;
6902 LOOP
6903 i := DynamicStrings.Index (s, ch, i) ;
6904 IF i = 0
6905 THEN
6906 s := ConCat (InitString (a), DynamicStrings.Slice (s, 1, 0)) ;
6907 i := StrLen (a)
6908 ELSIF i > 0
6909 THEN
6910 s := ConCat (ConCat (DynamicStrings.Slice (s, 0, i), Mark (InitString (a))), DynamicStrings.Slice (s, i+1, 0)) ;
6911 INC (i, StrLen (a))
6912 ELSE
6913 RETURN s
6916 END replaceChar ;
6920 toCstring - translates string, n, into a C string
6921 and returns the new String.
6924 PROCEDURE toCstring (n: Name) : String ;
6926 s: String ;
6927 BEGIN
6928 s := DynamicStrings.Slice (InitStringCharStar (keyToCharStar (n)), 1, -1) ;
6929 RETURN replaceChar (replaceChar (s, '\', '\\'), '"', '\"')
6930 END toCstring ;
6934 toCchar -
6937 PROCEDURE toCchar (n: Name) : String ;
6939 s: String ;
6940 BEGIN
6941 s := DynamicStrings.Slice (InitStringCharStar (keyToCharStar (n)), 1, -1) ;
6942 RETURN replaceChar (replaceChar (s, '\', '\\'), "'", "\'")
6943 END toCchar ;
6947 countChar -
6950 PROCEDURE countChar (s: String; ch: CHAR) : CARDINAL ;
6952 i: INTEGER ;
6953 c: CARDINAL ;
6954 BEGIN
6955 c := 0 ;
6956 i := 0 ;
6957 LOOP
6958 i := DynamicStrings.Index (s, ch, i) ;
6959 IF i >= 0
6960 THEN
6961 INC (i) ;
6962 INC (c)
6963 ELSE
6964 RETURN c
6967 END countChar ;
6971 lenCstring -
6974 PROCEDURE lenCstring (s: String) : CARDINAL ;
6975 BEGIN
6976 RETURN DynamicStrings.Length (s) - countChar (s, '\')
6977 END lenCstring ;
6981 outCstring -
6984 PROCEDURE outCstring (p: pretty; s: node; aString: BOOLEAN) ;
6985 BEGIN
6986 IF aString
6987 THEN
6988 outText (p, '"') ;
6989 outRawS (p, s^.stringF.cstring) ;
6990 outText (p, '"')
6991 ELSE
6992 outText (p, "'") ;
6993 outRawS (p, s^.stringF.cchar) ;
6994 outText (p, "'")
6996 END outCstring ;
7000 doStringC -
7003 PROCEDURE doStringC (p: pretty; n: node) ;
7005 s: String ;
7006 BEGIN
7007 assert (isString (n)) ;
7008 outCstring (p, n, NOT n^.stringF.isCharCompatible)
7010 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
7011 IF DynamicStrings.Length (s)>3
7012 THEN
7013 IF DynamicStrings.Index (s, '"', 0)=-1
7014 THEN
7015 s := DynamicStrings.Slice (s, 1, -1) ;
7016 outText (p, '"') ;
7017 outCstring (p, s) ;
7018 outText (p, '"')
7019 ELSIF DynamicStrings.Index (s, "'", 0)=-1
7020 THEN
7021 s := DynamicStrings.Slice (s, 1, -1) ;
7022 outText (p, '"') ;
7023 outCstring (p, s) ;
7024 outText (p, '"')
7025 ELSE
7026 metaError1 ('illegal string {%1k}', n)
7028 ELSIF DynamicStrings.Length (s) = 3
7029 THEN
7030 s := DynamicStrings.Slice (s, 1, -1) ;
7031 outText (p, "'") ;
7032 IF DynamicStrings.char (s, 0) = "'"
7033 THEN
7034 outText (p, "\'")
7035 ELSIF DynamicStrings.char (s, 0) = "\"
7036 THEN
7037 outText (p, "\\")
7038 ELSE
7039 outTextS (p, s)
7040 END ;
7041 outText (p, "'")
7042 ELSE
7043 outText (p, "'\0'")
7044 END ;
7045 s := KillString (s)
7047 END doStringC ;
7051 isPunct -
7054 PROCEDURE isPunct (ch: CHAR) : BOOLEAN ;
7055 BEGIN
7056 RETURN (ch = '.') OR (ch = '(') OR (ch = ')') OR
7057 (ch = '^') OR (ch = ':') OR (ch = ';') OR
7058 (ch = '{') OR (ch = '}') OR (ch = ',') OR
7059 (ch = '*')
7060 END isPunct ;
7064 isWhite -
7067 PROCEDURE isWhite (ch: CHAR) : BOOLEAN ;
7068 BEGIN
7069 RETURN (ch = ' ') OR (ch = tab) OR (ch = lf)
7070 END isWhite ;
7074 outText -
7077 PROCEDURE outText (p: pretty; a: ARRAY OF CHAR) ;
7079 s: String ;
7080 BEGIN
7081 s := InitString (a) ;
7082 outTextS (p, s) ;
7083 s := KillString (s)
7084 END outText ;
7088 outRawS -
7091 PROCEDURE outRawS (p: pretty; s: String) ;
7092 BEGIN
7093 raw (p, s)
7094 END outRawS ;
7098 outKm2 -
7101 PROCEDURE outKm2 (p: pretty; a: ARRAY OF CHAR) : pretty ;
7103 i: CARDINAL ;
7104 s: String ;
7105 BEGIN
7106 IF StrEqual (a, 'RECORD')
7107 THEN
7108 p := pushPretty (p) ;
7109 i := getcurpos (p) ;
7110 setindent (p, i) ;
7111 outText (p, a) ;
7112 p := pushPretty (p) ;
7113 setindent (p, i + indentation)
7114 ELSIF StrEqual (a, 'END')
7115 THEN
7116 p := popPretty (p) ;
7117 outText (p, a) ;
7118 p := popPretty (p)
7119 END ;
7120 RETURN p
7121 END outKm2 ;
7125 outKc -
7128 PROCEDURE outKc (p: pretty; a: ARRAY OF CHAR) : pretty ;
7130 i : INTEGER ;
7131 c : CARDINAL ;
7132 s, t: String ;
7133 BEGIN
7134 s := InitString (a) ;
7135 i := DynamicStrings.Index (s, '\', 0) ;
7136 IF i=-1
7137 THEN
7138 t := NIL
7139 ELSE
7140 t := DynamicStrings.Slice (s, i, 0) ;
7141 s := DynamicStrings.Slice (Mark (s), 0, i)
7142 END ;
7143 IF DynamicStrings.char (s, 0)='{'
7144 THEN
7145 p := pushPretty (p) ;
7146 c := getcurpos (p) ;
7147 setindent (p, c) ;
7148 outTextS (p, s) ;
7149 p := pushPretty (p) ;
7150 setindent (p, c + indentationC)
7151 ELSIF DynamicStrings.char (s, 0)='}'
7152 THEN
7153 p := popPretty (p) ;
7154 outTextS (p, s) ;
7155 p := popPretty (p)
7156 END ;
7157 outTextS (p, t) ;
7158 t := KillString (t) ;
7159 s := KillString (s) ;
7160 RETURN p
7161 END outKc ;
7165 outTextS -
7168 PROCEDURE outTextS (p: pretty; s: String) ;
7169 BEGIN
7170 IF s # NIL
7171 THEN
7172 prints (p, s)
7174 END outTextS ;
7178 outCard -
7181 PROCEDURE outCard (p: pretty; c: CARDINAL) ;
7183 s: String ;
7184 BEGIN
7185 s := CardinalToString (c, 0, ' ', 10, FALSE) ;
7186 outTextS (p, s) ;
7187 s := KillString (s)
7188 END outCard ;
7192 outTextN -
7195 PROCEDURE outTextN (p: pretty; n: Name) ;
7197 s: String ;
7198 BEGIN
7199 s := InitStringCharStar (keyToCharStar (n)) ;
7200 prints (p, s) ;
7201 s := KillString (s)
7202 END outTextN ;
7206 outputEnumerationC -
7209 PROCEDURE outputEnumerationC (p: pretty; n: node) ;
7211 i, h: CARDINAL ;
7212 s : node ;
7213 t : String ;
7214 BEGIN
7215 outText (p, "enum {") ;
7216 i := LowIndice (n^.enumerationF.listOfSons) ;
7217 h := HighIndice (n^.enumerationF.listOfSons) ;
7218 WHILE i <= h DO
7219 s := GetIndice (n^.enumerationF.listOfSons, i) ;
7220 doFQDNameC (p, s, FALSE) ;
7221 IF i < h
7222 THEN
7223 outText (p, ",") ; setNeedSpace (p)
7224 END ;
7225 INC (i)
7226 END ;
7227 outText (p, "}")
7228 END outputEnumerationC ;
7232 isDeclType - return TRUE if the current module should declare type.
7235 PROCEDURE isDeclType (type: node) : BOOLEAN ;
7238 def : node ;
7239 name: Name ;
7240 BEGIN
7241 IF isImp (currentModule)
7242 THEN
7243 name := getSymName (type) ;
7244 IF name # NulName
7245 THEN
7246 (* Lookup the matching .def module. *)
7247 def := lookupDef (getSymName (currentModule)) ;
7248 IF def # NIL
7249 THEN
7250 (* Return TRUE if the symbol has not already been declared in the .def. *)
7251 RETURN lookupExported (def, name) = NIL
7254 END ;
7255 RETURN TRUE
7256 END isDeclType ;
7260 doEnumerationC -
7263 PROCEDURE doEnumerationC (p: pretty; n: node) ;
7264 BEGIN
7265 IF isDeclType (n)
7266 THEN
7267 outputEnumerationC (p, n)
7269 END doEnumerationC ;
7273 doNamesC -
7276 PROCEDURE doNamesC (p: pretty; n: Name) ;
7278 s: String ;
7279 BEGIN
7280 s := InitStringCharStar (keyToCharStar (n)) ;
7281 outTextS (p, s) ;
7282 s := KillString (s)
7283 END doNamesC ;
7287 doNameC -
7290 PROCEDURE doNameC (p: pretty; n: node) ;
7291 BEGIN
7292 IF (n#NIL) AND (getSymName (n)#NulName)
7293 THEN
7294 doNamesC (p, getSymName (n))
7296 END doNameC ;
7300 initCname -
7303 PROCEDURE initCname (VAR c: cnameT) ;
7304 BEGIN
7305 c.init := FALSE
7306 END initCname ;
7310 doCname -
7313 PROCEDURE doCname (n: Name; VAR c: cnameT; scopes: BOOLEAN) : Name ;
7315 s: String ;
7316 BEGIN
7317 IF c.init
7318 THEN
7319 RETURN c.name
7320 ELSE
7321 c.init := TRUE ;
7322 s := keyc.cname (n, scopes) ;
7323 IF s=NIL
7324 THEN
7325 c.name := n
7326 ELSE
7327 c.name := makekey (DynamicStrings.string (s)) ;
7328 s := KillString (s)
7329 END ;
7330 RETURN c.name
7332 END doCname ;
7336 getDName -
7339 PROCEDURE getDName (n: node; scopes: BOOLEAN) : Name ;
7341 m: Name ;
7342 BEGIN
7343 m := getSymName (n) ;
7344 CASE n^.kind OF
7346 procedure : RETURN doCname (m, n^.procedureF.cname, scopes) |
7347 var : RETURN doCname (m, n^.varF.cname, scopes) |
7348 recordfield : RETURN doCname (m, n^.recordfieldF.cname, scopes) |
7349 enumerationfield: RETURN doCname (m, n^.enumerationfieldF.cname, scopes)
7351 ELSE
7352 END ;
7353 RETURN m
7354 END getDName ;
7358 doDNameC -
7361 PROCEDURE doDNameC (p: pretty; n: node; scopes: BOOLEAN) ;
7362 BEGIN
7363 IF (n#NIL) AND (getSymName (n)#NulName)
7364 THEN
7365 doNamesC (p, getDName (n, scopes))
7367 END doDNameC ;
7371 doFQDNameC -
7374 PROCEDURE doFQDNameC (p: pretty; n: node; scopes: BOOLEAN) ;
7376 s: String ;
7377 BEGIN
7378 s := getFQDstring (n, scopes) ;
7379 outTextS (p, s) ;
7380 s := KillString (s)
7381 END doFQDNameC ;
7385 doFQNameC -
7388 PROCEDURE doFQNameC (p: pretty; n: node) ;
7390 s: String ;
7391 BEGIN
7392 s := getFQstring (n) ;
7393 outTextS (p, s) ;
7394 s := KillString (s)
7395 END doFQNameC ;
7399 doNameM2 -
7402 PROCEDURE doNameM2 (p: pretty; n: node) ;
7403 BEGIN
7404 doNameC (p, n)
7405 END doNameM2 ;
7409 doUsed -
7412 PROCEDURE doUsed (p: pretty; used: BOOLEAN) ;
7413 BEGIN
7414 IF NOT used
7415 THEN
7416 setNeedSpace (p) ;
7417 outText (p, "__attribute__((unused))")
7419 END doUsed ;
7423 doHighC -
7426 PROCEDURE doHighC (p: pretty; a: node; n: Name; isused: BOOLEAN) ;
7427 BEGIN
7428 IF isArray (a) AND isUnbounded (a)
7429 THEN
7430 (* need to display high. *)
7431 print (p, ",") ; setNeedSpace (p) ;
7432 doTypeNameC (p, cardinalN) ; setNeedSpace (p) ;
7433 print (p, "_") ; outTextN (p, n) ; print (p, "_high") ;
7434 doUsed (p, isused)
7436 END doHighC ;
7440 doParamConstCast -
7443 PROCEDURE doParamConstCast (p: pretty; n: node) ;
7445 ptype: node ;
7446 BEGIN
7447 ptype := getType (n) ;
7448 IF isArray (ptype) AND isUnbounded (ptype) AND (lang = ansiCP)
7449 THEN
7450 outText (p, "const") ;
7451 setNeedSpace (p)
7453 END doParamConstCast ;
7457 getParameterVariable - returns the variable which shadows the parameter
7458 named, m, in parameter block, n.
7461 PROCEDURE getParameterVariable (n: node; m: Name) : node ;
7463 p: node ;
7464 BEGIN
7465 assert (isParam (n) OR isVarParam (n)) ;
7466 IF isParam (n)
7467 THEN
7468 p := n^.paramF.scope
7469 ELSE
7470 p := n^.varparamF.scope
7471 END ;
7472 assert (isProcedure (p)) ;
7473 RETURN lookupInScope (p, m)
7474 END getParameterVariable ;
7478 doParamTypeEmit - emit parameter type for C/C++. It checks to see if the
7479 parameter type is a procedure type and if it were declared
7480 in a definition module for "C" and if so it uses the "C"
7481 definition for a procedure type, rather than the mc
7482 C++ version.
7485 PROCEDURE doParamTypeEmit (p: pretty; paramnode, paramtype: node) ;
7486 BEGIN
7487 assert (isParam (paramnode) OR isVarParam (paramnode)) ;
7488 IF isForC (paramnode) AND isProcType (skipType (paramtype))
7489 THEN
7490 doFQNameC (p, paramtype) ;
7491 outText (p, "_C")
7492 ELSE
7493 doTypeNameC (p, paramtype) ;
7494 doOpaqueModifier (p, paramnode) ;
7496 IF nodeUsesOpaque (paramnode) AND (NOT getNodeOpaqueVoidStar (paramnode))
7497 THEN
7498 outText (p, '__opaque')
7502 END doParamTypeEmit ;
7506 doParamTypeNameModifier - Add an _ to an unbounded parameter which is non var.
7509 PROCEDURE doParamTypeNameModifier (p: pretty; ptype: node; varparam: BOOLEAN) ;
7510 BEGIN
7511 IF (NOT varparam) AND isArray (ptype) AND isUnbounded (ptype)
7512 THEN
7513 outText (p, '_')
7515 END doParamTypeNameModifier ;
7519 initOpaqueCastState - assign fields opaque and voidstar in opaquestate.
7522 PROCEDURE initOpaqueCastState (VAR opaquestate: opaqueCastState; opaque, voidstar: BOOLEAN) ;
7523 BEGIN
7524 opaquestate.opaque := opaque ;
7525 opaquestate.voidStar := voidstar
7526 END initOpaqueCastState ;
7530 initNodeOpaqueCastState - assign opaque and currentvoidstar
7533 PROCEDURE initNodeOpaqueCastState (n: node; opaque, voidstar: BOOLEAN) ;
7534 BEGIN
7535 CASE n^.kind OF
7537 opaquecast : initOpaqueCastState (n^.opaquecastF.opaqueState, opaque, voidstar) |
7538 funccall : initOpaqueCastState (n^.funccallF.opaqueState, opaque, voidstar) |
7539 var : initOpaqueCastState (n^.varF.opaqueState, opaque, voidstar) |
7540 array : initOpaqueCastState (n^.arrayF.opaqueState, opaque, voidstar) |
7541 varparam : initOpaqueCastState (n^.varparamF.opaqueState, opaque, voidstar) |
7542 param : initOpaqueCastState (n^.paramF.opaqueState, opaque, voidstar) |
7543 pointer : initOpaqueCastState (n^.pointerF.opaqueState, opaque, voidstar) |
7544 recordfield : initOpaqueCastState (n^.recordfieldF.opaqueState, opaque, voidstar) |
7545 componentref: initOpaqueCastState (n^.componentrefF.opaqueState, opaque, voidstar) |
7546 pointerref : initOpaqueCastState (n^.pointerrefF.opaqueState, opaque, voidstar) |
7547 arrayref : initOpaqueCastState (n^.arrayrefF.opaqueState, opaque, voidstar) |
7548 procedure : initOpaqueCastState (n^.procedureF.opaqueState, opaque, voidstar) |
7549 proctype : initOpaqueCastState (n^.proctypeF.opaqueState, opaque, voidstar)
7551 ELSE
7552 HALT
7554 END initNodeOpaqueCastState ;
7558 setOpaqueCastState - set the voidStar field in opaquestate.
7561 PROCEDURE setOpaqueCastState (VAR opaquestate: opaqueCastState; voidstar: BOOLEAN) ;
7562 BEGIN
7563 opaquestate.voidStar := voidstar
7564 END setOpaqueCastState ;
7568 setNodeOpaqueVoidStar - sets the voidStar field in node to voidstar.
7571 PROCEDURE setNodeOpaqueVoidStar (n: node; voidstar: BOOLEAN) ;
7572 BEGIN
7573 assert (nodeUsesOpaque (n)) ;
7574 CASE n^.kind OF
7576 opaquecast : setOpaqueCastState (n^.opaquecastF.opaqueState, voidstar) |
7577 funccall : setOpaqueCastState (n^.funccallF.opaqueState, voidstar) |
7578 var : setOpaqueCastState (n^.varF.opaqueState, voidstar) |
7579 array : setOpaqueCastState (n^.arrayF.opaqueState, voidstar) |
7580 varparam : setOpaqueCastState (n^.varparamF.opaqueState, voidstar) |
7581 param : setOpaqueCastState (n^.paramF.opaqueState, voidstar) |
7582 pointer : setOpaqueCastState (n^.pointerF.opaqueState, voidstar) |
7583 recordfield : setOpaqueCastState (n^.recordfieldF.opaqueState, voidstar) |
7584 componentref: assert (NOT voidstar) ;
7585 setOpaqueCastState (n^.componentrefF.opaqueState, voidstar) |
7586 pointerref : assert (NOT voidstar) ;
7587 setOpaqueCastState (n^.pointerrefF.opaqueState, voidstar) |
7588 arrayref : setOpaqueCastState (n^.arrayrefF.opaqueState, voidstar) |
7589 procedure : setOpaqueCastState (n^.procedureF.opaqueState, voidstar) |
7590 proctype : setOpaqueCastState (n^.proctypeF.opaqueState, voidstar)
7592 ELSE
7593 HALT
7595 END setNodeOpaqueVoidStar ;
7599 nodeUsesOpaque - return TRUE if node n uses an opaque type.
7602 PROCEDURE nodeUsesOpaque (n: node) : BOOLEAN ;
7603 BEGIN
7604 CASE n^.kind OF
7606 opaquecast : RETURN n^.opaquecastF.opaqueState.opaque |
7607 funccall : RETURN n^.funccallF.opaqueState.opaque |
7608 var : RETURN n^.varF.opaqueState.opaque |
7609 array : RETURN n^.arrayF.opaqueState.opaque |
7610 varparam : RETURN n^.varparamF.opaqueState.opaque |
7611 param : RETURN n^.paramF.opaqueState.opaque |
7612 pointer : RETURN n^.pointerF.opaqueState.opaque |
7613 recordfield : RETURN n^.recordfieldF.opaqueState.opaque |
7614 componentref: RETURN n^.componentrefF.opaqueState.opaque |
7615 pointerref : RETURN n^.pointerrefF.opaqueState.opaque |
7616 arrayref : RETURN n^.arrayrefF.opaqueState.opaque |
7617 procedure : RETURN n^.procedureF.opaqueState.opaque |
7618 proctype : RETURN n^.proctypeF.opaqueState.opaque |
7619 deref : RETURN nodeUsesOpaque (n^.unaryF.arg)
7621 ELSE
7622 RETURN FALSE
7624 END nodeUsesOpaque ;
7628 getNodeOpaqueVoidStar - return TRUE if the opaque type used by node n is a void *.
7631 PROCEDURE getNodeOpaqueVoidStar (n: node) : BOOLEAN ;
7632 BEGIN
7633 assert (nodeUsesOpaque (n)) ;
7634 CASE n^.kind OF
7636 opaquecast : RETURN n^.opaquecastF.opaqueState.voidStar |
7637 funccall : RETURN n^.funccallF.opaqueState.voidStar |
7638 var : RETURN n^.varF.opaqueState.voidStar |
7639 array : RETURN n^.arrayF.opaqueState.voidStar |
7640 varparam : RETURN n^.varparamF.opaqueState.voidStar |
7641 param : RETURN n^.paramF.opaqueState.voidStar |
7642 pointer : RETURN n^.pointerF.opaqueState.voidStar |
7643 recordfield : RETURN n^.recordfieldF.opaqueState.voidStar |
7644 componentref: RETURN n^.componentrefF.opaqueState.voidStar |
7645 pointerref : RETURN n^.pointerrefF.opaqueState.voidStar |
7646 arrayref : RETURN n^.arrayrefF.opaqueState.voidStar |
7647 procedure : RETURN n^.procedureF.opaqueState.voidStar |
7648 proctype : RETURN n^.proctypeF.opaqueState.voidStar |
7649 deref : RETURN FALSE
7651 ELSE
7652 HALT
7654 END getNodeOpaqueVoidStar ;
7658 getOpaqueFlushNecessary - return TRUE if the value next differs from the opaque state.
7661 PROCEDURE getOpaqueFlushNecessary (state: opaqueCastState; next: BOOLEAN) : BOOLEAN ;
7662 BEGIN
7663 RETURN state.opaque AND (state.voidStar # next)
7664 END getOpaqueFlushNecessary ;
7668 getNodeOpaqueFlushNecessary - return TRUE if the value of next requires a cast.
7671 PROCEDURE getNodeOpaqueFlushNecessary (n: node; next: BOOLEAN) : BOOLEAN ;
7672 BEGIN
7673 CASE n^.kind OF
7675 opaquecast : RETURN getOpaqueFlushNecessary (n^.opaquecastF.opaqueState, next) |
7676 funccall : RETURN getOpaqueFlushNecessary (n^.funccallF.opaqueState, next) |
7677 var : RETURN getOpaqueFlushNecessary (n^.varF.opaqueState, next) |
7678 array : RETURN getOpaqueFlushNecessary (n^.arrayF.opaqueState, next) |
7679 varparam : RETURN getOpaqueFlushNecessary (n^.varparamF.opaqueState, next) |
7680 param : RETURN getOpaqueFlushNecessary (n^.paramF.opaqueState, next) |
7681 pointer : RETURN getOpaqueFlushNecessary (n^.pointerF.opaqueState, next) |
7682 recordfield : RETURN getOpaqueFlushNecessary (n^.recordfieldF.opaqueState, next) |
7683 componentref: RETURN getOpaqueFlushNecessary (n^.componentrefF.opaqueState, next) |
7684 pointerref : RETURN getOpaqueFlushNecessary (n^.pointerrefF.opaqueState, next) |
7685 arrayref : RETURN getOpaqueFlushNecessary (n^.arrayrefF.opaqueState, next) |
7686 procedure : RETURN getOpaqueFlushNecessary (n^.procedureF.opaqueState, next) |
7687 proctype : RETURN getOpaqueFlushNecessary (n^.proctypeF.opaqueState, next)
7689 ELSE
7690 RETURN FALSE
7692 END getNodeOpaqueFlushNecessary ;
7696 makeOpaqueCast - wrap node n with an opaquecast node and assign
7697 voidstar into the new opaque state.
7700 PROCEDURE makeOpaqueCast (n: node; voidstar: BOOLEAN) : node ;
7702 o: node ;
7703 BEGIN
7704 o := newNode (opaquecast) ;
7705 WITH o^.opaquecastF DO
7706 exp := n ;
7707 initOpaqueCastState (opaqueState, TRUE, voidstar)
7708 END ;
7709 RETURN o
7710 END makeOpaqueCast ;
7714 flushOpaque - perform a cast to voidstar (if necessary) and ignore the new
7715 node which could be created.
7718 PROCEDURE flushOpaque (p: pretty; n: node; toVoidStar: BOOLEAN) ;
7720 o: node ;
7721 BEGIN
7722 o := castOpaque (p, n, toVoidStar)
7723 END flushOpaque ;
7727 castOpaque - flushes the opaque type casts if necessary and changes the
7728 voidstar boolean value. If necessary it creates a opaquecast
7729 and returns the new node otherwise return n.
7732 PROCEDURE castOpaque (p: pretty; n: node; toVoidStar: BOOLEAN) : node ;
7734 type: node ;
7735 BEGIN
7736 IF getNodeOpaqueFlushNecessary (n, toVoidStar)
7737 THEN
7738 type := getType (n) ;
7739 IF toVoidStar
7740 THEN
7741 (* next is true cast to void * opaque type. *)
7742 outText (p, 'static_cast<') ;
7743 doTypeNameC (p, type) ;
7744 noSpace (p) ;
7745 outText (p, '> (') ;
7746 doExprC (p, n) ;
7747 outText (p, ')') ;
7748 RETURN makeOpaqueCast (n, TRUE)
7749 ELSE
7750 (* next is false cast to __opaque opaque type. *)
7751 outText (p, 'static_cast<') ;
7752 doTypeNameC (p, type) ;
7753 outText (p, '__opaque') ;
7754 noSpace (p) ;
7755 outText (p, '> (') ;
7756 doExprC (p, n) ;
7757 outText (p, ')') ;
7758 RETURN makeOpaqueCast (n, FALSE)
7760 ELSE
7761 IF debugOpaque
7762 THEN
7763 doP := p ;
7764 dumpOpaqueState (n) ;
7765 IF nodeUsesOpaque (n)
7766 THEN
7767 outText (p, ' /* no difference seen */ ')
7768 ELSE
7769 outText (p, ' /* no opaque used */ ')
7771 END ;
7772 doExprC (p, n)
7773 END ;
7774 RETURN n
7775 END castOpaque ;
7779 isTypeOpaqueDefImp - returns TRUE if type is an opaque type by checking
7780 the def/imp pair of modules or fall back to the
7781 definition module.
7784 PROCEDURE isTypeOpaqueDefImp (type: node) : BOOLEAN ;
7786 scope,
7787 def,
7788 opaque: node ;
7789 BEGIN
7790 IF type = NIL
7791 THEN
7792 RETURN FALSE
7793 ELSIF isType (type)
7794 THEN
7795 scope := getScope (type) ;
7796 IF isImp (scope)
7797 THEN
7798 def := lookupDef (getSymName (scope)) ;
7799 IF def # NIL
7800 THEN
7801 (* Lookup the type name in the matching definition module. *)
7802 opaque := lookupExported (def, getSymName (type)) ;
7803 RETURN (opaque # NIL) AND isType (opaque) AND isTypeOpaque (opaque)
7805 ELSE
7806 (* Otherwise just check the definition module. *)
7807 RETURN isTypeOpaque (type)
7809 END ;
7810 RETURN FALSE
7811 END isTypeOpaqueDefImp ;
7815 isParamVoidStar - return TRUE if the procedure or proctype opaque type
7816 parameter should be implemented as a (void * ).
7819 PROCEDURE isParamVoidStar (n: node) : BOOLEAN ;
7821 proc,
7822 type: node ;
7823 BEGIN
7824 proc := getScope (n) ;
7825 assert (isProcedure (proc) OR isProcType (proc)) ;
7826 type := getType (n) ;
7827 RETURN isReturnVoidStar (proc, type)
7828 END isParamVoidStar ;
7832 isRefVoidStar - returns TRUE if the ref node uses an opaque type which
7833 is represented as a (void * ).
7836 PROCEDURE isRefVoidStar (n: node) : BOOLEAN ;
7838 type: node ;
7839 BEGIN
7840 type := getType (n) ;
7841 IF (NOT isType (type)) OR (NOT isTypeOpaque (type))
7842 THEN
7843 (* We should finish the procedure as the ref does not use an opaque. *)
7844 RETURN TRUE
7845 ELSE
7846 (* We check whether the opaque type was declared in the implementation
7847 module. If it is declared in the implementation module then we
7848 return FALSE. *)
7849 RETURN NOT isDeclInImp (type)
7851 END isRefVoidStar ;
7855 isReturnVoidStar - return TRUE if the procedure or proctype opaque type
7856 return type should be implemented as a (void * ).
7859 PROCEDURE isReturnVoidStar (proc, type: node) : BOOLEAN ;
7861 def : node ;
7862 BEGIN
7863 assert (isProcedure (proc) OR isProcType (proc)) ;
7864 IF isExported (proc)
7865 THEN
7866 RETURN TRUE
7867 ELSE
7868 (* Not exported therefore local, we check whether the opaque type
7869 was declared in the implementation module. *)
7870 IF isImp (currentModule)
7871 THEN
7872 IF isType (type)
7873 THEN
7874 RETURN NOT isDeclInImp (type)
7875 ELSE
7876 RETURN FALSE
7878 ELSE
7879 (* Always use void * in .def modules. *)
7880 RETURN TRUE
7883 END isReturnVoidStar ;
7887 isVarVoidStar - return TRUE if the variable using an opaque type should
7888 be implemented as a (void * ).
7891 PROCEDURE isVarVoidStar (n: node) : BOOLEAN ;
7893 type: node ;
7894 BEGIN
7895 assert (isVar (n)) ;
7896 type := getType (n) ;
7897 IF (NOT isType (type)) OR (NOT isTypeOpaque (type))
7898 THEN
7899 (* We should finish the procedure as the variable does not use an opaque. *)
7900 RETURN TRUE
7901 ELSIF isExported (n)
7902 THEN
7903 (* Exported variables using an opaque type will always be implemented
7904 with a (void * ). *)
7905 RETURN TRUE
7906 ELSE
7907 (* Not exported therefore static to the module (local or global non exported
7908 variable), we check whether the opaque type was declared in the
7909 implementation module. If it is declared in the implementation module
7910 then we return FALSE. *)
7911 RETURN NOT isDeclInImp (type)
7913 END isVarVoidStar ;
7917 initNodeOpaqueState - initialize the node opaque state.
7920 PROCEDURE initNodeOpaqueState (n: node) ;
7922 type: node ;
7923 BEGIN
7924 CASE n^.kind OF
7926 opaquecast : | (* This must be done when the cast direction is known. *)
7927 funccall : assignNodeOpaqueCastState (n, getFunction (n)) |
7928 var : type := getType (n) ;
7929 IF n^.varF.isParameter OR n^.varF.isVarParameter
7930 THEN
7931 (* If the variable is really a parameter then it uses
7932 the state of the parameter. *)
7933 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7934 isParamVoidStar (n))
7935 ELSE
7936 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7937 isVarVoidStar (n))
7938 END |
7939 array : type := getType (n) ;
7940 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7941 isExported (n)) |
7942 varparam,
7943 param : assert (isProcedure (getScope (n)) OR isProcType (getScope (n))) ;
7944 type := getType (n) ;
7945 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7946 isParamVoidStar (n)) |
7947 componentref,
7948 pointerref,
7949 pointer,
7950 recordfield,
7951 arrayref : type := getType (n) ;
7952 (* In the future this should be revisited. *)
7953 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7954 isRefVoidStar (n)) |
7955 (* For the moment treat as never exported. *)
7956 proctype,
7957 procedure : (* We only consider the return type for a procedure or proctype.
7958 The parameters and local vars are handled separately (see
7959 above). *)
7960 type := getType (n) ;
7961 IF type = NIL
7962 THEN
7963 (* No return type, therefore no opaque type used. *)
7964 initNodeOpaqueCastState (n, FALSE, FALSE)
7965 ELSE
7966 (* Init state from the return type. Is type an opaque type?
7967 Is the opaque type declared in this module? *)
7968 initNodeOpaqueCastState (n, isTypeOpaqueDefImp (type),
7969 isReturnVoidStar (n, type))
7970 END |
7972 ELSE
7973 END ;
7974 IF debugOpaque
7975 THEN
7976 dumpOpaqueState (n)
7978 END initNodeOpaqueState ;
7982 assignNodeOpaqueCastState - copy the opaqueCastState from src into dest.
7985 PROCEDURE assignNodeOpaqueCastState (dest, src: node) ;
7986 BEGIN
7987 IF nodeUsesOpaque (src)
7988 THEN
7989 initNodeOpaqueCastState (dest, TRUE, getNodeOpaqueVoidStar (src))
7990 ELSE
7991 initNodeOpaqueCastState (dest, FALSE, FALSE)
7993 END assignNodeOpaqueCastState ;
7997 assignNodeOpaqueCastFalse - assign the voidstar field of dest to false.
7998 It assigns the opaque field of dest to the value
7999 of the src opaque field.
8002 PROCEDURE assignNodeOpaqueCastFalse (dest, src: node) ;
8003 BEGIN
8004 IF nodeUsesOpaque (src)
8005 THEN
8006 initNodeOpaqueCastState (dest, TRUE, FALSE)
8007 ELSE
8008 initNodeOpaqueCastState (dest, FALSE, FALSE)
8010 END assignNodeOpaqueCastFalse ;
8014 dumpOpaqueState -
8017 PROCEDURE dumpOpaqueState (n: node) ;
8019 o: node ;
8020 BEGIN
8021 CASE n^.kind OF
8023 opaquecast,
8024 funccall,
8025 var,
8026 array,
8027 varparam,
8028 param,
8029 pointer,
8030 recordfield,
8031 componentref,
8032 arrayref,
8033 procedure,
8034 proctype : o := n
8036 ELSE
8037 o := NIL
8038 END ;
8039 IF o # NIL
8040 THEN
8041 outText (doP, "/* ") ;
8042 doNameC (doP, o) ;
8043 outText (doP, " ") ;
8044 CASE o^.kind OF
8046 opaquecast : outText (doP, "opaquecast") |
8047 funccall : outText (doP, "funccall") |
8048 var : outText (doP, "var") |
8049 array : outText (doP, "array") |
8050 varparam : outText (doP, "varparam") |
8051 param : outText (doP, "param") |
8052 pointer : outText (doP, "pointer") |
8053 recordfield : outText (doP, "recordfield") |
8054 componentref: outText (doP, "componentref") |
8055 pointerref : outText (doP, "pointerref") |
8056 arrayref : outText (doP, "arrayref") |
8057 procedure : outText (doP, "procedure") |
8058 proctype : outText (doP, "proctype")
8060 ELSE
8061 END ;
8062 IF nodeUsesOpaque (o)
8063 THEN
8064 IF getNodeOpaqueVoidStar (o)
8065 THEN
8066 outText (doP, " uses (void *) opaque")
8067 ELSE
8068 outText (doP, " uses opaque__full")
8069 END ;
8070 END ;
8071 outText (doP, " */ \n")
8073 END dumpOpaqueState ;
8077 doParamC - emit parameter for C/C++.
8080 PROCEDURE doParamC (p: pretty; n: node) ;
8083 ptype: node ;
8084 i : Name ;
8085 c, t : CARDINAL ;
8086 l : wlist ;
8087 BEGIN
8088 assert (isParam (n)) ;
8089 ptype := getType (n) ;
8090 IF n^.paramF.namelist = NIL
8091 THEN
8092 doParamConstCast (p, n) ;
8093 doTypeNameC (p, ptype) ;
8094 doUsed (p, n^.paramF.isUsed) ;
8095 IF isArray (ptype) AND isUnbounded (ptype)
8096 THEN
8097 outText (p, ',') ; setNeedSpace (p) ;
8098 outText (p, 'unsigned int')
8100 ELSE
8101 assert (isIdentList (n^.paramF.namelist)) ;
8102 l := n^.paramF.namelist^.identlistF.names ;
8103 IF l=NIL
8104 THEN
8105 doParamConstCast (p, n) ;
8106 doParamTypeEmit (p, n, ptype) ;
8107 IF isArray (ptype) AND isUnbounded (ptype)
8108 THEN
8109 doUsed (p, n^.paramF.isUsed) ;
8110 outText (p, ',') ; setNeedSpace (p) ;
8111 outText (p, 'unsigned int')
8113 ELSE
8114 t := wlists.noOfItemsInList (l) ;
8115 c := 1 ;
8116 WHILE c <= t DO
8117 doParamConstCast (p, n) ;
8118 doParamTypeEmit (p, n, ptype) ;
8119 i := wlists.getItemFromList (l, c) ;
8120 IF isArray (ptype) AND isUnbounded (ptype)
8121 THEN
8122 noSpace (p)
8123 ELSE
8124 setNeedSpace (p)
8125 END ;
8126 v := getParameterVariable (n, i) ;
8127 IF v=NIL
8128 THEN
8129 doNamesC (p, keyc.cnamen (i, TRUE))
8130 ELSE
8131 doFQDNameC (p, v, TRUE)
8132 END ;
8133 doParamTypeNameModifier (p, ptype, FALSE) ;
8134 doUsed (p, n^.paramF.isUsed) ;
8135 doHighC (p, ptype, i, n^.paramF.isUsed) ;
8136 IF c<t
8137 THEN
8138 outText (p, ',') ; setNeedSpace (p)
8139 END ;
8140 INC (c)
8144 END doParamC ;
8148 doVarParamC - emit a VAR parameter for C/C++.
8151 PROCEDURE doVarParamC (p: pretty; n: node) ;
8154 ptype: node ;
8155 i : Name ;
8156 c, t : CARDINAL ;
8157 l : wlist ;
8158 BEGIN
8159 assert (isVarParam (n)) ;
8160 ptype := getType (n) ;
8161 IF n^.varparamF.namelist = NIL
8162 THEN
8163 doTypeNameC (p, ptype) ;
8164 (* doTypeC (p, ptype, n) ; *)
8165 IF NOT isArray (ptype)
8166 THEN
8167 setNeedSpace (p) ;
8168 outText (p, "*")
8169 END ;
8170 doUsed (p, n^.varparamF.isUsed) ;
8171 IF isArray (ptype) AND isUnbounded (ptype)
8172 THEN
8173 outText (p, ',') ; setNeedSpace (p) ;
8174 outText (p, 'unsigned int')
8176 ELSE
8177 assert (isIdentList (n^.varparamF.namelist)) ;
8178 l := n^.varparamF.namelist^.identlistF.names ;
8179 IF l=NIL
8180 THEN
8181 doParamTypeEmit (p, n, ptype) ;
8182 doUsed (p, n^.varparamF.isUsed)
8183 ELSE
8184 t := wlists.noOfItemsInList (l) ;
8185 c := 1 ;
8186 WHILE c <= t DO
8187 doParamTypeEmit (p, n, ptype) ;
8188 IF NOT isArray (ptype)
8189 THEN
8190 setNeedSpace (p) ;
8191 outText (p, "*")
8192 END ;
8193 i := wlists.getItemFromList (l, c) ;
8194 v := getParameterVariable (n, i) ;
8195 IF v=NIL
8196 THEN
8197 doNamesC (p, keyc.cnamen (i, TRUE))
8198 ELSE
8199 doFQDNameC (p, v, TRUE)
8200 END ;
8201 doParamTypeNameModifier (p, ptype, TRUE) ;
8202 doUsed (p, n^.varparamF.isUsed) ;
8203 doHighC (p, ptype, i, n^.varparamF.isUsed) ;
8204 IF c<t
8205 THEN
8206 outText (p, ',') ; setNeedSpace (p)
8207 END ;
8208 INC (c)
8212 END doVarParamC ;
8216 doOptargC -
8219 PROCEDURE doOptargC (p: pretty; n: node) ;
8221 ptype: node ;
8222 i : Name ;
8223 t : CARDINAL ;
8224 l : wlist ;
8225 BEGIN
8226 assert (isOptarg (n)) ;
8227 ptype := getType (n) ;
8228 assert (n^.optargF.namelist # NIL) ;
8229 assert (isIdentList (n^.paramF.namelist)) ;
8230 l := n^.paramF.namelist^.identlistF.names ;
8231 assert (l # NIL) ;
8232 t := wlists.noOfItemsInList (l) ;
8233 assert (t = 1) ;
8234 doTypeNameC (p, ptype) ;
8235 i := wlists.getItemFromList (l, 1) ;
8236 setNeedSpace (p) ;
8237 doNamesC (p, i)
8238 END doOptargC ;
8242 doParameterC -
8245 PROCEDURE doParameterC (p: pretty; n: node) ;
8246 BEGIN
8247 IF isParam (n)
8248 THEN
8249 doParamC (p, n)
8250 ELSIF isVarParam (n)
8251 THEN
8252 doVarParamC (p, n)
8253 ELSIF isVarargs (n)
8254 THEN
8255 print (p, "...")
8256 ELSIF isOptarg (n)
8257 THEN
8258 doOptargC (p, n)
8260 END doParameterC ;
8264 doProcTypeC -
8267 PROCEDURE doProcTypeC (p: pretty; t, n: node) ;
8268 BEGIN
8269 assert (isType (t)) ;
8270 IF isDeclType (t) AND isDeclType (n)
8271 THEN
8272 outputPartial (t) ;
8273 doCompletePartialProcType (p, t, n)
8275 END doProcTypeC ;
8279 isDeclInImp - returns TRUE if node type is declared as an opaque and
8280 is declared fully in the current implementation module.
8281 This should only be called if isType (type). Its purpose
8282 is specific to a type checking whether it is an opaque type
8283 declared in the .def/.mod pair of the current imp module.
8286 PROCEDURE isDeclInImp (type: node) : BOOLEAN ;
8288 scope,
8289 def : node ;
8290 name : Name ;
8291 BEGIN
8292 assert (isType (type)) ;
8293 scope := getScope (type) ;
8294 IF isTypeOpaqueDefImp (type) AND isImp (currentModule)
8295 THEN
8296 name := getSymName (type) ;
8297 IF name # NulName
8298 THEN
8299 (* Lookup the matching .def module. *)
8300 def := lookupDef (getSymName (currentModule)) ;
8301 IF (def # NIL) AND ((def = scope) OR (currentModule = scope))
8302 THEN
8303 (* Return TRUE if the symbol has already been declared in the .def. *)
8304 RETURN lookupExported (def, name) # NIL
8307 END ;
8308 RETURN FALSE
8309 END isDeclInImp ;
8313 doTypeNameModifier - adds the __opaque modifier to the type n provided
8314 it is an opaque type which is being declared in the
8315 implementation module.
8318 PROCEDURE doTypeNameModifier (p: pretty; n: node) ;
8319 BEGIN
8320 IF isTypeOpaqueDefImp (n) AND isImp (currentModule)
8321 THEN
8322 outText (p, '__opaque')
8324 END doTypeNameModifier ;
8328 isGccType - return TRUE if n is tree or location_t.
8331 PROCEDURE isGccType (n: node) : BOOLEAN ;
8332 BEGIN
8333 RETURN (getGccConfigSystem () AND
8334 ((getSymName (n) = makeKey ('location_t')) OR
8335 (getSymName (n) = makeKey ('tree'))))
8336 END isGccType ;
8340 doGccType - record whether we are going to declare tree or location_t
8341 so that the appropriate gcc header can be included instead.
8344 PROCEDURE doGccType (p: pretty; n: node) ;
8345 BEGIN
8346 IF getGccConfigSystem ()
8347 THEN
8348 IF getSymName (n) = makeKey ('location_t')
8349 THEN
8350 outText (p, "/* Not going to declare ") ;
8351 doTypeNameC (p, n) ;
8352 outText (p, " as it is declared in the gcc header input.h. */\n\n") ;
8353 keyc.useGccLocation
8354 ELSIF getSymName (n) = makeKey ('tree')
8355 THEN
8356 outText (p, "/* Not going to declare ") ;
8357 doTypeNameC (p, n) ;
8358 outText (p, " as it is declared in the gcc header tree.h. */\n\n") ;
8359 keyc.useGccTree
8362 END doGccType ;
8366 isCDataType - return true if n is charStar or constCharStar.
8369 PROCEDURE isCDataType (n: node) : BOOLEAN ;
8370 BEGIN
8371 RETURN (n # NIL) AND ((n = charStarN) OR (n = constCharStarN))
8372 END isCDataType ;
8376 isCDataTypes - return TRUE if n is CharStar or ConstCharStar.
8379 PROCEDURE isCDataTypes (n: node) : BOOLEAN ;
8381 scope: node ;
8382 BEGIN
8383 scope := getScope (n) ;
8384 RETURN (scope # NIL) AND (getSymName (scope) = makeKey ('CDataTypes')) AND
8385 ((getSymName (n) = makeKey ('CharStar')) OR
8386 (getSymName (n) = makeKey ('ConstCharStar')))
8387 END isCDataTypes ;
8391 doCDataTypes - if we are going to declare CharStar or ConstCharStar
8392 then generate a comment instead.
8395 PROCEDURE doCDataTypes (p: pretty; n: node) ;
8396 BEGIN
8397 IF isCDataTypes (n)
8398 THEN
8399 IF getSymName (n) = makeKey ('CharStar')
8400 THEN
8401 outText (p, "/* Not going to declare ") ;
8402 doTypeNameC (p, n) ;
8403 outText (p, " as it is a C type. */\n\n") ;
8404 charStarN := n
8405 ELSIF getSymName (n) = makeKey ('ConstCharStar')
8406 THEN
8407 outText (p, "/* Not going to declare ") ;
8408 doTypeNameC (p, n) ;
8409 outText (p, " as it is a C type. */\n\n") ;
8410 constCharStarN := n
8413 END doCDataTypes ;
8417 doCDataTypesC - generate the C representation of the CDataTypes data types.
8420 PROCEDURE doCDataTypesC (p: pretty; n: node) ;
8421 BEGIN
8422 IF n = charStarN
8423 THEN
8424 outText (p, "char *") ;
8425 setNeedSpace (p)
8426 ELSIF n = constCharStarN
8427 THEN
8428 outText (p, "const char *") ;
8429 setNeedSpace (p)
8431 END doCDataTypesC ;
8435 doTypeOrPointer - only declare type or pointer n providing that
8436 the name is not location_t or tree and
8437 the --gccConfigSystem option is enabled.
8440 PROCEDURE doTypeOrPointer (p: pretty; n: node) ;
8442 m: node ;
8443 BEGIN
8444 IF isGccType (n)
8445 THEN
8446 doGccType (p, n)
8447 ELSIF isCDataTypes (n)
8448 THEN
8449 doCDataTypes (p, n)
8450 ELSE
8451 m := getType (n) ;
8452 outText (p, "typedef") ; setNeedSpace (p) ;
8453 doTypeC (p, m, m) ;
8454 IF isType (m)
8455 THEN
8456 setNeedSpace (p)
8457 END ;
8458 doTypeNameC (p, n) ;
8459 doTypeNameModifier (p, n) ;
8460 outText (p, ";\n\n")
8462 END doTypeOrPointer ;
8466 doTypedef - generate a typedef for n provuiding it is not
8469 PROCEDURE doTypedef (p: pretty; n: node) ;
8471 m: node ;
8472 BEGIN
8473 IF isGccType (n)
8474 THEN
8475 doGccType (p, n)
8476 ELSIF isCDataTypes (n)
8477 THEN
8478 doCDataTypes (p, n)
8479 ELSE
8480 m := getType (n) ;
8481 outText (p, "typedef") ; setNeedSpace (p) ;
8482 doTypeC (p, m, m) ;
8483 IF isType (m)
8484 THEN
8485 setNeedSpace (p)
8486 END ;
8487 doTypeNameC (p, n) ;
8488 doTypeNameModifier (p, n) ;
8489 outText (p, ";\n\n")
8491 END doTypedef ;
8495 doTypesC -
8498 PROCEDURE doTypesC (n: node) ;
8500 m: node ;
8501 BEGIN
8502 IF isType (n)
8503 THEN
8504 m := getType (n) ;
8505 IF isProcType (m)
8506 THEN
8507 doProcTypeC (doP, n, m)
8508 ELSIF isType (m) OR isPointer (m)
8509 THEN
8510 doTypeOrPointer (doP, n)
8511 ELSIF isEnumeration (m)
8512 THEN
8513 IF isDeclType (n)
8514 THEN
8515 outText (doP, "typedef") ; setNeedSpace (doP) ;
8516 doTypeC (doP, m, m) ;
8517 setNeedSpace (doP) ;
8518 doTypeNameC (doP, n) ;
8519 outText (doP, ";\n\n")
8521 ELSE
8522 doTypedef (doP, n)
8525 END doTypesC ;
8529 doCompletePartialC -
8532 PROCEDURE doCompletePartialC (n: node) ;
8534 m: node ;
8535 BEGIN
8536 IF isType (n)
8537 THEN
8538 m := getType (n) ;
8539 IF isRecord (m)
8540 THEN
8541 doCompletePartialRecord (doP, n, m)
8542 ELSIF isArray (m)
8543 THEN
8544 doCompletePartialArray (doP, n, m)
8545 ELSIF isProcType (m)
8546 THEN
8547 doCompletePartialProcType (doP, n, m)
8550 END doCompletePartialC ;
8554 doCompletePartialRecord -
8557 PROCEDURE doCompletePartialRecord (p: pretty; t, r: node) ;
8559 i, h: CARDINAL ;
8560 f : node ;
8561 BEGIN
8562 assert (isRecord (r)) ;
8563 assert (isType (t)) ;
8564 outText (p, "struct") ; setNeedSpace (p) ;
8565 doFQNameC (p, t) ;
8566 outText (p, "_r") ; setNeedSpace (p) ;
8567 p := outKc (p, "{\n") ;
8568 i := LowIndice (r^.recordF.listOfSons) ;
8569 h := HighIndice (r^.recordF.listOfSons) ;
8570 WHILE i<=h DO
8571 f := GetIndice (r^.recordF.listOfSons, i) ;
8572 IF isRecordField (f)
8573 THEN
8574 IF NOT f^.recordfieldF.tag
8575 THEN
8576 doRecordFieldC (p, f) ;
8577 outText (p, ";\n")
8579 ELSIF isVarient (f)
8580 THEN
8581 doVarientC (p, f) ;
8582 outText (p, ";\n")
8583 ELSIF isVarientField (f)
8584 THEN
8585 doVarientFieldC (p, f)
8586 END ;
8587 INC (i)
8588 END ;
8589 p := outKc (p, "};\n\n")
8590 END doCompletePartialRecord ;
8594 doCompletePartialArray -
8597 PROCEDURE doCompletePartialArray (p: pretty; t, r: node) ;
8599 type, s: node ;
8600 BEGIN
8601 assert (isArray (r)) ;
8602 type := r^.arrayF.type ;
8603 s := NIL ;
8604 outText (p, "struct") ; setNeedSpace (p) ;
8605 doFQNameC (p, t) ;
8606 outText (p, "_a {") ;
8607 setNeedSpace (p) ;
8608 doTypeC (p, type, s) ;
8609 setNeedSpace (p) ;
8610 outText (p, "array[") ;
8611 doSubrC (p, r^.arrayF.subr) ;
8612 outText (p, "];") ;
8613 setNeedSpace (p) ;
8614 outText (p, "};\n")
8615 END doCompletePartialArray ;
8619 lookupConst -
8622 PROCEDURE lookupConst (type: node; n: Name) : node ;
8623 BEGIN
8624 RETURN makeLiteralInt (n)
8625 END lookupConst ;
8629 doMin -
8632 PROCEDURE doMin (n: node) : node ;
8633 BEGIN
8634 IF n=booleanN
8635 THEN
8636 RETURN falseN
8637 ELSIF n=integerN
8638 THEN
8639 keyc.useIntMin ;
8640 RETURN lookupConst (integerN, makeKey ('INT_MIN'))
8641 ELSIF n=cardinalN
8642 THEN
8643 keyc.useUIntMin ;
8644 RETURN lookupConst (cardinalN, makeKey ('UINT_MIN'))
8645 ELSIF n=longintN
8646 THEN
8647 keyc.useLongMin ;
8648 RETURN lookupConst (longintN, makeKey ('LONG_MIN'))
8649 ELSIF n=longcardN
8650 THEN
8651 keyc.useULongMin ;
8652 RETURN lookupConst (longcardN, makeKey ('LONG_MIN'))
8653 ELSIF n=charN
8654 THEN
8655 keyc.useCharMin ;
8656 RETURN lookupConst (charN, makeKey ('CHAR_MIN'))
8657 ELSIF n=bitsetN
8658 THEN
8659 assert (isSubrange (bitnumN)) ;
8660 RETURN bitnumN^.subrangeF.low
8661 ELSIF n=locN
8662 THEN
8663 keyc.useUCharMin ;
8664 RETURN lookupConst (locN, makeKey ('UCHAR_MIN'))
8665 ELSIF n=byteN
8666 THEN
8667 keyc.useUCharMin ;
8668 RETURN lookupConst (byteN, makeKey ('UCHAR_MIN'))
8669 ELSIF n=wordN
8670 THEN
8671 keyc.useUIntMin ;
8672 RETURN lookupConst (wordN, makeKey ('UCHAR_MIN'))
8673 ELSIF n=addressN
8674 THEN
8675 RETURN lookupConst (addressN, makeKey ('((void *) 0)'))
8676 ELSE
8677 HALT (* finish the cacading elsif statement. *)
8679 END doMin ;
8683 doMax -
8686 PROCEDURE doMax (n: node) : node ;
8687 BEGIN
8688 IF n=booleanN
8689 THEN
8690 RETURN trueN
8691 ELSIF n=integerN
8692 THEN
8693 keyc.useIntMax ;
8694 RETURN lookupConst (integerN, makeKey ('INT_MAX'))
8695 ELSIF n=cardinalN
8696 THEN
8697 keyc.useUIntMax ;
8698 RETURN lookupConst (cardinalN, makeKey ('UINT_MAX'))
8699 ELSIF n=longintN
8700 THEN
8701 keyc.useLongMax ;
8702 RETURN lookupConst (longintN, makeKey ('LONG_MAX'))
8703 ELSIF n=longcardN
8704 THEN
8705 keyc.useULongMax ;
8706 RETURN lookupConst (longcardN, makeKey ('ULONG_MAX'))
8707 ELSIF n=charN
8708 THEN
8709 keyc.useCharMax ;
8710 RETURN lookupConst (charN, makeKey ('CHAR_MAX'))
8711 ELSIF n=bitsetN
8712 THEN
8713 assert (isSubrange (bitnumN)) ;
8714 RETURN bitnumN^.subrangeF.high
8715 ELSIF n=locN
8716 THEN
8717 keyc.useUCharMax ;
8718 RETURN lookupConst (locN, makeKey ('UCHAR_MAX'))
8719 ELSIF n=byteN
8720 THEN
8721 keyc.useUCharMax ;
8722 RETURN lookupConst (byteN, makeKey ('UCHAR_MAX'))
8723 ELSIF n=wordN
8724 THEN
8725 keyc.useUIntMax ;
8726 RETURN lookupConst (wordN, makeKey ('UINT_MAX'))
8727 ELSIF n=addressN
8728 THEN
8729 metaError1 ('trying to obtain MAX ({%1ad}) is illegal', n) ;
8730 RETURN NIL
8731 ELSE
8732 HALT (* finish the cacading elsif statement. *)
8734 END doMax ;
8738 getMax -
8741 PROCEDURE getMax (n: node) : node ;
8742 BEGIN
8743 n := skipType (n) ;
8744 IF isSubrange (n)
8745 THEN
8746 RETURN n^.subrangeF.high
8747 ELSIF isEnumeration (n)
8748 THEN
8749 RETURN n^.enumerationF.high
8750 ELSE
8751 assert (isOrdinal (n)) ;
8752 RETURN doMax (n)
8754 END getMax ;
8758 getMin -
8761 PROCEDURE getMin (n: node) : node ;
8762 BEGIN
8763 n := skipType (n) ;
8764 IF isSubrange (n)
8765 THEN
8766 RETURN n^.subrangeF.low
8767 ELSIF isEnumeration (n)
8768 THEN
8769 RETURN n^.enumerationF.low
8770 ELSE
8771 assert (isOrdinal (n)) ;
8772 RETURN doMin (n)
8774 END getMin ;
8778 doSubtractC -
8781 PROCEDURE doSubtractC (p: pretty; s: node) ;
8782 BEGIN
8783 IF NOT isZero (s)
8784 THEN
8785 outText (p, "-") ;
8786 doExprC (p, s)
8788 END doSubtractC ;
8792 doSubrC -
8795 PROCEDURE doSubrC (p: pretty; s: node) ;
8797 low, high: node ;
8798 BEGIN
8799 s := skipType (s) ;
8800 IF isOrdinal (s)
8801 THEN
8802 low := getMin (s) ;
8803 high := getMax (s) ;
8804 doExprC (p, high) ;
8805 doSubtractC (p, low) ;
8806 outText (p, "+1")
8807 ELSIF isEnumeration (s)
8808 THEN
8809 low := getMin (s) ;
8810 high := getMax (s) ;
8811 doExprC (p, high) ;
8812 doSubtractC (p, low) ;
8813 outText (p, "+1")
8814 ELSE
8815 assert (isSubrange (s)) ;
8816 IF (s^.subrangeF.high = NIL) OR (s^.subrangeF.low = NIL)
8817 THEN
8818 doSubrC (p, getType (s))
8819 ELSE
8820 doExprC (p, s^.subrangeF.high) ;
8821 doSubtractC (p, s^.subrangeF.low) ;
8822 outText (p, "+1")
8825 END doSubrC ;
8829 doCompletePartialProcType -
8832 PROCEDURE doCompletePartialProcType (p: pretty; t, n: node) ;
8833 BEGIN
8834 IF isDeclType (t) AND isDeclType (n)
8835 THEN
8836 outputCompletePartialProcType (p, t, n)
8838 END doCompletePartialProcType ;
8842 outputCompletePartialProcType -
8845 PROCEDURE outputCompletePartialProcType (p: pretty; t, n: node) ;
8847 i, h: CARDINAL ;
8848 v, u: node ;
8849 BEGIN
8850 assert (isProcType (n)) ;
8851 u := NIL ;
8852 outText (p, "typedef") ; setNeedSpace (p) ;
8853 doTypeC (p, n^.proctypeF.returnType, u) ;
8854 doOpaqueModifier (p, n) ;
8855 setNeedSpace (p) ;
8856 outText (p, "(*") ;
8857 doFQNameC (p, t) ;
8858 outText (p, "_t) (") ;
8859 i := LowIndice (n^.proctypeF.parameters) ;
8860 h := HighIndice (n^.proctypeF.parameters) ;
8861 WHILE i <= h DO
8862 v := GetIndice (n^.proctypeF.parameters, i) ;
8863 doParameterC (p, v) ;
8864 noSpace (p) ;
8865 IF i < h
8866 THEN
8867 outText (p, ",") ; setNeedSpace (p)
8868 END ;
8869 INC (i)
8870 END ;
8871 IF h=0
8872 THEN
8873 outText (p, "void")
8874 END ;
8875 outText (p, ");\n") ;
8876 IF isDefForCNode (n)
8877 THEN
8878 (* emit a C named type which differs from the m2 proctype. *)
8879 outText (p, "typedef") ; setNeedSpace (p) ;
8880 doFQNameC (p, t) ;
8881 outText (p, "_t") ; setNeedSpace (p) ;
8882 doFQNameC (p, t) ;
8883 outText (p, "_C;\n\n")
8884 END ;
8885 outText (p, "struct") ; setNeedSpace (p) ;
8886 doFQNameC (p, t) ;
8887 outText (p, "_p {") ; setNeedSpace (p) ;
8888 doFQNameC (p, t) ;
8889 outText (p, "_t proc; };\n\n")
8890 END outputCompletePartialProcType ;
8894 isBase -
8897 PROCEDURE isBase (n: node) : BOOLEAN ;
8898 BEGIN
8899 CASE n^.kind OF
8901 char,
8902 cardinal,
8903 longcard,
8904 shortcard,
8905 integer,
8906 longint,
8907 shortint,
8908 complex,
8909 longcomplex,
8910 shortcomplex,
8911 real,
8912 longreal,
8913 shortreal,
8914 bitset,
8915 boolean,
8916 proc : RETURN TRUE
8918 ELSE
8919 RETURN FALSE
8921 END isBase ;
8925 doBoolC -
8928 PROCEDURE doBoolC (p: pretty) ;
8929 BEGIN
8930 IF useBool ()
8931 THEN
8932 outText (p, 'bool')
8933 ELSE
8934 outText (p, 'unsigned int')
8936 END doBoolC ;
8940 doBaseC -
8943 PROCEDURE doBaseC (p: pretty; n: node) ;
8944 BEGIN
8945 CASE n^.kind OF
8947 char : outText (p, 'char') |
8948 cardinal : outText (p, 'unsigned int') |
8949 longcard : outText (p, 'long unsigned int') |
8950 shortcard : outText (p, 'short unsigned int') |
8951 integer : outText (p, 'int') |
8952 longint : outText (p, 'long int') |
8953 shortint : outText (p, 'short int') |
8954 complex : outText (p, 'double complex') |
8955 longcomplex : outText (p, 'long double complex') |
8956 shortcomplex: outText (p, 'float complex') |
8957 real : outTextS (p, getCRealType ()) |
8958 longreal : outTextS (p, getCLongRealType ()) |
8959 shortreal : outTextS (p, getCShortRealType ()) |
8960 bitset : outText (p, 'unsigned int') |
8961 boolean : doBoolC (p) |
8962 proc : outText (p, 'PROC')
8964 END ;
8965 setNeedSpace (p)
8966 END doBaseC ;
8970 isSystem -
8973 PROCEDURE isSystem (n: node) : BOOLEAN ;
8974 BEGIN
8975 CASE n^.kind OF
8977 address: RETURN TRUE |
8978 loc : RETURN TRUE |
8979 byte : RETURN TRUE |
8980 word : RETURN TRUE |
8981 csizet : RETURN TRUE |
8982 cssizet: RETURN TRUE
8984 ELSE
8985 RETURN FALSE
8987 END isSystem ;
8991 doSystemC -
8994 PROCEDURE doSystemC (p: pretty; n: node) ;
8995 BEGIN
8996 CASE n^.kind OF
8998 address: outText (p, 'void *') |
8999 loc : outText (p, 'unsigned char') ; setNeedSpace (p) |
9000 byte : outText (p, 'unsigned char') ; setNeedSpace (p) |
9001 word : outText (p, 'unsigned int') ; setNeedSpace (p) |
9002 csizet : outText (p, 'size_t') ; setNeedSpace (p) ; keyc.useSize_t |
9003 cssizet: outText (p, 'ssize_t') ; setNeedSpace (p) ; keyc.useSSize_t
9006 END doSystemC ;
9010 doArrayC -
9013 PROCEDURE doArrayC (p: pretty; n: node) ;
9015 t, s, u: node ;
9016 BEGIN
9017 assert (isArray (n)) ;
9018 t := n^.arrayF.type ;
9019 s := n^.arrayF.subr ;
9020 u := NIL ;
9021 IF s=NIL
9022 THEN
9023 doTypeC (p, t, u) ;
9024 setNeedSpace (p) ;
9025 outText (p, "*")
9026 ELSE
9027 outText (p, "struct") ;
9028 setNeedSpace (p) ;
9029 outText (p, "{") ;
9030 setNeedSpace (p) ;
9031 doTypeC (p, t, u) ;
9032 setNeedSpace (p) ;
9033 outText (p, "array[") ;
9034 IF isZero (getMin (s))
9035 THEN
9036 doExprC (p, getMax (s))
9037 ELSE
9038 doExprC (p, getMax (s)) ;
9039 doSubtractC (p, getMin (s))
9040 END ;
9041 outText (p, "];") ;
9042 setNeedSpace (p) ;
9043 outText (p, "}") ;
9044 setNeedSpace (p)
9046 END doArrayC ;
9050 doPointerC -
9053 PROCEDURE doPointerC (p: pretty; n: node; VAR m: node) ;
9055 t, s: node ;
9056 BEGIN
9057 t := n^.pointerF.type ;
9058 s := NIL ;
9059 doTypeC (p, t, s) ;
9060 setNeedSpace (p) ;
9061 outText (p, "*")
9062 END doPointerC ;
9066 doRecordFieldC -
9069 PROCEDURE doRecordFieldC (p: pretty; f: node) ;
9071 m: node ;
9072 BEGIN
9073 m := NIL ;
9074 setNeedSpace (p) ;
9075 doTypeC (p, f^.recordfieldF.type, m) ;
9076 IF isType (f^.recordfieldF.type) AND isDeclInImp (f^.recordfieldF.type)
9077 THEN
9078 outText (p, '__opaque')
9079 END ;
9080 setNeedSpace (p) ;
9081 doDNameC (p, f, FALSE)
9082 END doRecordFieldC ;
9086 doVarientFieldC -
9089 PROCEDURE doVarientFieldC (p: pretty; n: node) ;
9091 i, t: CARDINAL ;
9092 q : node ;
9093 BEGIN
9094 assert (isVarientField (n)) ;
9095 IF NOT n^.varientfieldF.simple
9096 THEN
9097 outText (p, "struct") ; setNeedSpace (p) ;
9098 p := outKc (p, "{\n")
9099 END ;
9100 i := LowIndice (n^.varientfieldF.listOfSons) ;
9101 t := HighIndice (n^.varientfieldF.listOfSons) ;
9102 WHILE i<=t DO
9103 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
9104 IF isRecordField (q)
9105 THEN
9106 IF NOT q^.recordfieldF.tag
9107 THEN
9108 doRecordFieldC (p, q) ;
9109 outText (p, ";\n")
9111 ELSIF isVarient (q)
9112 THEN
9113 doVarientC (p, q) ;
9114 outText (p, ";\n")
9115 ELSE
9116 HALT
9117 END ;
9118 INC (i)
9119 END ;
9120 IF NOT n^.varientfieldF.simple
9121 THEN
9122 p := outKc (p, "};\n")
9124 END doVarientFieldC ;
9128 doVarientC -
9131 PROCEDURE doVarientC (p: pretty; n: node) ;
9133 i, t: CARDINAL ;
9134 q : node ;
9135 BEGIN
9136 assert (isVarient (n)) ;
9137 IF n^.varientF.tag # NIL
9138 THEN
9139 IF isRecordField (n^.varientF.tag)
9140 THEN
9141 doRecordFieldC (p, n^.varientF.tag) ;
9142 outText (p, "; /* case tag */\n")
9143 ELSIF isVarientField (n^.varientF.tag)
9144 THEN
9145 HALT
9146 (* doVarientFieldC (p, n^.varientF.tag) *)
9147 ELSE
9148 HALT
9150 END ;
9151 outText (p, "union") ;
9152 setNeedSpace (p) ;
9153 p := outKc (p, "{\n") ;
9154 i := LowIndice (n^.varientF.listOfSons) ;
9155 t := HighIndice (n^.varientF.listOfSons) ;
9156 WHILE i<=t DO
9157 q := GetIndice (n^.varientF.listOfSons, i) ;
9158 IF isRecordField (q)
9159 THEN
9160 IF NOT q^.recordfieldF.tag
9161 THEN
9162 doRecordFieldC (p, q) ;
9163 outText (p, ";\n")
9165 ELSIF isVarientField (q)
9166 THEN
9167 doVarientFieldC (p, q)
9168 ELSE
9169 HALT
9170 END ;
9171 INC (i)
9172 END ;
9173 p := outKc (p, "}")
9174 END doVarientC ;
9178 doRecordC -
9181 PROCEDURE doRecordC (p: pretty; n: node; VAR m: node) ;
9183 i, h: CARDINAL ;
9184 f : node ;
9185 BEGIN
9186 assert (isRecord (n)) ;
9187 outText (p, "struct") ;
9188 setNeedSpace (p) ;
9189 p := outKc (p, "{") ;
9190 i := LowIndice (n^.recordF.listOfSons) ;
9191 h := HighIndice (n^.recordF.listOfSons) ;
9192 setindent (p, getcurpos (p) + indentation) ;
9193 outText (p, "\n") ;
9194 WHILE i<=h DO
9195 f := GetIndice (n^.recordF.listOfSons, i) ;
9196 IF isRecordField (f)
9197 THEN
9198 IF NOT f^.recordfieldF.tag
9199 THEN
9200 doRecordFieldC (p, f) ;
9201 outText (p, ";\n")
9203 ELSIF isVarient (f)
9204 THEN
9205 doVarientC (p, f) ;
9206 outText (p, ";\n")
9207 ELSIF isVarientField (f)
9208 THEN
9209 doVarientFieldC (p, f)
9210 END ;
9211 INC (i)
9212 END ;
9213 p := outKc (p, "}") ;
9214 setNeedSpace (p)
9215 END doRecordC ;
9219 isBitset -
9222 PROCEDURE isBitset (n: node) : BOOLEAN ;
9223 BEGIN
9224 RETURN n = bitsetN
9225 END isBitset ;
9229 isNegative - returns TRUE if expression, n, is negative.
9232 PROCEDURE isNegative (n: node) : BOOLEAN ;
9233 BEGIN
9234 (* --fixme-- needs to be completed. *)
9235 RETURN FALSE
9236 END isNegative ;
9240 doSubrangeC -
9243 PROCEDURE doSubrangeC (p: pretty; n: node) ;
9244 BEGIN
9245 assert (isSubrange (n)) ;
9246 IF isNegative (n^.subrangeF.low)
9247 THEN
9248 outText (p, "int") ; setNeedSpace (p)
9249 ELSE
9250 outText (p, "unsigned int") ; setNeedSpace (p)
9252 END doSubrangeC ;
9256 doSetC - generates a C type which holds the set.
9257 Currently we only support sets of size WORD.
9260 PROCEDURE doSetC (p: pretty; n: node) ;
9261 BEGIN
9262 assert (isSet (n)) ;
9263 outText (p, "unsigned int") ; setNeedSpace (p)
9264 END doSetC ;
9268 doTypeC -
9271 PROCEDURE doTypeC (p: pretty; n: node; VAR m: node) ;
9272 BEGIN
9273 IF n=NIL
9274 THEN
9275 outText (p, "void")
9276 ELSIF isCDataTypes (n)
9277 THEN
9278 doCDataTypesC (p, n)
9279 ELSIF isBase (n)
9280 THEN
9281 doBaseC (p, n)
9282 ELSIF isSystem (n)
9283 THEN
9284 doSystemC (p, n)
9285 ELSIF isEnumeration (n)
9286 THEN
9287 doEnumerationC (p, n)
9288 ELSIF isType (n)
9289 THEN
9290 doFQNameC (p, n)
9291 ELSIF isProcType (n)
9292 THEN
9293 doProcTypeC (p, n, m)
9294 ELSIF isArray (n)
9295 THEN
9296 doArrayC (p, n)
9297 ELSIF isRecord (n)
9298 THEN
9299 doRecordC (p, n, m)
9300 ELSIF isPointer (n)
9301 THEN
9302 doPointerC (p, n, m)
9303 ELSIF isSubrange (n)
9304 THEN
9305 doSubrangeC (p, n)
9306 ELSIF isSet (n)
9307 THEN
9308 doSetC (p, n)
9309 ELSIF isCDataTypes (n)
9310 THEN
9311 doCDataTypesC (p, n)
9312 ELSE
9313 metaError1 ('expecting a type symbol rather than a {%1DMd} {%1DMa}', n) ;
9314 flushErrors ;
9315 errorAbort0 ('terminating compilation')
9317 END doTypeC ;
9321 doArrayNameC - it displays the array declaration (it might be an unbounded).
9324 PROCEDURE doArrayNameC (p: pretty; n: node) ;
9325 BEGIN
9326 doTypeNameC (p, getType (n)) ; setNeedSpace (p) ; outText (p, "*")
9327 END doArrayNameC ;
9331 doRecordNameC - emit the C/C++ record name <name of n>"_r".
9334 PROCEDURE doRecordNameC (p: pretty; n: node) ;
9336 s: String ;
9337 BEGIN
9338 s := getFQstring (n) ;
9339 s := ConCat (s, Mark (InitString ("_r"))) ;
9340 outTextS (p, s) ;
9341 s := KillString (s)
9342 END doRecordNameC ;
9346 doPointerNameC - emit the C/C++ pointer type <name of n>*.
9349 PROCEDURE doPointerNameC (p: pretty; n: node) ;
9350 BEGIN
9351 doTypeNameC (p, getType (n)) ; setNeedSpace (p) ; outText (p, "*")
9352 END doPointerNameC ;
9356 doTypeNameC -
9359 PROCEDURE doTypeNameC (p: pretty; n: node) ;
9361 t: String ;
9362 BEGIN
9363 IF n=NIL
9364 THEN
9365 outText (p, "void") ;
9366 setNeedSpace (p)
9367 ELSIF n = charStarN
9368 THEN
9369 outText (p, "char *") ;
9370 setNeedSpace (p)
9371 ELSIF n = constCharStarN
9372 THEN
9373 outText (p, "const char *") ;
9374 setNeedSpace (p)
9375 ELSIF isBase (n)
9376 THEN
9377 doBaseC (p, n)
9378 ELSIF isSystem (n)
9379 THEN
9380 doSystemC (p, n)
9381 ELSIF isEnumeration (n)
9382 THEN
9383 print (p, "is enumeration type name required\n")
9384 ELSIF isType (n)
9385 THEN
9386 doFQNameC (p, n) ;
9387 ELSIF isProcType (n)
9388 THEN
9389 doFQNameC (p, n) ;
9390 outText (p, "_t")
9391 ELSIF isArray (n)
9392 THEN
9393 doArrayNameC (p, n)
9394 ELSIF isRecord (n)
9395 THEN
9396 doRecordNameC (p, n)
9397 ELSIF isPointer (n)
9398 THEN
9399 doPointerNameC (p, n)
9400 ELSIF isSubrange (n)
9401 THEN
9402 doSubrangeC (p, n)
9403 ELSE
9404 print (p, "is type unknown required\n")
9406 END doTypeNameC ;
9410 isExternal - returns TRUE if symbol, n, was declared in another module.
9413 PROCEDURE isExternal (n: node) : BOOLEAN ;
9415 s: node ;
9416 BEGIN
9417 s := getScope (n) ;
9418 RETURN (s # NIL) AND isDef (s) AND
9419 ((isImp (getMainModule ()) AND (s # lookupDef (getSymName (getMainModule ())))) OR
9420 isModule (getMainModule ()))
9421 END isExternal ;
9425 doOpaqueModifier - adds postfix __opaque providing n uses an opaque type which is
9426 not represented by ( void * ). n is a non type node which might
9427 be using an opaque type. For example a var or param node.
9430 PROCEDURE doOpaqueModifier (p: pretty; n: node) ;
9431 BEGIN
9432 assert (NOT isType (n)) ;
9433 IF isImp (getCurrentModule ()) AND nodeUsesOpaque (n) AND (NOT getNodeOpaqueVoidStar (n))
9434 THEN
9435 outText (doP, '__opaque')
9437 END doOpaqueModifier ;
9441 doDeclareVarC -
9444 PROCEDURE doDeclareVarC (n: node) ;
9446 type,
9447 s : node ;
9448 BEGIN
9449 s := NIL ;
9450 type := getType (n) ;
9451 doTypeC (doP, type, s) ;
9452 doOpaqueModifier (doP, n) ;
9453 setNeedSpace (doP) ;
9454 doFQDNameC (doP, n, FALSE) ;
9455 print (doP, ";\n")
9456 END doDeclareVarC ;
9460 doVarC - output a variable declaration. Note that we do not generate
9461 a declaration if we are translating the implementation module
9462 and a variable is exported as the variable will be in the .h
9463 file to avoid all -Wodr issues.
9466 PROCEDURE doVarC (n: node) ;
9467 BEGIN
9468 IF isDef (getMainModule ())
9469 THEN
9470 print (doP, "EXTERN") ; setNeedSpace (doP) ;
9471 doDeclareVarC (n)
9472 ELSIF (NOT isExported (n)) AND (NOT isLocal (n))
9473 THEN
9474 print (doP, "static") ; setNeedSpace (doP) ;
9475 doDeclareVarC (n)
9476 ELSIF getExtendedOpaque ()
9477 THEN
9478 (* --fixme-- need to revisit extended opaque. *)
9479 IF isExternal (n)
9480 THEN
9481 (* different module declared this variable, therefore it is extern. *)
9482 print (doP, "extern") ; setNeedSpace (doP)
9483 END ;
9484 doDeclareVarC (n)
9485 ELSIF isLocal (n)
9486 THEN
9487 doDeclareVarC (n)
9489 END doVarC ;
9493 doExternCP -
9496 PROCEDURE doExternCP (p: pretty) ;
9497 BEGIN
9498 IF lang = ansiCP
9499 THEN
9500 outText (p, 'extern "C"') ; setNeedSpace (p)
9502 END doExternCP ;
9506 doProcedureCommentText -
9509 PROCEDURE doProcedureCommentText (p: pretty; s: String) ;
9510 BEGIN
9511 (* remove \n from the start of the comment. *)
9512 WHILE (DynamicStrings.Length (s) > 0) AND (DynamicStrings.char (s, 0) = lf) DO
9513 s := DynamicStrings.Slice (s, 1, 0)
9514 END ;
9515 outTextS (p, s)
9516 END doProcedureCommentText ;
9520 doProcedureComment -
9523 PROCEDURE doProcedureComment (p: pretty; s: String) ;
9524 BEGIN
9525 IF s # NIL
9526 THEN
9527 outText (p, '\n/*\n') ;
9528 doProcedureCommentText (p, s) ;
9529 outText (p, '*/\n\n')
9531 END doProcedureComment ;
9535 doProcedureHeadingC -
9538 PROCEDURE doProcedureHeadingC (n: node; prototype: BOOLEAN) ;
9540 s : String ;
9541 i, h: CARDINAL ;
9542 p, q: node ;
9543 BEGIN
9544 assert (isProcedure (n)) ;
9545 s := getFQstring (n) ;
9546 IF EqualArray (s, 'M2Quads_BuildAssignment')
9547 THEN
9548 localstop
9549 END ;
9550 s := KillString (s) ;
9551 noSpace (doP) ;
9552 IF isDef (getMainModule ())
9553 THEN
9554 doProcedureComment (doP, getContent (n^.procedureF.defComment)) ;
9555 outText (doP, "EXTERN") ; setNeedSpace (doP)
9556 ELSIF isExported (n)
9557 THEN
9558 doProcedureComment (doP, getContent (n^.procedureF.modComment)) ;
9559 doExternCP (doP)
9560 ELSE
9561 doProcedureComment (doP, getContent (n^.procedureF.modComment)) ;
9562 outText (doP, "static") ; setNeedSpace (doP)
9563 END ;
9564 q := NIL ;
9565 doTypeC (doP, n^.procedureF.returnType, q) ;
9567 IF NOT isExported (n)
9568 THEN
9569 doTypeNameModifier (doP, n^.procedureF.returnType)
9570 END ;
9572 doOpaqueModifier (doP, n) ;
9573 setNeedSpace (doP) ;
9574 doFQDNameC (doP, n, FALSE) ;
9575 setNeedSpace (doP) ;
9576 outText (doP, "(") ;
9577 i := LowIndice (n^.procedureF.parameters) ;
9578 h := HighIndice (n^.procedureF.parameters) ;
9579 WHILE i <= h DO
9580 p := GetIndice (n^.procedureF.parameters, i) ;
9581 doParameterC (doP, p) ;
9582 noSpace (doP) ;
9583 IF i < h
9584 THEN
9585 print (doP, ",") ; setNeedSpace (doP)
9586 END ;
9587 INC (i)
9588 END ;
9589 IF h=0
9590 THEN
9591 outText (doP, "void")
9592 END ;
9593 print (doP, ")") ;
9594 IF n^.procedureF.noreturn AND prototype AND (NOT getSuppressNoReturn ())
9595 THEN
9596 setNeedSpace (doP) ;
9597 outText (doP, "__attribute__ ((noreturn))")
9599 END doProcedureHeadingC ;
9603 checkDeclareUnboundedParamCopyC -
9606 PROCEDURE checkDeclareUnboundedParamCopyC (p: pretty; n: node) : BOOLEAN ;
9608 t : node ;
9609 i, c: CARDINAL ;
9610 l : wlist ;
9611 seen: BOOLEAN ;
9612 BEGIN
9613 seen := FALSE ;
9614 t := getType (n) ;
9615 l := n^.paramF.namelist^.identlistF.names ;
9616 IF isArray (t) AND isUnbounded (t) AND (l#NIL)
9617 THEN
9618 t := getType (t) ;
9619 c := wlists.noOfItemsInList (l) ;
9620 i := 1 ;
9621 WHILE i <= c DO
9622 doTypeNameC (p, t) ;
9623 setNeedSpace (p) ;
9624 doNamesC (p, wlists.getItemFromList (l, i)) ;
9625 outText (p, '[_');
9626 doNamesC (p, wlists.getItemFromList (l, i)) ;
9627 outText (p, '_high+1];\n');
9628 seen := TRUE ;
9629 INC (i)
9631 END ;
9632 RETURN seen
9633 END checkDeclareUnboundedParamCopyC ;
9637 checkUnboundedParamCopyC -
9640 PROCEDURE checkUnboundedParamCopyC (p: pretty; n: node) ;
9642 t, s: node ;
9643 i, c: CARDINAL ;
9644 l : wlist ;
9645 BEGIN
9646 t := getType (n) ;
9647 l := n^.paramF.namelist^.identlistF.names ;
9648 IF isArray (t) AND isUnbounded (t) AND (l#NIL)
9649 THEN
9650 c := wlists.noOfItemsInList (l) ;
9651 i := 1 ;
9652 t := getType (t) ;
9653 s := skipType (t) ;
9654 WHILE i <= c DO
9655 keyc.useMemcpy ;
9656 outText (p, 'memcpy (') ;
9657 doNamesC (p, wlists.getItemFromList (l, i)) ;
9658 outText (p, ',') ;
9659 setNeedSpace (p) ;
9660 doNamesC (p, wlists.getItemFromList (l, i)) ;
9661 outText (p, '_, ') ;
9662 IF (s = charN) OR (s = byteN) OR (s = locN)
9663 THEN
9664 outText (p, '_') ;
9665 doNamesC (p, wlists.getItemFromList (l, i)) ;
9666 outText (p, '_high+1);\n')
9667 ELSE
9668 outText (p, '(_') ;
9669 doNamesC (p, wlists.getItemFromList (l, i)) ;
9670 outText (p, '_high+1)') ;
9671 setNeedSpace (p) ;
9672 doMultiplyBySize (p, t) ;
9673 outText (p, ');\n')
9674 END ;
9675 INC (i)
9678 END checkUnboundedParamCopyC ;
9682 doUnboundedParamCopyC -
9685 PROCEDURE doUnboundedParamCopyC (p: pretty; n: node) ;
9687 i, h: CARDINAL ;
9688 q : node ;
9689 seen: BOOLEAN ;
9690 BEGIN
9691 assert (isProcedure (n)) ;
9692 i := LowIndice (n^.procedureF.parameters) ;
9693 h := HighIndice (n^.procedureF.parameters) ;
9694 seen := FALSE ;
9695 WHILE i <= h DO
9696 q := GetIndice (n^.procedureF.parameters, i) ;
9697 IF isParam (q)
9698 THEN
9699 seen := checkDeclareUnboundedParamCopyC (p, q) OR seen
9700 END ;
9701 INC (i)
9702 END ;
9703 IF seen
9704 THEN
9705 outText (p, "\n") ;
9706 outText (p, "/* make a local copy of each unbounded array. */\n") ;
9707 i := LowIndice (n^.procedureF.parameters) ;
9708 WHILE i <= h DO
9709 q := GetIndice (n^.procedureF.parameters, i) ;
9710 IF isParam (q)
9711 THEN
9712 checkUnboundedParamCopyC (p, q)
9713 END ;
9714 INC (i)
9717 END doUnboundedParamCopyC ;
9721 doPrototypeC -
9724 PROCEDURE doPrototypeC (n: node) ;
9725 BEGIN
9726 IF NOT isExported (n)
9727 THEN
9728 keyc.enterScope (n) ;
9729 doProcedureHeadingC (n, TRUE) ;
9730 print (doP, ";\n") ;
9731 keyc.leaveScope (n)
9733 END doPrototypeC ;
9737 addTodo - adds, n, to the todo list.
9740 PROCEDURE addTodo (n: node) ;
9741 BEGIN
9742 IF (n#NIL) AND
9743 (NOT alists.isItemInList (globalGroup^.partialQ, n)) AND
9744 (NOT alists.isItemInList (globalGroup^.doneQ, n))
9745 THEN
9746 assert (NOT isVarient (n)) ;
9747 assert (NOT isVarientField (n)) ;
9748 assert (NOT isDef (n)) ;
9749 alists.includeItemIntoList (globalGroup^.todoQ, n)
9751 END addTodo ;
9755 addVariablesTodo -
9758 PROCEDURE addVariablesTodo (n: node) ;
9759 BEGIN
9760 IF isVar (n)
9761 THEN
9762 IF n^.varF.isParameter OR n^.varF.isVarParameter
9763 THEN
9764 addDone (n) ;
9765 addTodo (getType (n))
9766 ELSE
9767 addTodo (n)
9770 END addVariablesTodo ;
9774 addTypesTodo -
9777 PROCEDURE addTypesTodo (n: node) ;
9778 BEGIN
9779 IF isUnbounded (n)
9780 THEN
9781 addDone (n)
9782 ELSE
9783 addTodo (n)
9785 END addTypesTodo ;
9789 tempName -
9792 PROCEDURE tempName () : String ;
9793 BEGIN
9794 INC (tempCount) ;
9795 RETURN Sprintf1 (InitString ("_T%d"), tempCount) ;
9796 END tempName ;
9800 makeIntermediateType -
9803 PROCEDURE makeIntermediateType (s: String; p: node) : node ;
9805 n: Name ;
9806 o: node ;
9807 BEGIN
9808 n := makekey (DynamicStrings.string (s)) ;
9809 enterScope (getScope (p)) ;
9810 o := p ;
9811 p := makeType (makekey (DynamicStrings.string (s))) ;
9812 putType (p, o) ;
9813 putTypeInternal (p) ;
9814 leaveScope ;
9815 RETURN p
9816 END makeIntermediateType ;
9820 simplifyType -
9823 PROCEDURE simplifyType (l: alist; VAR p: node) ;
9825 s: String ;
9826 BEGIN
9827 IF (p#NIL) AND (isRecord (p) OR isArray (p) OR isProcType (p)) AND (NOT isUnbounded (p))
9828 THEN
9829 s := tempName () ;
9830 p := makeIntermediateType (s, p) ;
9831 s := KillString (s) ;
9832 simplified := FALSE
9833 END ;
9834 simplifyNode (l, p)
9835 END simplifyType ;
9839 simplifyVar -
9842 PROCEDURE simplifyVar (l: alist; n: node) ;
9844 i, t: CARDINAL ;
9846 d, o: node ;
9847 BEGIN
9848 assert (isVar (n)) ;
9849 o := n^.varF.type ;
9850 simplifyType (l, n^.varF.type) ;
9851 IF o # n^.varF.type
9852 THEN
9853 (* simplification has occurred, make sure that all other variables of this type
9854 use the new type. *)
9855 d := n^.varF.decl ;
9856 assert (isVarDecl (d)) ;
9857 t := wlists.noOfItemsInList (d^.vardeclF.names) ;
9858 i := 1 ;
9859 WHILE i<=t DO
9860 v := lookupInScope (n^.varF.scope, wlists.getItemFromList (d^.vardeclF.names, i)) ;
9861 assert (isVar (v)) ;
9862 v^.varF.type := n^.varF.type ;
9863 INC (i)
9866 END simplifyVar ;
9870 simplifyRecord -
9873 PROCEDURE simplifyRecord (l: alist; n: node) ;
9875 i, t: CARDINAL ;
9876 q : node ;
9877 BEGIN
9878 i := LowIndice (n^.recordF.listOfSons) ;
9879 t := HighIndice (n^.recordF.listOfSons) ;
9880 WHILE i<=t DO
9881 q := GetIndice (n^.recordF.listOfSons, i) ;
9882 simplifyNode (l, q) ;
9883 INC (i)
9885 END simplifyRecord ;
9889 simplifyVarient -
9892 PROCEDURE simplifyVarient (l: alist; n: node) ;
9894 i, t: CARDINAL ;
9895 q : node ;
9896 BEGIN
9897 simplifyNode (l, n^.varientF.tag) ;
9898 i := LowIndice (n^.varientF.listOfSons) ;
9899 t := HighIndice (n^.varientF.listOfSons) ;
9900 WHILE i<=t DO
9901 q := GetIndice (n^.varientF.listOfSons, i) ;
9902 simplifyNode (l, q) ;
9903 INC (i)
9905 END simplifyVarient ;
9909 simplifyVarientField -
9912 PROCEDURE simplifyVarientField (l: alist; n: node) ;
9914 i, t: CARDINAL ;
9915 q : node ;
9916 BEGIN
9917 i := LowIndice (n^.varientfieldF.listOfSons) ;
9918 t := HighIndice (n^.varientfieldF.listOfSons) ;
9919 WHILE i<=t DO
9920 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
9921 simplifyNode (l, q) ;
9922 INC (i)
9924 END simplifyVarientField ;
9928 doSimplifyNode -
9931 PROCEDURE doSimplifyNode (l: alist; n: node) ;
9932 BEGIN
9933 IF n=NIL
9934 THEN
9935 (* nothing. *)
9936 ELSIF isType (n)
9937 THEN
9938 (* no need to simplify a type. *)
9939 simplifyNode (l, getType (n))
9940 ELSIF isVar (n)
9941 THEN
9942 simplifyVar (l, n)
9943 ELSIF isRecord (n)
9944 THEN
9945 simplifyRecord (l, n)
9946 ELSIF isRecordField (n)
9947 THEN
9948 simplifyType (l, n^.recordfieldF.type)
9949 ELSIF isArray (n)
9950 THEN
9951 simplifyType (l, n^.arrayF.type)
9952 ELSIF isVarient (n)
9953 THEN
9954 simplifyVarient (l, n)
9955 ELSIF isVarientField (n)
9956 THEN
9957 simplifyVarientField (l, n)
9958 ELSIF isPointer (n)
9959 THEN
9960 simplifyType (l, n^.pointerF.type)
9962 END doSimplifyNode ;
9966 simplifyNode -
9969 PROCEDURE simplifyNode (l: alist; n: node) ;
9970 BEGIN
9971 IF NOT alists.isItemInList (l, n)
9972 THEN
9973 alists.includeItemIntoList (l, n) ;
9974 doSimplifyNode (l, n)
9976 END simplifyNode ;
9980 doSimplify -
9983 PROCEDURE doSimplify (n: node) ;
9985 l: alist ;
9986 BEGIN
9987 l := alists.initList () ;
9988 simplifyNode (l, n) ;
9989 alists.killList (l)
9990 END doSimplify ;
9994 simplifyTypes -
9997 PROCEDURE simplifyTypes (s: scopeT) ;
9998 BEGIN
9999 REPEAT
10000 simplified := TRUE ;
10001 ForeachIndiceInIndexDo (s.types, doSimplify) ;
10002 ForeachIndiceInIndexDo (s.variables, doSimplify)
10003 UNTIL simplified
10004 END simplifyTypes ;
10008 outDeclsDefC -
10011 PROCEDURE outDeclsDefC (p: pretty; n: node) ;
10013 s: scopeT ;
10014 BEGIN
10015 s := n^.defF.decls ;
10016 simplifyTypes (s) ;
10017 includeConstType (s) ;
10019 doP := p ;
10021 topologicallyOut (doConstC, doTypesC, doVarC,
10022 outputPartial,
10023 doNone, doCompletePartialC, doNone) ;
10025 (* try and output types, constants before variables and procedures. *)
10026 includeDefVarProcedure (n) ;
10028 topologicallyOut (doConstC, doTypesC, doVarC,
10029 outputPartial,
10030 doNone, doCompletePartialC, doNone) ;
10032 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
10033 END outDeclsDefC ;
10037 includeConstType -
10040 PROCEDURE includeConstType (s: scopeT) ;
10041 BEGIN
10042 ForeachIndiceInIndexDo (s.constants, addTodo) ;
10043 ForeachIndiceInIndexDo (s.types, addTypesTodo)
10044 END includeConstType ;
10048 includeVarProcedure -
10051 PROCEDURE includeVarProcedure (s: scopeT) ;
10052 BEGIN
10053 ForeachIndiceInIndexDo (s.procedures, addTodo) ;
10054 ForeachIndiceInIndexDo (s.variables, addVariablesTodo)
10055 END includeVarProcedure ;
10059 includeVar -
10062 PROCEDURE includeVar (s: scopeT) ;
10063 BEGIN
10064 ForeachIndiceInIndexDo (s.variables, addTodo)
10065 END includeVar ;
10069 includeExternals -
10072 PROCEDURE includeExternals (n: node) ;
10074 l: alist ;
10075 BEGIN
10076 l := alists.initList () ;
10077 visitNode (l, n, addExported) ;
10078 alists.killList (l)
10079 END includeExternals ;
10083 checkSystemInclude -
10086 PROCEDURE checkSystemInclude (n: node) ;
10087 BEGIN
10089 END checkSystemInclude ;
10093 addExported -
10096 PROCEDURE addExported (n: node) ;
10098 s: node ;
10099 BEGIN
10100 s := getScope (n) ;
10101 IF (s # NIL) AND isDef (s) AND (s # defModule)
10102 THEN
10103 IF isType (n) OR isVar (n) OR isConst (n)
10104 THEN
10105 addTodo (n)
10108 END addExported ;
10112 addExternal - only adds, n, if this symbol is external to the
10113 implementation module and is not a hidden type.
10116 PROCEDURE addExternal (n: node) ;
10117 BEGIN
10118 IF (getScope (n) = defModule) AND isType (n) AND
10119 isTypeHidden (n) AND (NOT getExtendedOpaque ())
10120 THEN
10121 (* do nothing. *)
10122 ELSIF NOT isDef (n)
10123 THEN
10124 addTodo (n)
10126 END addExternal ;
10130 includeDefConstType -
10133 PROCEDURE includeDefConstType (n: node) ;
10135 d: node ;
10136 BEGIN
10137 IF isImp (n)
10138 THEN
10139 defModule := lookupDef (getSymName (n)) ;
10140 IF defModule#NIL
10141 THEN
10142 simplifyTypes (defModule^.defF.decls) ;
10143 includeConstType (defModule^.defF.decls) ;
10144 foreachNodeDo (defModule^.defF.decls.symbols, addExternal)
10147 END includeDefConstType ;
10151 runIncludeDefConstType -
10154 PROCEDURE runIncludeDefConstType (n: node) ;
10156 d: node ;
10157 BEGIN
10158 IF isDef (n)
10159 THEN
10160 simplifyTypes (n^.defF.decls) ;
10161 includeConstType (n^.defF.decls) ;
10162 foreachNodeDo (n^.defF.decls.symbols, addExternal)
10164 END runIncludeDefConstType ;
10168 joinProcedures - copies procedures from definition module,
10169 d, into implementation module, i.
10172 PROCEDURE joinProcedures (i, d: node) ;
10174 h, j: CARDINAL ;
10175 BEGIN
10176 assert (isDef (d)) ;
10177 assert (isImp (i)) ;
10178 j := 1 ;
10179 h := HighIndice (d^.defF.decls.procedures) ;
10180 WHILE j<=h DO
10181 IncludeIndiceIntoIndex (i^.impF.decls.procedures,
10182 GetIndice (d^.defF.decls.procedures, j)) ;
10183 INC (j)
10185 END joinProcedures ;
10189 includeDefVarProcedure -
10192 PROCEDURE includeDefVarProcedure (n: node) ;
10194 d: node ;
10195 BEGIN
10196 IF isImp (n)
10197 THEN
10198 defModule := lookupDef (getSymName (n)) ;
10199 IF defModule#NIL
10200 THEN
10202 includeVar (defModule^.defF.decls) ;
10203 simplifyTypes (defModule^.defF.decls) ;
10205 joinProcedures (n, defModule)
10207 ELSIF isDef (n)
10208 THEN
10209 includeVar (n^.defF.decls) ;
10210 simplifyTypes (n^.defF.decls)
10212 END includeDefVarProcedure ;
10216 foreachModuleDo -
10219 PROCEDURE foreachModuleDo (n: node; p: performOperation) ;
10220 BEGIN
10221 foreachDefModuleDo (p) ;
10222 foreachModModuleDo (p)
10223 END foreachModuleDo ;
10227 outDeclsImpC -
10230 PROCEDURE outDeclsImpC (p: pretty; s: scopeT) ;
10231 BEGIN
10232 simplifyTypes (s) ;
10233 includeConstType (s) ;
10235 doP := p ;
10237 topologicallyOut (doConstC, doTypesC, doVarC,
10238 outputPartial,
10239 doNone, doCompletePartialC, doNone) ;
10241 (* try and output types, constants before variables and procedures. *)
10242 includeVarProcedure (s) ;
10244 topologicallyOut (doConstC, doTypesC, doVarC,
10245 outputPartial,
10246 doNone, doCompletePartialC, doNone) ;
10248 END outDeclsImpC ;
10252 doStatementSequenceC -
10255 PROCEDURE doStatementSequenceC (p: pretty; s: node) ;
10257 i, h: CARDINAL ;
10258 BEGIN
10259 assert (isStatementSequence (s)) ;
10260 h := HighIndice (s^.stmtF.statements) ;
10261 i := 1 ;
10262 WHILE i<=h DO
10263 doStatementsC (p, GetIndice (s^.stmtF.statements, i)) ;
10264 INC (i)
10266 END doStatementSequenceC ;
10270 isStatementSequenceEmpty -
10273 PROCEDURE isStatementSequenceEmpty (s: node) : BOOLEAN ;
10274 BEGIN
10275 assert (isStatementSequence (s)) ;
10276 RETURN HighIndice (s^.stmtF.statements) = 0
10277 END isStatementSequenceEmpty ;
10281 isSingleStatement - returns TRUE if the statement sequence, s, has
10282 only one statement.
10285 PROCEDURE isSingleStatement (s: node) : BOOLEAN ;
10287 h: CARDINAL ;
10288 BEGIN
10289 assert (isStatementSequence (s)) ;
10290 h := HighIndice (s^.stmtF.statements) ;
10291 IF (h = 0) OR (h > 1)
10292 THEN
10293 RETURN FALSE
10294 END ;
10295 s := GetIndice (s^.stmtF.statements, 1) ;
10296 RETURN (NOT isStatementSequence (s)) OR isSingleStatement (s)
10297 END isSingleStatement ;
10301 doCommentC -
10304 PROCEDURE doCommentC (p: pretty; s: node) ;
10306 c: String ;
10307 BEGIN
10308 IF s # NIL
10309 THEN
10310 assert (isComment (s)) ;
10311 IF NOT isProcedureComment (s^.commentF.content)
10312 THEN
10313 IF isAfterComment (s^.commentF.content)
10314 THEN
10315 setNeedSpace (p) ;
10316 outText (p, " /* ")
10317 ELSE
10318 outText (p, "/* ")
10319 END ;
10320 c := getContent (s^.commentF.content) ;
10321 c := RemoveWhitePrefix (RemoveWhitePostfix (c)) ;
10322 outTextS (p, c) ;
10323 outText (p, " */\n")
10326 END doCommentC ;
10330 doAfterCommentC - emit an after comment, c, or a newline if, c, is empty.
10333 PROCEDURE doAfterCommentC (p: pretty; c: node) ;
10334 BEGIN
10335 IF c = NIL
10336 THEN
10337 outText (p, "\n")
10338 ELSE
10339 doCommentC (p, c)
10341 END doAfterCommentC ;
10345 doReturnC - issue a return statement and also place in an after comment if one exists.
10348 PROCEDURE doReturnC (p: pretty; s: node) ;
10350 type: node ;
10351 BEGIN
10352 assert (isReturn (s)) ;
10353 doCommentC (p, s^.returnF.returnComment.body) ;
10354 outText (p, "return") ;
10355 IF (s^.returnF.scope#NIL) AND (s^.returnF.exp#NIL)
10356 THEN
10357 setNeedSpace (p) ;
10358 IF (NOT isProcedure (s^.returnF.scope)) OR (getType (s^.returnF.scope)=NIL)
10359 THEN
10360 metaError1 ('{%1DMad} has no return type', s^.returnF.scope) ;
10361 ELSE
10362 IF isProcedure (s^.returnF.scope) AND nodeUsesOpaque (s^.returnF.scope)
10363 THEN
10364 forceCastOpaque (p, s^.returnF.scope, s^.returnF.exp,
10365 getNodeOpaqueVoidStar (s^.returnF.scope))
10366 ELSE
10367 doExprCastC (p, s^.returnF.exp, getType (s^.returnF.scope))
10370 END ;
10371 outText (p, ";") ;
10372 doAfterCommentC (p, s^.returnF.returnComment.after)
10373 END doReturnC ;
10377 isZtypeEquivalent -
10380 PROCEDURE isZtypeEquivalent (type: node) : BOOLEAN ;
10381 BEGIN
10382 CASE type^.kind OF
10384 cardinal,
10385 longcard,
10386 shortcard,
10387 integer,
10388 longint,
10389 shortint,
10390 ztype : RETURN TRUE
10392 ELSE
10393 RETURN FALSE
10395 END isZtypeEquivalent ;
10399 isEquivalentType - returns TRUE if type1 and type2 are equivalent.
10402 PROCEDURE isEquivalentType (type1, type2: node) : BOOLEAN ;
10403 BEGIN
10404 type1 := skipType (type1) ;
10405 type2 := skipType (type2) ;
10406 RETURN ((type1 = type2) OR
10407 (isZtypeEquivalent (type1) AND isZtypeEquivalent (type2)))
10408 END isEquivalentType ;
10412 doExprCastC - build a cast if necessary.
10415 PROCEDURE doExprCastC (p: pretty; e, type: node) ;
10417 stype: node ;
10418 BEGIN
10419 stype := skipType (type) ;
10420 IF (NOT isEquivalentType (type, getExprType (e))) AND
10421 (NOT ((e^.kind = nil) AND (isPointer (stype) OR (stype^.kind = address))))
10422 THEN
10423 IF lang = ansiCP
10424 THEN
10425 (* potentially a cast is required. *)
10426 IF isPointer (type) OR (type = addressN)
10427 THEN
10428 outText (p, 'static_cast<') ;
10429 doTypeNameC (p, type) ;
10430 noSpace (p) ;
10431 outText (p, '> (') ;
10432 doExprC (p, e) ;
10433 outText (p, ')') ;
10434 RETURN
10435 ELSE
10436 outText (p, 'static_cast<') ;
10437 IF isProcType (skipType (type))
10438 THEN
10439 doTypeNameC (p, type) ;
10440 outText (p, "_t")
10441 ELSE
10442 doTypeNameC (p, type)
10443 END ;
10444 noSpace (p) ;
10445 outText (p, '> (') ;
10446 doExprC (p, e) ;
10447 outText (p, ')') ;
10448 RETURN
10451 END ;
10452 doExprC (p, e)
10453 END doExprCastC ;
10457 requiresUnpackProc - returns TRUE if either the expr is a procedure or the proctypes differ.
10460 PROCEDURE requiresUnpackProc (s: node) : BOOLEAN ;
10461 BEGIN
10462 assert (isAssignment (s)) ;
10463 RETURN isProcedure (s^.assignmentF.expr) OR
10464 (skipType (getType (s^.assignmentF.des)) # skipType (getType (s^.assignmentF.expr)))
10465 END requiresUnpackProc ;
10469 forceCastOpaque -
10472 PROCEDURE forceCastOpaque (p: pretty; des, expr: node; toVoidStar: BOOLEAN) ;
10473 BEGIN
10474 IF nodeUsesOpaque (expr)
10475 THEN
10476 flushOpaque (p, expr, getNodeOpaqueVoidStar (des))
10477 ELSE
10478 forceReintCastOpaque (p, des, expr, toVoidStar)
10480 END forceCastOpaque ;
10484 forceReintCastOpaque -
10487 PROCEDURE forceReintCastOpaque (p: pretty; des, expr: node; toVoidStar: BOOLEAN) ;
10489 type: node ;
10490 BEGIN
10491 type := getType (des) ;
10492 IF toVoidStar
10493 THEN
10494 (* next is true cast to void * opaque type. *)
10495 outText (p, 'static_cast<') ;
10496 doTypeNameC (p, type) ;
10497 noSpace (p) ;
10498 outText (p, '> (') ;
10499 doExprC (p, expr) ;
10500 outText (p, ')')
10501 ELSE
10502 (* next is false cast to __opaque opaque type. *)
10503 outText (p, 'static_cast<') ;
10504 doTypeNameC (p, type) ;
10505 outText (p, '__opaque') ;
10506 noSpace (p) ;
10507 outText (p, '> (') ;
10508 doExprC (p, expr) ;
10509 outText (p, ')') ;
10511 END forceReintCastOpaque ;
10515 doUnConstCastUnbounded - if node n type is an unbounded array then
10516 use const_cast to remove the const parameter
10517 to allow the unbounded array to be modified.
10520 PROCEDURE doUnConstCastUnbounded (p: pretty; n: node) ;
10522 type, v: node ;
10523 BEGIN
10524 IF isArrayRef (n)
10525 THEN
10526 IF isVar (n^.arrayrefF.array)
10527 THEN
10528 v := n^.arrayrefF.array ;
10529 IF (v^.varF.isParameter OR v^.varF.isVarParameter) AND
10530 isUnbounded (getType (v))
10531 THEN
10532 type := getType (v) ;
10533 outText (p, " /* const_cast<") ;
10534 doTypeNameC (p, type) ;
10535 outText (p, "> is needed */ ") ;
10539 END doUnConstCastUnbounded ;
10543 doAssignmentC -
10546 PROCEDURE doAssignmentC (p: pretty; s: node) ;
10547 BEGIN
10548 assert (isAssignment (s)) ;
10549 doCommentC (p, s^.assignmentF.assignComment.body) ;
10550 IF debugOpaque
10551 THEN
10552 outText (p, " /* des: */ ") ;
10553 dumpOpaqueState (s^.assignmentF.des) ;
10554 outText (p, " /* expr: */ ") ;
10555 dumpOpaqueState (s^.assignmentF.expr)
10556 END ;
10557 s^.assignmentF.des := doExprCup (p, s^.assignmentF.des,
10558 requiresUnpackProc (s), TRUE) ;
10559 IF debugOpaque
10560 THEN
10561 outText (p, "\n /* after doExprCup des: */ ") ;
10562 dumpOpaqueState (s^.assignmentF.des) ;
10563 outText (p, "\n")
10564 END ;
10565 setNeedSpace (p) ;
10566 outText (p, "=") ;
10567 setNeedSpace (p) ;
10568 IF nodeUsesOpaque (s^.assignmentF.des)
10569 THEN
10570 forceCastOpaque (p, s^.assignmentF.des, s^.assignmentF.expr,
10571 getNodeOpaqueVoidStar (s^.assignmentF.des))
10572 ELSE
10573 IF debugOpaque
10574 THEN
10575 outText (p, " /* no opaque des seen */ ")
10576 END ;
10577 doExprCastC (p, s^.assignmentF.expr, getType (s^.assignmentF.des))
10578 END ;
10579 outText (p, ";") ;
10580 doAfterCommentC (p, s^.assignmentF.assignComment.after)
10581 END doAssignmentC ;
10585 containsStatement -
10588 PROCEDURE containsStatement (s: node) : BOOLEAN ;
10589 BEGIN
10590 RETURN (s # NIL) AND isStatementSequence (s) AND (NOT isStatementSequenceEmpty (s))
10591 END containsStatement ;
10595 doCompoundStmt -
10598 PROCEDURE doCompoundStmt (p: pretty; s: node) ;
10599 BEGIN
10600 IF (s = NIL) OR (isStatementSequence (s) AND isStatementSequenceEmpty (s))
10601 THEN
10602 p := pushPretty (p) ;
10603 setindent (p, getindent (p) + indentationC) ;
10604 outText (p, "{} /* empty. */\n") ;
10605 p := popPretty (p)
10606 ELSIF isStatementSequence (s) AND isSingleStatement (s) AND (NOT forceCompoundStatement)
10607 THEN
10608 p := pushPretty (p) ;
10609 setindent (p, getindent (p) + indentationC) ;
10610 doStatementSequenceC (p, s) ;
10611 p := popPretty (p)
10612 ELSE
10613 p := pushPretty (p) ;
10614 setindent (p, getindent (p) + indentationC) ;
10615 outText (p, "{\n") ;
10616 p := pushPretty (p) ;
10617 setindent (p, getindent (p) + indentationC) ;
10618 doStatementSequenceC (p, s) ;
10619 p := popPretty (p) ;
10620 outText (p, "}\n") ;
10621 p := popPretty (p)
10623 END doCompoundStmt ;
10627 doElsifC -
10630 PROCEDURE doElsifC (p: pretty; s: node) ;
10631 BEGIN
10632 assert (isElsif (s)) ;
10633 outText (p, "else if") ;
10634 setNeedSpace (p) ;
10635 outText (p, "(") ;
10636 doExprC (p, s^.elsifF.expr) ;
10637 outText (p, ")\n") ;
10638 assert ((s^.elsifF.else = NIL) OR (s^.elsifF.elsif = NIL)) ;
10639 IF forceCompoundStatement OR
10640 (hasIfAndNoElse (s^.elsifF.then) AND
10641 ((s^.elsifF.else # NIL) OR (s^.elsifF.elsif # NIL)))
10642 THEN
10643 (* avoid dangling else. *)
10644 p := pushPretty (p) ;
10645 setindent (p, getindent (p) + indentationC) ;
10646 outText (p, "{\n") ;
10647 p := pushPretty (p) ;
10648 setindent (p, getindent (p) + indentationC) ;
10649 outText (p, "/* avoid dangling else. */\n") ;
10650 doStatementSequenceC (p, s^.elsifF.then) ;
10651 p := popPretty (p) ;
10652 outText (p, "}\n") ;
10653 p := popPretty (p)
10654 ELSE
10655 doCompoundStmt (p, s^.elsifF.then)
10656 END ;
10657 IF containsStatement (s^.elsifF.else)
10658 THEN
10659 outText (p, "else\n") ;
10660 IF forceCompoundStatement
10661 THEN
10662 (* avoid dangling else. *)
10663 p := pushPretty (p) ;
10664 setindent (p, getindent (p) + indentationC) ;
10665 outText (p, "{\n") ;
10666 p := pushPretty (p) ;
10667 setindent (p, getindent (p) + indentationC) ;
10668 outText (p, "/* avoid dangling else. */\n") ;
10669 doStatementSequenceC (p, s^.elsifF.else) ;
10670 p := popPretty (p) ;
10671 outText (p, "}\n") ;
10672 p := popPretty (p)
10673 ELSE
10674 doCompoundStmt (p, s^.elsifF.else)
10676 ELSIF (s^.elsifF.elsif#NIL) AND isElsif (s^.elsifF.elsif)
10677 THEN
10678 doElsifC (p, s^.elsifF.elsif)
10680 END doElsifC ;
10684 noIfElse -
10687 PROCEDURE noIfElse (n: node) : BOOLEAN ;
10688 BEGIN
10689 RETURN (n # NIL) AND isIf (n) AND (n^.ifF.else = NIL) AND (n^.ifF.elsif = NIL)
10690 END noIfElse ;
10694 noIfElseChained - returns TRUE if, n, is an IF statement which
10695 has no associated ELSE statement. An IF with an
10696 ELSIF is also checked for no ELSE and will result
10697 in a return value of TRUE.
10700 PROCEDURE noIfElseChained (n: node) : BOOLEAN ;
10702 e: node ;
10703 BEGIN
10704 IF n # NIL
10705 THEN
10706 IF isIf (n)
10707 THEN
10708 IF n^.ifF.else # NIL
10709 THEN
10710 (* we do have an else, continue to check this statement. *)
10711 RETURN hasIfAndNoElse (n^.ifF.else)
10712 ELSIF n^.ifF.elsif = NIL
10713 THEN
10714 (* neither else or elsif. *)
10715 RETURN TRUE
10716 ELSE
10717 (* test elsif for lack of else. *)
10718 e := n^.ifF.elsif ;
10719 assert (isElsif (e)) ;
10720 RETURN noIfElseChained (e)
10722 ELSIF isElsif (n)
10723 THEN
10724 IF n^.elsifF.else # NIL
10725 THEN
10726 (* we do have an else, continue to check this statement. *)
10727 RETURN hasIfAndNoElse (n^.elsifF.else)
10728 ELSIF n^.elsifF.elsif = NIL
10729 THEN
10730 (* neither else or elsif. *)
10731 RETURN TRUE
10732 ELSE
10733 (* test elsif for lack of else. *)
10734 e := n^.elsifF.elsif ;
10735 assert (isElsif (e)) ;
10736 RETURN noIfElseChained (e)
10739 END ;
10740 RETURN FALSE
10741 END noIfElseChained ;
10745 hasIfElse -
10748 PROCEDURE hasIfElse (n: node) : BOOLEAN ;
10749 BEGIN
10750 IF n # NIL
10751 THEN
10752 IF isStatementSequence (n)
10753 THEN
10754 IF isStatementSequenceEmpty (n)
10755 THEN
10756 RETURN FALSE
10757 ELSIF isSingleStatement (n)
10758 THEN
10759 n := GetIndice (n^.stmtF.statements, 1) ;
10760 RETURN isIfElse (n)
10763 END ;
10764 RETURN FALSE
10765 END hasIfElse ;
10769 isIfElse -
10772 PROCEDURE isIfElse (n: node) : BOOLEAN ;
10773 BEGIN
10774 RETURN (n # NIL) AND isIf (n) AND ((n^.ifF.else # NIL) OR (n^.ifF.elsif # NIL))
10775 END isIfElse ;
10779 hasIfAndNoElse - returns TRUE if statement, n, is a single statement
10780 which is an IF and it has no else statement.
10783 PROCEDURE hasIfAndNoElse (n: node) : BOOLEAN ;
10784 BEGIN
10785 IF n # NIL
10786 THEN
10787 IF isStatementSequence (n)
10788 THEN
10789 IF isStatementSequenceEmpty (n)
10790 THEN
10791 RETURN FALSE
10792 ELSIF isSingleStatement (n)
10793 THEN
10794 n := GetIndice (n^.stmtF.statements, 1) ;
10795 RETURN hasIfAndNoElse (n)
10796 ELSE
10797 n := GetIndice (n^.stmtF.statements, HighIndice (n^.stmtF.statements)) ;
10798 RETURN hasIfAndNoElse (n)
10800 ELSIF isElsif (n) OR isIf (n)
10801 THEN
10802 RETURN noIfElseChained (n)
10804 END ;
10805 RETURN FALSE
10806 END hasIfAndNoElse ;
10810 doIfC - issue an if statement and also place in an after comment if one exists.
10811 The if statement might contain an else or elsif which are also handled.
10814 PROCEDURE doIfC (p: pretty; s: node) ;
10815 BEGIN
10816 assert (isIf (s)) ;
10817 doCommentC (p, s^.ifF.ifComment.body) ;
10818 outText (p, "if") ;
10819 setNeedSpace (p) ;
10820 outText (p, "(") ;
10821 doExprC (p, s^.ifF.expr) ;
10822 outText (p, ")") ;
10823 doAfterCommentC (p, s^.ifF.ifComment.after) ;
10824 IF hasIfAndNoElse (s^.ifF.then) AND
10825 ((s^.ifF.else # NIL) OR (s^.ifF.elsif # NIL))
10826 THEN
10827 (* avoid dangling else. *)
10828 p := pushPretty (p) ;
10829 setindent (p, getindent (p) + indentationC) ;
10830 outText (p, "{\n") ;
10831 p := pushPretty (p) ;
10832 setindent (p, getindent (p) + indentationC) ;
10833 outText (p, "/* avoid dangling else. */\n") ;
10834 doStatementSequenceC (p, s^.ifF.then) ;
10835 p := popPretty (p) ;
10836 outText (p, "}\n") ;
10837 p := popPretty (p)
10838 ELSIF noIfElse (s) AND hasIfElse (s^.ifF.then)
10839 THEN
10840 (* gcc does not like legal non dangling else, as it is poor style.
10841 So we will avoid getting a warning. *)
10842 p := pushPretty (p) ;
10843 setindent (p, getindent (p) + indentationC) ;
10844 outText (p, "{\n") ;
10845 p := pushPretty (p) ;
10846 setindent (p, getindent (p) + indentationC) ;
10847 outText (p, "/* avoid gcc warning by using compound statement even if not strictly necessary. */\n") ;
10848 doStatementSequenceC (p, s^.ifF.then) ;
10849 p := popPretty (p) ;
10850 outText (p, "}\n") ;
10851 p := popPretty (p)
10852 ELSE
10853 doCompoundStmt (p, s^.ifF.then)
10854 END ;
10855 assert ((s^.ifF.else = NIL) OR (s^.ifF.elsif = NIL)) ;
10856 IF containsStatement (s^.ifF.else)
10857 THEN
10858 doCommentC (p, s^.ifF.elseComment.body) ;
10859 outText (p, "else") ;
10860 doAfterCommentC (p, s^.ifF.elseComment.after) ;
10861 doCompoundStmt (p, s^.ifF.else)
10862 ELSIF (s^.ifF.elsif#NIL) AND isElsif (s^.ifF.elsif)
10863 THEN
10864 doCommentC (p, s^.ifF.elseComment.body) ;
10865 doCommentC (p, s^.ifF.elseComment.after) ;
10866 doElsifC (p, s^.ifF.elsif)
10867 END ;
10868 doCommentC (p, s^.ifF.endComment.after) ;
10869 doCommentC (p, s^.ifF.endComment.body)
10870 END doIfC ;
10874 doForIncCP -
10877 PROCEDURE doForIncCP (p: pretty; s: node) ;
10879 t: node ;
10880 BEGIN
10881 assert (isFor (s)) ;
10882 t := skipType (getType (s^.forF.des)) ;
10883 IF isEnumeration (t)
10884 THEN
10885 IF s^.forF.increment = NIL
10886 THEN
10887 doExprC (p, s^.forF.des) ;
10888 outText (p, "= static_cast<") ;
10889 doTypeNameC (p, getType (s^.forF.des)) ;
10890 noSpace (p) ;
10891 outText (p, ">(static_cast<int>(") ;
10892 doExprC (p, s^.forF.des) ;
10893 outText (p, "+1))")
10894 ELSE
10895 doExprC (p, s^.forF.des) ;
10896 outText (p, "= static_cast<") ;
10897 doTypeNameC (p, getType (s^.forF.des)) ;
10898 noSpace (p) ;
10899 outText (p, ">(static_cast<int>(") ;
10900 doExprC (p, s^.forF.des) ;
10901 outText (p, "+") ;
10902 doExprC (p, s^.forF.increment) ;
10903 outText (p, "))")
10905 ELSE
10906 doForIncC (p, s)
10908 END doForIncCP ;
10912 doForIncC -
10915 PROCEDURE doForIncC (p: pretty; s: node) ;
10916 BEGIN
10917 IF s^.forF.increment = NIL
10918 THEN
10919 doExprC (p, s^.forF.des) ;
10920 outText (p, "++")
10921 ELSE
10922 doExprC (p, s^.forF.des) ;
10923 outText (p, "=") ;
10924 doExprC (p, s^.forF.des) ;
10925 outText (p, "+") ;
10926 doExprC (p, s^.forF.increment)
10928 END doForIncC ;
10932 doForInc -
10935 PROCEDURE doForInc (p: pretty; s: node) ;
10936 BEGIN
10937 IF lang = ansiCP
10938 THEN
10939 doForIncCP (p, s)
10940 ELSE
10941 doForIncC (p, s)
10943 END doForInc ;
10947 doForC -
10950 PROCEDURE doForC (p: pretty; s: node) ;
10951 BEGIN
10952 assert (isFor (s)) ;
10953 outText (p, "for (") ;
10954 doExprC (p, s^.forF.des) ;
10955 outText (p, "=") ;
10956 doExprC (p, s^.forF.start) ;
10957 outText (p, ";") ;
10958 setNeedSpace (p) ;
10959 doExprC (p, s^.forF.des) ;
10960 outText (p, "<=") ;
10961 doExprC (p, s^.forF.end) ;
10962 outText (p, ";") ;
10963 setNeedSpace (p) ;
10964 doForInc (p, s) ;
10965 outText (p, ")\n") ;
10966 doCompoundStmt (p, s^.forF.statements)
10967 END doForC ;
10971 doRepeatC -
10974 PROCEDURE doRepeatC (p: pretty; s: node) ;
10975 BEGIN
10976 assert (isRepeat (s)) ;
10977 doCommentC (p, s^.repeatF.repeatComment.body) ;
10978 outText (p, "do {") ;
10979 doAfterCommentC (p, s^.repeatF.repeatComment.after) ;
10980 p := pushPretty (p) ;
10981 setindent (p, getindent (p) + indentationC) ;
10982 doStatementSequenceC (p, s^.repeatF.statements) ;
10983 doCommentC (p, s^.repeatF.untilComment.body) ;
10984 p := popPretty (p) ;
10985 outText (p, "} while (! (") ;
10986 doExprC (p, s^.repeatF.expr) ;
10987 outText (p, "));") ;
10988 doAfterCommentC (p, s^.repeatF.untilComment.after)
10989 END doRepeatC ;
10993 doWhileC -
10996 PROCEDURE doWhileC (p: pretty; s: node) ;
10997 BEGIN
10998 assert (isWhile (s)) ;
10999 doCommentC (p, s^.whileF.doComment.body) ;
11000 outText (p, "while (") ;
11001 doExprC (p, s^.whileF.expr) ;
11002 outText (p, ")") ;
11003 doAfterCommentC (p, s^.whileF.doComment.after) ;
11004 doCompoundStmt (p, s^.whileF.statements) ;
11005 doCommentC (p, s^.whileF.endComment.body) ;
11006 doCommentC (p, s^.whileF.endComment.after)
11007 END doWhileC ;
11011 doFuncHighC -
11014 PROCEDURE doFuncHighC (p: pretty; a: node) ;
11016 s, n: node ;
11017 BEGIN
11018 IF isLiteral (a) AND (getType (a) = charN)
11019 THEN
11020 outCard (p, 0)
11021 ELSIF isString (a)
11022 THEN
11023 outCard (p, a^.stringF.length-2)
11024 ELSIF isConst (a) AND isString (a^.constF.value)
11025 THEN
11026 doFuncHighC (p, a^.constF.value)
11027 ELSIF isUnbounded (getType (a))
11028 THEN
11029 outText (p, '_') ;
11030 outTextN (p, getSymName (a)) ;
11031 outText (p, '_high')
11032 ELSIF isArray (skipType (getType (a)))
11033 THEN
11034 n := skipType (getType (a)) ;
11035 s := n^.arrayF.subr ;
11036 IF isZero (getMin (s))
11037 THEN
11038 doExprC (p, getMax (s))
11039 ELSE
11040 outText (p, '(') ;
11041 doExprC (p, getMax (s)) ;
11042 doSubtractC (p, getMin (s)) ;
11043 outText (p, ')')
11045 ELSE
11046 (* output sizeof (a) in bytes for the high. *)
11047 outText (p, '(sizeof') ;
11048 setNeedSpace (p) ;
11049 outText (p, '(') ;
11050 doExprC (p, a) ;
11051 outText (p, ')-1)')
11053 END doFuncHighC ;
11057 doMultiplyBySize -
11060 PROCEDURE doMultiplyBySize (p: pretty; a: node) ;
11061 BEGIN
11062 IF (a # charN) AND (a # byteN) AND (a # locN)
11063 THEN
11064 setNeedSpace (p) ;
11065 outText (p, '* sizeof (') ;
11066 doTypeNameC (p, a) ;
11067 noSpace (p) ;
11068 outText (p, ')')
11070 END doMultiplyBySize ;
11074 doTotype -
11077 PROCEDURE doTotype (p: pretty; a, t: node) ;
11078 BEGIN
11079 IF (NOT isString (a)) AND (NOT isLiteral (a))
11080 THEN
11081 IF isVar (a)
11082 THEN
11083 IF (a^.varF.isParameter OR a^.varF.isVarParameter) AND
11084 isUnbounded (getType (a)) AND (skipType (getType (getType (a))) = skipType (getType (t)))
11085 THEN
11086 (* do not multiply by size as the existing high value is correct. *)
11087 RETURN
11088 END ;
11089 a := getType (a) ;
11090 IF isArray (a)
11091 THEN
11092 doMultiplyBySize (p, skipType (getType (a)))
11095 END ;
11096 IF t = wordN
11097 THEN
11098 setNeedSpace (p) ;
11099 outText (p, '/ sizeof (') ;
11100 doTypeNameC (p, wordN) ;
11101 noSpace (p) ;
11102 outText (p, ')')
11104 END doTotype ;
11108 doFuncUnbounded -
11111 PROCEDURE doFuncUnbounded (p: pretty; actual, formalParam, formal, func: node) ;
11113 h: node ;
11114 s: String ;
11115 BEGIN
11116 assert (isUnbounded (formal)) ;
11117 outText (p, '(') ;
11118 IF (lang = ansiCP) AND isParam (formalParam)
11119 THEN
11120 outText (p, "const") ;
11121 setNeedSpace (p)
11122 END ;
11123 doTypeC (p, getType (formal), formal) ;
11124 setNeedSpace (p) ;
11125 outText (p, '*)') ;
11126 setNeedSpace (p) ;
11127 IF isLiteral (actual) AND (getType (actual) = charN)
11128 THEN
11129 outText (p, '"\0') ;
11130 s := InitStringCharStar (keyToCharStar (actual^.literalF.name)) ;
11131 s := DynamicStrings.Slice (DynamicStrings.Mark (s), 0, -1) ;
11132 outTextS (p, s) ;
11133 outText (p, '"') ;
11134 s := KillString (s)
11135 ELSIF isString (actual)
11136 THEN
11137 outCstring (p, actual, TRUE)
11138 ELSIF isConst (actual)
11139 THEN
11140 actual := resolveString (actual) ;
11141 assert (isString (actual)) ;
11142 outCstring (p, actual, TRUE)
11143 ELSIF isFuncCall (actual)
11144 THEN
11145 IF getExprType (actual) = NIL
11146 THEN
11147 metaError3 ('there is no return type to the procedure function {%3ad} which is being passed as the parameter {%1ad} to {%2ad}', formal, func, actual)
11148 ELSE
11149 outText (p, '&') ;
11150 doExprC (p, actual)
11152 ELSIF isUnbounded (getType (actual))
11153 THEN
11154 doFQNameC (p, actual)
11155 (* doExprC (p, actual). *)
11156 ELSE
11157 outText (p, '&') ;
11158 doExprC (p, actual) ;
11159 IF isArray (skipType (getType (actual)))
11160 THEN
11161 outText (p, '.array[0]')
11163 END ;
11164 IF NOT (enableDefForCStrings AND isDefForC (getScope (func)))
11165 THEN
11166 outText (p, ',') ;
11167 setNeedSpace (p) ;
11168 doFuncHighC (p, actual) ;
11169 doTotype (p, actual, formal)
11171 END doFuncUnbounded ;
11175 doProcedureParamC -
11178 PROCEDURE doProcedureParamC (p: pretty; actual, formal: node) ;
11179 BEGIN
11180 IF isForC (formal)
11181 THEN
11182 outText (p, '(') ;
11183 doFQNameC (p, getType (formal)) ;
11184 outText (p, "_C") ;
11185 outText (p, ')') ;
11186 setNeedSpace (p) ;
11187 doExprC (p, actual)
11188 ELSE
11189 outText (p, '(') ;
11190 doTypeNameC (p, getType (formal)) ;
11191 outText (p, ')') ;
11192 setNeedSpace (p) ;
11193 outText (p, '{') ;
11194 outText (p, '(') ;
11195 doFQNameC (p, getType (formal)) ;
11196 outText (p, '_t)') ;
11197 setNeedSpace (p) ;
11198 doExprC (p, actual) ;
11199 outText (p, '}')
11201 END doProcedureParamC ;
11205 doAdrExprC -
11208 PROCEDURE doAdrExprC (p: pretty; n: node) ;
11209 BEGIN
11210 IF isDeref (n)
11211 THEN
11212 (* No point in issuing & ( * n ). *)
11213 doExprC (p, n^.unaryF.arg)
11214 ELSIF isVar (n) AND n^.varF.isVarParameter
11215 THEN
11216 (* No point in issuing & ( * n ). *)
11217 doFQNameC (p, n)
11218 ELSE
11219 outText (p, '&') ;
11220 doExprC (p, n)
11222 END doAdrExprC ;
11226 typePair -
11229 PROCEDURE typePair (a, b, x, y: node) : BOOLEAN ;
11230 BEGIN
11231 RETURN ((a = x) AND (b = y)) OR ((a = y) AND (b = x))
11232 END typePair ;
11236 needsCast - return TRUE if the actual type parameter needs to be cast to
11237 the formal type.
11240 PROCEDURE needsCast (at, ft: node) : BOOLEAN ;
11241 BEGIN
11242 at := skipType (at) ;
11243 ft := skipType (ft) ;
11244 IF (at = nilN) OR (at^.kind = nil) OR
11245 (at = ft) OR
11246 typePair (at, ft, cardinalN, wordN) OR
11247 typePair (at, ft, cardinalN, ztypeN) OR
11248 typePair (at, ft, integerN, ztypeN) OR
11249 typePair (at, ft, longcardN, ztypeN) OR
11250 typePair (at, ft, shortcardN, ztypeN) OR
11251 typePair (at, ft, longintN, ztypeN) OR
11252 typePair (at, ft, shortintN, ztypeN) OR
11253 typePair (at, ft, realN, rtypeN) OR
11254 typePair (at, ft, longrealN, rtypeN) OR
11255 typePair (at, ft, shortrealN, rtypeN)
11256 THEN
11257 RETURN FALSE
11258 ELSE
11259 RETURN TRUE
11261 END needsCast ;
11265 castDestType - emit the destination type ft
11268 PROCEDURE castDestType (p: pretty; formal, ft: node) ;
11269 BEGIN
11270 doTypeNameC (p, ft) ;
11271 IF isVarParam (formal)
11272 THEN
11273 outText (p, '*')
11275 END castDestType ;
11279 identifyPointer -
11282 PROCEDURE identifyPointer (type: node) : node ;
11283 BEGIN
11284 IF isPointer (type)
11285 THEN
11286 IF skipType (getType (type)) = charN
11287 THEN
11288 RETURN charStarN
11289 ELSIF (skipType (getType (type)) = byteN) OR
11290 (skipType (getType (type)) = locN)
11291 THEN
11292 RETURN addressN
11294 END ;
11295 RETURN type
11296 END identifyPointer ;
11300 castPointer - provides a six way cast between ADDRESS (ie void * ),
11301 char * and const char *.
11304 PROCEDURE castPointer (p: pretty; actual, formal, at, ft: node) : CARDINAL ;
11306 sat, sft: node ;
11307 parenth : CARDINAL ;
11308 BEGIN
11309 parenth := 0 ;
11310 IF at # ft
11311 THEN
11312 sat := identifyPointer (skipType (at)) ;
11313 sft := identifyPointer (skipType (ft)) ;
11314 IF sat = addressN
11315 THEN
11316 IF sft = charStarN
11317 THEN
11318 outText (p, 'reinterpret_cast <') ;
11319 castDestType (p, formal, ft) ;
11320 outText (p, '>')
11321 ELSIF sft = constCharStarN
11322 THEN
11323 outText (p, 'const_cast <') ;
11324 castDestType (p, formal, ft) ;
11325 outText (p, '> (static_cast <') ;
11326 doTypeNameC (p, charStarN) ;
11327 outText (p, '>') ;
11328 INC (parenth)
11329 ELSE
11330 outText (p, 'reinterpret_cast <') ;
11331 castDestType (p, formal, ft) ;
11332 outText (p, '>')
11334 ELSIF sat = charStarN
11335 THEN
11336 IF sft = addressN
11337 THEN
11338 outText (p, 'reinterpret_cast <') ;
11339 castDestType (p, formal, ft) ;
11340 outText (p, '>')
11341 ELSIF sft = constCharStarN
11342 THEN
11343 outText (p, 'const_cast <') ;
11344 castDestType (p, formal, ft) ;
11345 outText (p, '>')
11346 ELSE
11347 outText (p, 'reinterpret_cast <') ;
11348 castDestType (p, formal, ft) ;
11349 outText (p, '>')
11351 ELSIF sat = constCharStarN
11352 THEN
11353 IF sft = addressN
11354 THEN
11355 outText (p, 'static_cast <') ;
11356 castDestType (p, formal, ft) ;
11357 outText (p, '> (const_cast <') ;
11358 doTypeNameC (p, charStarN) ;
11359 outText (p, '>') ;
11360 INC (parenth)
11361 ELSIF sft = charStarN
11362 THEN
11363 outText (p, 'const_cast <') ;
11364 castDestType (p, formal, ft) ;
11365 outText (p, '>')
11366 ELSE
11367 outText (p, 'reinterpret_cast <') ;
11368 castDestType (p, formal, ft) ;
11369 outText (p, '>')
11371 ELSE
11372 outText (p, 'reinterpret_cast <') ;
11373 castDestType (p, formal, ft) ;
11374 outText (p, '>')
11375 END ;
11376 setNeedSpace (p) ;
11377 outText (p, '(') ;
11378 INC (parenth)
11379 END ;
11380 RETURN parenth
11381 END castPointer ;
11385 checkSystemCast - checks to see if we are passing to/from
11386 a system generic type (WORD, BYTE, ADDRESS)
11387 and if so emit a cast. It returns the number of
11388 open parenthesis.
11391 PROCEDURE checkSystemCast (p: pretty; actual, formal: node) : CARDINAL ;
11393 at, ft: node ;
11394 BEGIN
11395 at := getExprType (actual) ;
11396 ft := getType (formal) ;
11397 IF needsCast (at, ft)
11398 THEN
11399 IF lang = ansiCP
11400 THEN
11401 IF isString (actual) AND isCDataType (skipType (ft))
11402 THEN
11403 (* Nothing to do. *)
11404 RETURN 0
11405 ELSIF isString (actual) AND (skipType (ft) = addressN)
11406 THEN
11407 outText (p, "const_cast<void*> (static_cast<const void*> (") ;
11408 RETURN 2
11409 ELSIF isPointer (skipType (ft)) OR (skipType (ft) = addressN) OR
11410 isCDataType (skipType (ft))
11411 THEN
11412 IF actual = nilN
11413 THEN
11414 IF isVarParam (formal)
11415 THEN
11416 metaError1 ('NIL is being passed to a VAR parameter {%1DMad}', formal)
11417 END ;
11418 (* NULL is compatible with pointers/address. *)
11419 RETURN 0
11420 ELSE
11421 RETURN castPointer (p, actual, formal, at, ft)
11423 ELSE
11424 outText (p, 'static_cast<') ;
11425 doTypeNameC (p, ft) ;
11426 IF isVarParam (formal)
11427 THEN
11428 outText (p, '*')
11429 END ;
11430 noSpace (p) ;
11431 outText (p, '> (')
11432 END ;
11433 RETURN 1
11434 ELSE
11435 outText (p, '(') ;
11436 doTypeNameC (p, ft) ;
11437 IF isVarParam (formal)
11438 THEN
11439 outText (p, '*')
11440 END ;
11441 noSpace (p) ;
11442 outText (p, ')') ;
11443 setNeedSpace (p)
11445 END ;
11446 RETURN 0
11447 END checkSystemCast ;
11451 emitN -
11454 PROCEDURE emitN (p: pretty; a: ARRAY OF CHAR; n: CARDINAL) ;
11455 BEGIN
11456 WHILE n>0 DO
11457 outText (p, a) ;
11458 DEC (n)
11460 END emitN ;
11464 isForC - return true if node n is a varparam, param or procedure
11465 which was declared inside a definition module for "C".
11468 PROCEDURE isForC (n: node) : BOOLEAN ;
11469 BEGIN
11470 IF isVarParam (n)
11471 THEN
11472 RETURN n^.varparamF.isForC
11473 ELSIF isParam (n)
11474 THEN
11475 RETURN n^.paramF.isForC
11476 ELSIF isProcedure (n)
11477 THEN
11478 RETURN n^.procedureF.isForC
11479 END ;
11480 RETURN FALSE
11481 END isForC ;
11485 isDefForCNode - return TRUE if node n was declared inside a definition module for "C".
11488 PROCEDURE isDefForCNode (n: node) : BOOLEAN ;
11490 name: Name ;
11491 BEGIN
11492 WHILE (n # NIL) AND (NOT (isImp (n) OR isDef (n) OR isModule (n))) DO
11493 n := getScope (n)
11494 END ;
11495 IF (n # NIL) AND isImp (n)
11496 THEN
11497 name := getSymName (n) ;
11498 n := lookupDef (name) ;
11499 END ;
11500 RETURN (n # NIL) AND isDef (n) AND isDefForC (n)
11501 END isDefForCNode ;
11505 doFuncVarParam - detect whether the formal uses an opaque and ensure that the address of
11506 the actual parameter is cast to the formal type.
11509 PROCEDURE doFuncVarParam (p: pretty; actual, formal: node) ;
11511 type: node ;
11512 BEGIN
11513 IF nodeUsesOpaque (formal) AND
11514 getNodeOpaqueFlushNecessary (actual, getNodeOpaqueVoidStar (formal))
11515 THEN
11516 type := getType (formal) ;
11517 outText (p, 'reinterpret_cast<') ;
11518 IF getNodeOpaqueVoidStar (formal)
11519 THEN
11520 doTypeNameC (p, type) ;
11521 setNeedSpace (p) ;
11522 outText (p, '*> (&') ;
11523 doExprC (p, actual) ;
11524 outText (p, ')') ;
11525 actual := makeOpaqueCast (actual, TRUE)
11526 ELSE
11527 doTypeNameC (p, type) ;
11528 noSpace (p) ;
11529 outText (p, '__opaque *> (&') ;
11530 doExprC (p, actual) ;
11531 outText (p, ')') ;
11532 actual := makeOpaqueCast (actual, FALSE)
11534 ELSE
11535 doAdrExprC (p, actual)
11537 END doFuncVarParam ;
11541 doFuncParamC -
11544 PROCEDURE doFuncParamC (p: pretty; actual, formal, func: node) ;
11546 ft, at: node ;
11547 lbr : CARDINAL ;
11548 BEGIN
11549 IF formal = NIL
11550 THEN
11551 doExprC (p, actual)
11552 ELSE
11553 ft := skipType (getType (formal)) ;
11554 IF isUnbounded (ft)
11555 THEN
11556 doFuncUnbounded (p, actual, formal, ft, func)
11557 ELSE
11558 IF isAProcType (ft) AND isProcedure (actual)
11559 THEN
11560 IF isVarParam (formal)
11561 THEN
11562 metaError1 ('{%1MDad} cannot be passed as a VAR parameter', actual)
11563 ELSE
11564 doProcedureParamC (p, actual, formal)
11566 ELSIF (getType (actual) # NIL) AND isProcType (skipType (getType (actual))) AND isAProcType (ft) AND isForC (formal)
11567 THEN
11568 IF isVarParam (formal)
11569 THEN
11570 metaError2 ('{%1MDad} cannot be passed as a VAR parameter to the definition for C module as the parameter requires a cast to the formal type {%2MDtad}',
11571 actual, formal)
11572 ELSE
11573 outText (p, '(') ;
11574 doFQNameC (p, getType (formal)) ;
11575 outText (p, "_C") ;
11576 outText (p, ')') ;
11577 setNeedSpace (p) ;
11578 doExprC (p, actual) ;
11579 outText (p, ".proc")
11581 ELSIF (getType (actual) # NIL) AND isProcType (skipType (getType (actual))) AND (getType (actual) # getType (formal))
11582 THEN
11583 IF isVarParam (formal)
11584 THEN
11585 metaError2 ('{%1MDad} cannot be passed as a VAR parameter as the parameter requires a cast to the formal type {%2MDtad}',
11586 actual, formal)
11587 ELSE
11588 doCastC (p, getType (formal), actual)
11590 ELSE
11591 IF isVarParam (formal)
11592 THEN
11593 lbr := checkSystemCast (p, actual, formal) ;
11594 doFuncVarParam (p, actual, formal) ;
11595 emitN (p, ")", lbr)
11596 ELSE
11597 IF nodeUsesOpaque (formal)
11598 THEN
11599 forceCastOpaque (p, formal, actual,
11600 getNodeOpaqueVoidStar (formal))
11601 ELSE
11602 lbr := checkSystemCast (p, actual, formal) ;
11603 doExprC (p, actual) ;
11604 emitN (p, ")", lbr)
11610 END doFuncParamC ;
11614 getNthParamType - return the type of parameter, i, in list, l.
11615 If the parameter is a vararg NIL is returned.
11618 PROCEDURE getNthParamType (l: Index; i: CARDINAL) : node ;
11620 p: node ;
11621 BEGIN
11622 p := getNthParam (l, i) ;
11623 IF p # NIL
11624 THEN
11625 RETURN getType (p)
11626 END ;
11627 RETURN NIL
11628 END getNthParamType ;
11632 getNthParam - return the parameter, i, in list, l.
11633 If the parameter is a vararg NIL is returned.
11636 PROCEDURE getNthParam (l: Index; i: CARDINAL) : node ;
11638 p : node ;
11639 j, k, h: CARDINAL ;
11640 BEGIN
11641 IF l # NIL
11642 THEN
11643 j := LowIndice (l) ;
11644 h := HighIndice (l) ;
11645 WHILE j <= h DO
11646 p := GetIndice (l, j) ;
11647 IF isParam (p)
11648 THEN
11649 k := identListLen (p^.paramF.namelist)
11650 ELSIF isVarParam (p)
11651 THEN
11652 k := identListLen (p^.varparamF.namelist)
11653 ELSE
11654 assert (isVarargs (p)) ;
11655 RETURN NIL
11656 END ;
11657 IF i <= k
11658 THEN
11659 RETURN p
11660 ELSE
11661 DEC (i, k) ;
11662 INC (j)
11665 END ;
11666 RETURN NIL
11667 END getNthParam ;
11671 doFuncArgsC -
11674 PROCEDURE doFuncArgsC (p: pretty; s: node; l: Index; needParen: BOOLEAN) ;
11676 actual, formal: node ;
11677 i, n : CARDINAL ;
11678 BEGIN
11679 IF needParen
11680 THEN
11681 outText (p, "(")
11682 END ;
11683 IF s^.funccallF.args # NIL
11684 THEN
11685 i := 1 ;
11686 n := expListLen (s^.funccallF.args) ;
11687 WHILE i<=n DO
11688 actual := getExpList (s^.funccallF.args, i) ;
11689 formal := getNthParam (l, i) ;
11690 doFuncParamC (p, actual, formal, s^.funccallF.function) ;
11691 IF i<n
11692 THEN
11693 outText (p, ",") ;
11694 setNeedSpace (p)
11695 END ;
11696 INC (i)
11698 END ;
11699 IF needParen
11700 THEN
11701 noSpace (p) ;
11702 outText (p, ")")
11704 END doFuncArgsC ;
11708 doProcTypeArgsC -
11711 PROCEDURE doProcTypeArgsC (p: pretty; s: node; args: Index; needParen: BOOLEAN) ;
11713 a, b: node ;
11714 i, n: CARDINAL ;
11715 BEGIN
11716 IF needParen
11717 THEN
11718 outText (p, "(")
11719 END ;
11720 IF s^.funccallF.args # NIL
11721 THEN
11722 i := 1 ;
11723 n := expListLen (s^.funccallF.args) ;
11724 WHILE i<=n DO
11725 a := getExpList (s^.funccallF.args, i) ;
11726 b := GetIndice (args, i) ;
11727 doFuncParamC (p, a, b, s^.funccallF.function) ;
11728 IF i<n
11729 THEN
11730 outText (p, ",") ;
11731 setNeedSpace (p)
11732 END ;
11733 INC (i)
11735 END ;
11736 IF needParen
11737 THEN
11738 noSpace (p) ;
11739 outText (p, ")")
11741 END doProcTypeArgsC ;
11745 doAdrArgC -
11748 PROCEDURE doAdrArgC (p: pretty; n: node) ;
11749 BEGIN
11750 IF isDeref (n)
11751 THEN
11752 (* & and * cancel each other out. *)
11753 doExprC (p, n^.unaryF.arg)
11754 ELSIF isVar (n) AND (n^.varF.isVarParameter)
11755 THEN
11756 (* & and * cancel each other out. *)
11757 outTextN (p, getSymName (n)) (* --fixme-- does the caller need to cast it? *)
11758 ELSIF isString (n) OR (isArray (getType (n)) AND isUnbounded (getType (n)))
11759 THEN
11760 IF lang = ansiCP
11761 THEN
11762 outText (p, "const_cast<void*> (static_cast<const void*>") ;
11763 outText (p, "(") ;
11764 doExprC (p, n) ;
11765 outText (p, "))")
11766 ELSE
11767 doExprC (p, n)
11769 ELSE
11770 outText (p, "&") ;
11771 doExprC (p, n)
11773 END doAdrArgC ;
11777 doAdrC -
11780 PROCEDURE doAdrC (p: pretty; n: node) ;
11781 BEGIN
11782 assert (isUnary (n)) ;
11783 doAdrArgC (p, n^.unaryF.arg)
11784 END doAdrC ;
11788 doInc -
11791 PROCEDURE doInc (p: pretty; n: node) ;
11792 BEGIN
11793 assert (isIntrinsic (n)) ;
11794 IF lang = ansiCP
11795 THEN
11796 doIncDecCP (p, n, "+")
11797 ELSE
11798 doIncDecC (p, n, "+=")
11800 END doInc ;
11804 doDec -
11807 PROCEDURE doDec (p: pretty; n: node) ;
11808 BEGIN
11809 assert (isIntrinsic (n)) ;
11810 IF lang = ansiCP
11811 THEN
11812 doIncDecCP (p, n, "-")
11813 ELSE
11814 doIncDecC (p, n, "-=")
11816 END doDec ;
11820 doIncDecC -
11823 PROCEDURE doIncDecC (p: pretty; n: node; op: ARRAY OF CHAR) ;
11824 BEGIN
11825 assert (isIntrinsic (n)) ;
11826 IF n^.intrinsicF.args # NIL
11827 THEN
11828 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11829 setNeedSpace (p) ;
11830 outText (p, op) ;
11831 setNeedSpace (p) ;
11832 IF expListLen (n^.intrinsicF.args) = 1
11833 THEN
11834 outText (p, '1')
11835 ELSE
11836 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11839 END doIncDecC ;
11843 doIncDecCP -
11846 PROCEDURE doIncDecCP (p: pretty; n: node; op: ARRAY OF CHAR) ;
11848 lhs,
11849 type: node ;
11850 BEGIN
11851 assert (isIntrinsic (n)) ;
11852 IF n^.intrinsicF.args # NIL
11853 THEN
11854 lhs := getExpList (n^.intrinsicF.args, 1) ;
11855 doExprC (p, lhs) ;
11856 setNeedSpace (p) ;
11857 type := getType (lhs) ;
11858 IF isPointer (type) OR (type = addressN)
11859 THEN
11860 (* cast to (char * ) and then back again after the arithmetic is complete. *)
11861 outText (p, "=") ;
11862 setNeedSpace (p) ;
11863 outText (p, 'reinterpret_cast<') ;
11864 doTypeNameC (p, type) ;
11865 noSpace (p) ;
11866 outText (p, '> (reinterpret_cast<char *> (') ;
11867 doExprC (p, lhs) ;
11868 noSpace (p) ;
11869 outText (p, ')') ;
11870 outText (p, op) ;
11871 IF expListLen (n^.intrinsicF.args) = 1
11872 THEN
11873 outText (p, '1')
11874 ELSE
11875 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11876 END ;
11877 outText (p, ')')
11878 ELSIF isEnumeration (skipType (type))
11879 THEN
11880 outText (p, "= static_cast<") ;
11881 doTypeNameC (p, type) ;
11882 noSpace (p) ;
11883 outText (p, ">(static_cast<int>(") ;
11884 doExprC (p, lhs) ;
11885 outText (p, ")") ;
11886 outText (p, op) ;
11887 IF expListLen (n^.intrinsicF.args) = 1
11888 THEN
11889 outText (p, '1')
11890 ELSE
11891 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11892 END ;
11893 outText (p, ")")
11894 ELSE
11895 outText (p, op) ;
11896 outText (p, "=") ;
11897 setNeedSpace (p) ;
11898 IF expListLen (n^.intrinsicF.args) = 1
11899 THEN
11900 outText (p, '1')
11901 ELSE
11902 doExprC (p, getExpList (n^.intrinsicF.args, 2))
11906 END doIncDecCP ;
11910 doInclC -
11913 PROCEDURE doInclC (p: pretty; n: node) ;
11915 lo: node ;
11916 BEGIN
11917 assert (isIntrinsic (n)) ;
11918 IF n^.intrinsicF.args # NIL
11919 THEN
11920 IF expListLen (n^.intrinsicF.args) = 2
11921 THEN
11922 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11923 lo := getSetLow (getExpList (n^.intrinsicF.args, 1)) ;
11924 setNeedSpace (p) ;
11925 outText (p, '|=') ;
11926 setNeedSpace (p) ;
11927 outText (p, '(1') ;
11928 setNeedSpace (p) ;
11929 outText (p, '<<') ;
11930 setNeedSpace (p) ;
11931 outText (p, '(') ;
11932 doExprC (p, getExpList (n^.intrinsicF.args, 2)) ;
11933 doSubtractC (p, lo) ;
11934 setNeedSpace (p) ;
11935 outText (p, '))')
11936 ELSE
11937 HALT (* metaError0 ('expecting two parameters to INCL') *)
11940 END doInclC ;
11944 doExclC -
11947 PROCEDURE doExclC (p: pretty; n: node) ;
11949 lo: node ;
11950 BEGIN
11951 assert (isIntrinsic (n)) ;
11952 IF n^.intrinsicF.args # NIL
11953 THEN
11954 IF expListLen (n^.intrinsicF.args) = 2
11955 THEN
11956 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11957 lo := getSetLow (getExpList (n^.intrinsicF.args, 1)) ;
11958 setNeedSpace (p) ;
11959 outText (p, '&=') ;
11960 setNeedSpace (p) ;
11961 outText (p, '(~(1') ;
11962 setNeedSpace (p) ;
11963 outText (p, '<<') ;
11964 setNeedSpace (p) ;
11965 outText (p, '(') ;
11966 doExprC (p, getExpList (n^.intrinsicF.args, 2)) ;
11967 doSubtractC (p, lo) ;
11968 setNeedSpace (p) ;
11969 outText (p, ')))')
11970 ELSE
11971 HALT (* metaError0 ('expecting two parameters to EXCL') *)
11974 END doExclC ;
11978 doNewC -
11981 PROCEDURE doNewC (p: pretty; n: node) ;
11983 t: node ;
11984 BEGIN
11985 assert (isIntrinsic (n)) ;
11986 IF n^.intrinsicF.args = NIL
11987 THEN
11988 HALT
11989 ELSE
11990 IF expListLen (n^.intrinsicF.args) = 1
11991 THEN
11992 keyc.useStorage ;
11993 outText (p, 'Storage_ALLOCATE') ;
11994 setNeedSpace (p) ;
11995 outText (p, '((void **)') ;
11996 setNeedSpace (p) ;
11997 outText (p, '&') ;
11998 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
11999 outText (p, ',') ;
12000 setNeedSpace (p) ;
12001 t := skipType (getType (getExpList (n^.intrinsicF.args, 1))) ;
12002 IF isPointer (t)
12003 THEN
12004 t := getType (t) ;
12005 outText (p, 'sizeof') ;
12006 setNeedSpace (p) ;
12007 outText (p, '(') ;
12008 doTypeNameC (p, t) ;
12009 noSpace (p) ;
12010 outText (p, '))')
12011 ELSE
12012 metaError1 ('expecting a pointer type variable as the argument to NEW, rather than {%1ad}', t)
12016 END doNewC ;
12020 doDisposeC -
12023 PROCEDURE doDisposeC (p: pretty; n: node) ;
12025 t: node ;
12026 BEGIN
12027 assert (isIntrinsic (n)) ;
12028 IF n^.intrinsicF.args = NIL
12029 THEN
12030 HALT
12031 ELSE
12032 IF expListLen (n^.intrinsicF.args) = 1
12033 THEN
12034 keyc.useStorage ;
12035 outText (p, 'Storage_DEALLOCATE') ;
12036 setNeedSpace (p) ;
12037 outText (p, '((void **)') ;
12038 setNeedSpace (p) ;
12039 outText (p, '&') ;
12040 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
12041 outText (p, ',') ;
12042 setNeedSpace (p) ;
12043 t := skipType (getType (getExpList (n^.intrinsicF.args, 1))) ;
12044 IF isPointer (t)
12045 THEN
12046 t := getType (t) ;
12047 outText (p, 'sizeof') ;
12048 setNeedSpace (p) ;
12049 outText (p, '(') ;
12050 doTypeNameC (p, t) ;
12051 noSpace (p) ;
12052 outText (p, '))')
12053 ELSE
12054 metaError1 ('expecting a pointer type variable as the argument to DISPOSE, rather than {%1ad}', t)
12056 ELSE
12057 HALT (* metaError0 ('expecting a single parameter to DISPOSE') *)
12060 END doDisposeC ;
12064 doCapC -
12067 PROCEDURE doCapC (p: pretty; n: node) ;
12068 BEGIN
12069 assert (isUnary (n)) ;
12070 IF n^.unaryF.arg = NIL
12071 THEN
12072 HALT (* metaError0 ('expecting a single parameter to CAP') *)
12073 ELSE
12074 keyc.useCtype ;
12075 IF getGccConfigSystem ()
12076 THEN
12077 outText (p, 'TOUPPER')
12078 ELSE
12079 outText (p, 'toupper')
12080 END ;
12081 setNeedSpace (p) ;
12082 outText (p, '(') ;
12083 doExprC (p, n^.unaryF.arg) ;
12084 outText (p, ')')
12086 END doCapC ;
12090 doLengthC -
12093 PROCEDURE doLengthC (p: pretty; n: node) ;
12094 BEGIN
12095 assert (isUnary (n)) ;
12096 IF n^.unaryF.arg = NIL
12097 THEN
12098 HALT (* metaError0 ('expecting a single parameter to LENGTH') *)
12099 ELSE
12100 keyc.useM2RTS ;
12101 outText (p, 'M2RTS_Length') ;
12102 setNeedSpace (p) ;
12103 outText (p, '(') ;
12104 doExprC (p, n^.unaryF.arg) ;
12105 outText (p, ',') ;
12106 setNeedSpace (p) ;
12107 doFuncHighC (p, n^.unaryF.arg) ;
12108 outText (p, ')')
12110 END doLengthC ;
12114 doAbsC -
12117 PROCEDURE doAbsC (p: pretty; n: node) ;
12119 t: node ;
12120 BEGIN
12121 assert (isUnary (n)) ;
12122 IF n^.unaryF.arg = NIL
12123 THEN
12124 HALT
12125 ELSE
12126 t := getExprType (n)
12127 END ;
12128 IF t = longintN
12129 THEN
12130 keyc.useLabs ;
12131 outText (p, "labs")
12132 ELSIF t = integerN
12133 THEN
12134 keyc.useAbs ;
12135 outText (p, "abs")
12136 ELSIF t = realN
12137 THEN
12138 keyc.useFabs ;
12139 outText (p, "fabs")
12140 ELSIF t = longrealN
12141 THEN
12142 keyc.useFabsl ;
12143 outText (p, "fabsl")
12144 ELSIF t = cardinalN
12145 THEN
12146 (* do nothing. *)
12147 ELSE
12148 HALT
12149 END ;
12150 setNeedSpace (p) ;
12151 outText (p, "(") ;
12152 doExprC (p, n^.unaryF.arg) ;
12153 outText (p, ")")
12154 END doAbsC ;
12158 doValC -
12161 PROCEDURE doValC (p: pretty; n: node) ;
12162 BEGIN
12163 assert (isBinary (n)) ;
12164 outText (p, '(') ;
12165 doTypeNameC (p, n^.binaryF.left) ;
12166 outText (p, ')') ;
12167 setNeedSpace (p) ;
12168 outText (p, '(') ;
12169 doExprC (p, n^.binaryF.right) ;
12170 outText (p, ')')
12171 END doValC ;
12175 doMinC -
12178 PROCEDURE doMinC (p: pretty; n: node) ;
12180 t: node ;
12181 BEGIN
12182 assert (isUnary (n)) ;
12183 t := getExprType (n^.unaryF.arg) ;
12184 doExprC (p, getMin (t)) ;
12185 END doMinC ;
12189 doMaxC -
12192 PROCEDURE doMaxC (p: pretty; n: node) ;
12194 t: node ;
12195 BEGIN
12196 assert (isUnary (n)) ;
12197 t := getExprType (n^.unaryF.arg) ;
12198 doExprC (p, getMax (t)) ;
12199 END doMaxC ;
12203 isIntrinsic - returns if, n, is an intrinsic procedure.
12204 The intrinsic functions are represented as unary and binary nodes.
12207 PROCEDURE isIntrinsic (n: node) : BOOLEAN ;
12208 BEGIN
12209 CASE n^.kind OF
12211 unreachable,
12212 throw,
12213 inc,
12214 dec,
12215 incl,
12216 excl,
12217 new,
12218 dispose,
12219 halt : RETURN TRUE
12221 ELSE
12222 RETURN FALSE
12224 END isIntrinsic ;
12228 doHalt -
12231 PROCEDURE doHalt (p: pretty; n: node) ;
12232 BEGIN
12233 assert (n^.kind = halt) ;
12234 IF (n^.intrinsicF.args = NIL) OR (expListLen (n^.intrinsicF.args) = 0)
12235 THEN
12236 outText (p, 'M2RTS_HALT') ;
12237 setNeedSpace (p) ;
12238 outText (p, '(-1)')
12239 ELSIF expListLen (n^.intrinsicF.args) = 1
12240 THEN
12241 outText (p, 'M2RTS_HALT') ;
12242 setNeedSpace (p) ;
12243 outText (p, '(') ;
12244 doExprC (p, getExpList (n^.intrinsicF.args, 1)) ;
12245 outText (p, ')')
12247 END doHalt ;
12251 doCreal - emit the appropriate creal function.
12254 PROCEDURE doCreal (p: pretty; t: node) ;
12255 BEGIN
12256 CASE t^.kind OF
12258 complex : keyc.useComplex ;
12259 outText (p, "creal") |
12260 longcomplex : keyc.useComplex ;
12261 outText (p, "creall") |
12262 shortcomplex: keyc.useComplex ;
12263 outText (p, "crealf")
12266 END doCreal ;
12270 doCimag - emit the appropriate cimag function.
12273 PROCEDURE doCimag (p: pretty; t: node) ;
12274 BEGIN
12275 CASE t^.kind OF
12277 complex : keyc.useComplex ;
12278 outText (p, "cimag") |
12279 longcomplex : keyc.useComplex ;
12280 outText (p, "cimagl") |
12281 shortcomplex: keyc.useComplex ;
12282 outText (p, "cimagf")
12285 END doCimag ;
12289 doReC -
12292 PROCEDURE doReC (p: pretty; n: node) ;
12294 t: node ;
12295 BEGIN
12296 assert (n^.kind = re) ;
12297 IF n^.unaryF.arg # NIL
12298 THEN
12299 t := getExprType (n^.unaryF.arg)
12300 ELSE
12301 HALT
12302 END ;
12303 doCreal (p, t) ;
12304 setNeedSpace (p) ;
12305 outText (p, '(') ;
12306 doExprC (p, n^.unaryF.arg) ;
12307 outText (p, ')')
12308 END doReC ;
12312 doImC -
12315 PROCEDURE doImC (p: pretty; n: node) ;
12317 t: node ;
12318 BEGIN
12319 assert (n^.kind = im) ;
12320 IF n^.unaryF.arg # NIL
12321 THEN
12322 t := getExprType (n^.unaryF.arg)
12323 ELSE
12324 HALT
12325 END ;
12326 doCimag (p, t) ;
12327 setNeedSpace (p) ;
12328 outText (p, '(') ;
12329 doExprC (p, n^.unaryF.arg) ;
12330 outText (p, ')')
12331 END doImC ;
12335 doCmplx -
12338 PROCEDURE doCmplx (p: pretty; n: node) ;
12339 BEGIN
12340 assert (isBinary (n)) ;
12341 keyc.useComplex ;
12342 setNeedSpace (p) ;
12343 outText (p, '(') ;
12344 doExprC (p, n^.binaryF.left) ;
12345 outText (p, ')') ;
12346 setNeedSpace (p) ;
12347 outText (p, '+') ;
12348 setNeedSpace (p) ;
12349 outText (p, '(') ;
12350 doExprC (p, n^.binaryF.right) ;
12351 setNeedSpace (p) ;
12352 outText (p, '*') ;
12353 setNeedSpace (p) ;
12354 outText (p, 'I') ;
12355 outText (p, ')')
12356 END doCmplx ;
12360 doIntrinsicC -
12363 PROCEDURE doIntrinsicC (p: pretty; n: node) ;
12364 BEGIN
12365 assert (isIntrinsic (n)) ;
12366 doCommentC (p, n^.intrinsicF.intrinsicComment.body) ;
12367 CASE n^.kind OF
12369 unreachable: doUnreachableC (p, n) |
12370 throw : doThrowC (p, n) |
12371 halt : doHalt (p, n) |
12372 inc : doInc (p, n) |
12373 dec : doDec (p, n) |
12374 incl : doInclC (p, n) |
12375 excl : doExclC (p, n) |
12376 new : doNewC (p, n) |
12377 dispose : doDisposeC (p, n)
12379 END ;
12380 outText (p, ";") ;
12381 doAfterCommentC (p, n^.intrinsicF.intrinsicComment.after)
12382 END doIntrinsicC ;
12386 isIntrinsicFunction - returns true if, n, is an instrinsic function.
12389 PROCEDURE isIntrinsicFunction (n: node) : BOOLEAN ;
12390 BEGIN
12391 CASE n^.kind OF
12393 val,
12394 adr,
12395 size,
12396 tsize,
12397 float,
12398 trunc,
12399 ord,
12400 chr,
12401 cap,
12402 abs,
12403 high,
12404 length,
12405 min,
12406 max,
12409 cmplx: RETURN TRUE
12411 ELSE
12412 RETURN FALSE
12414 END isIntrinsicFunction ;
12418 doSizeC -
12421 PROCEDURE doSizeC (p: pretty; n: node) ;
12422 BEGIN
12423 assert (isUnary (n)) ;
12424 outText (p, "sizeof (") ;
12425 doExprC (p, n^.unaryF.arg) ;
12426 outText (p, ")")
12427 END doSizeC ;
12431 doConvertC -
12434 PROCEDURE doConvertC (p: pretty; n: node; conversion: ARRAY OF CHAR) ;
12436 s: String ;
12437 BEGIN
12438 s := InitString (conversion) ;
12439 doConvertSC (p, n, s) ;
12440 s := KillString (s)
12441 END doConvertC ;
12445 doConvertSC -
12448 PROCEDURE doConvertSC (p: pretty; n: node; conversion: String) ;
12449 BEGIN
12450 assert (isUnary (n)) ;
12451 setNeedSpace (p) ;
12452 outText (p, "((") ;
12453 outTextS (p, conversion) ;
12454 outText (p, ")") ;
12455 setNeedSpace (p) ;
12456 outText (p, "(") ;
12457 doExprC (p, n^.unaryF.arg) ;
12458 outText (p, "))")
12459 END doConvertSC ;
12462 (* not needed?
12463 val: doValC (p, n) |
12464 adr: doAdrC (p, n) |
12465 size,
12466 tsize: doSizeC (p, n) |
12467 float: doConvertC (p, n, "(double)") |
12468 trunc: doConvertC (p, n, "(int)") |
12469 ord: doConvertC (p, n, "(unsigned int)") |
12470 chr: doConvertC (p, n, "(char)") |
12471 cap: doCapC (p, n) |
12472 abs: doAbsC (p, n) |
12473 high: doFuncHighC (p, n^.unaryF.arg, 1)) |
12474 length: doLengthC (p, n) |
12475 min: doMinC (p, n) |
12476 max: doMaxC (p, n) |
12477 throw: doThrowC (p, n) |
12478 re: doReC (p, n) |
12479 im: doImC (p, n) |
12480 cmplx: doCmplx (p, n)
12485 getFunction - return the function associate with funccall node n.
12488 PROCEDURE getFunction (n: node) : node ;
12489 BEGIN
12490 assert (isFuncCall (n)) ;
12491 CASE n^.kind OF
12493 funccall: RETURN n^.funccallF.function
12495 ELSE
12496 HALT
12498 END getFunction ;
12502 getFuncFromExpr -
12505 PROCEDURE getFuncFromExpr (n: node) : node ;
12506 BEGIN
12507 n := skipType (getType (n)) ;
12508 WHILE (n # procN) AND (NOT isProcType (n)) DO
12509 n := skipType (getType (n))
12510 END ;
12511 RETURN n
12512 END getFuncFromExpr ;
12516 doFuncExprC -
12519 PROCEDURE doFuncExprC (p: pretty; n: node) ;
12521 t: node ;
12522 BEGIN
12523 assert (isFuncCall (n)) ;
12524 IF isProcedure (n^.funccallF.function)
12525 THEN
12526 doFQDNameC (p, n^.funccallF.function, TRUE) ;
12527 setNeedSpace (p) ;
12528 doFuncArgsC (p, n, n^.funccallF.function^.procedureF.parameters, TRUE)
12529 ELSE
12530 outText (p, "(*") ;
12531 doExprC (p, n^.funccallF.function) ;
12532 outText (p, ".proc") ;
12533 outText (p, ")") ;
12534 t := getFuncFromExpr (n^.funccallF.function) ;
12535 setNeedSpace (p) ;
12536 IF t = procN
12537 THEN
12538 doProcTypeArgsC (p, n, NIL, TRUE)
12539 ELSE
12540 assert (isProcType (t)) ;
12541 doProcTypeArgsC (p, n, t^.proctypeF.parameters, TRUE)
12544 END doFuncExprC ;
12548 doFuncCallC -
12551 PROCEDURE doFuncCallC (p: pretty; n: node) ;
12552 BEGIN
12553 doCommentC (p, n^.funccallF.funccallComment.body) ;
12554 doFuncExprC (p, n) ;
12555 outText (p, ";") ;
12556 doAfterCommentC (p, n^.funccallF.funccallComment.after)
12557 END doFuncCallC ;
12561 doCaseStatementC -
12564 PROCEDURE doCaseStatementC (p: pretty; n: node; needBreak: BOOLEAN) ;
12565 BEGIN
12566 p := pushPretty (p) ;
12567 setindent (p, getindent (p) + indentationC) ;
12568 doStatementSequenceC (p, n) ;
12569 IF needBreak
12570 THEN
12571 outText (p, "break;\n")
12572 END ;
12573 p := popPretty (p)
12574 END doCaseStatementC ;
12578 doExceptionC -
12581 PROCEDURE doExceptionC (p: pretty; a: ARRAY OF CHAR; n: node) ;
12583 w: CARDINAL ;
12584 BEGIN
12585 w := getDeclaredMod (n) ;
12586 outText (p, a) ;
12587 setNeedSpace (p) ;
12588 outText (p, '("') ;
12589 outTextS (p, findFileNameFromToken (w, 0)) ;
12590 outText (p, '",') ;
12591 setNeedSpace (p) ;
12592 outCard (p, tokenToLineNo (w, 0)) ;
12593 outText (p, ',') ;
12594 setNeedSpace (p) ;
12595 outCard (p, tokenToColumnNo (w, 0)) ;
12596 outText (p, ');\n') ;
12597 outText (p, '__builtin_unreachable ();\n')
12598 END doExceptionC ;
12602 doExceptionCP -
12605 PROCEDURE doExceptionCP (p: pretty; a: ARRAY OF CHAR; n: node) ;
12607 w: CARDINAL ;
12608 BEGIN
12609 w := getDeclaredMod (n) ;
12610 outText (p, a) ;
12611 setNeedSpace (p) ;
12612 outText (p, '("') ;
12613 outTextS (p, findFileNameFromToken (w, 0)) ;
12614 outText (p, '",') ;
12615 setNeedSpace (p) ;
12616 outCard (p, tokenToLineNo (w, 0)) ;
12617 outText (p, ',') ;
12618 setNeedSpace (p) ;
12619 outCard (p, tokenToColumnNo (w, 0)) ;
12620 outText (p, ');\n') ;
12621 outText (p, '__builtin_unreachable ();\n')
12622 END doExceptionCP ;
12626 doException -
12629 PROCEDURE doException (p: pretty; a: ARRAY OF CHAR; n: node) ;
12630 BEGIN
12631 keyc.useException ;
12632 IF lang = ansiCP
12633 THEN
12634 doExceptionCP (p, a, n)
12635 ELSE
12636 doExceptionC (p, a, n)
12638 END doException ;
12642 doRangeListC -
12645 PROCEDURE doRangeListC (p: pretty; c: node) ;
12647 r : node ;
12648 i, h: CARDINAL ;
12649 BEGIN
12650 assert (isCaseList (c)) ;
12651 i := 1 ;
12652 h := HighIndice (c^.caselistF.rangePairs) ;
12653 WHILE i<=h DO
12654 r := GetIndice (c^.caselistF.rangePairs, i) ;
12655 assert ((r^.rangeF.hi = NIL) OR (r^.rangeF.lo = r^.rangeF.hi)) ;
12656 outText (p, "case") ;
12657 setNeedSpace (p) ;
12658 doExprC (p, r^.rangeF.lo) ;
12659 outText (p, ":\n") ;
12660 INC (i)
12662 END doRangeListC ;
12666 doRangeIfListC -
12669 PROCEDURE doRangeIfListC (p: pretty; e, c: node) ;
12671 r : node ;
12672 i, h: CARDINAL ;
12673 BEGIN
12674 assert (isCaseList (c)) ;
12675 i := 1 ;
12676 h := HighIndice (c^.caselistF.rangePairs) ;
12677 WHILE i<=h DO
12678 r := GetIndice (c^.caselistF.rangePairs, i) ;
12679 IF (r^.rangeF.lo # r^.rangeF.hi) AND (r^.rangeF.hi # NIL)
12680 THEN
12681 outText (p, "((") ;
12682 doExprC (p, e) ;
12683 outText (p, ")") ;
12684 setNeedSpace (p) ;
12685 outText (p, ">=") ;
12686 setNeedSpace (p) ;
12687 doExprC (p, r^.rangeF.lo) ;
12688 outText (p, ")") ;
12689 setNeedSpace (p) ;
12690 outText (p, "&&") ;
12691 setNeedSpace (p) ;
12692 outText (p, "((") ;
12693 doExprC (p, e) ;
12694 outText (p, ")") ;
12695 setNeedSpace (p) ;
12696 outText (p, "<=") ;
12697 setNeedSpace (p) ;
12698 doExprC (p, r^.rangeF.hi) ;
12699 outText (p, ")")
12700 ELSE
12701 outText (p, "((") ;
12702 doExprC (p, e) ;
12703 outText (p, ")") ;
12704 setNeedSpace (p) ;
12705 outText (p, "==") ;
12706 setNeedSpace (p) ;
12707 doExprC (p, r^.rangeF.lo) ;
12708 outText (p, ")")
12709 END ;
12710 IF i<h
12711 THEN
12712 setNeedSpace (p) ;
12713 outText (p, "||") ;
12714 setNeedSpace (p)
12715 END ;
12716 INC (i)
12718 END doRangeIfListC ;
12722 doCaseLabels -
12725 PROCEDURE doCaseLabels (p: pretty; n: node; needBreak: BOOLEAN) ;
12726 BEGIN
12727 assert (isCaseLabelList (n)) ;
12728 doRangeListC (p, n^.caselabellistF.caseList) ;
12729 p := pushPretty (p) ;
12730 setindent (p, getindent (p) + indentationC) ;
12731 doStatementSequenceC (p, n^.caselabellistF.statements) ;
12732 IF needBreak
12733 THEN
12734 outText (p, "break;\n\n")
12735 END ;
12736 p := popPretty (p)
12737 END doCaseLabels ;
12741 doCaseLabelListC -
12744 PROCEDURE doCaseLabelListC (p: pretty; n: node; haveElse: BOOLEAN) ;
12746 i, h: CARDINAL ;
12747 c : node ;
12748 BEGIN
12749 assert (isCase (n)) ;
12750 i := 1 ;
12751 h := HighIndice (n^.caseF.caseLabelList) ;
12752 WHILE i<=h DO
12753 c := GetIndice (n^.caseF.caseLabelList, i) ;
12754 doCaseLabels (p, c, (i<h) OR haveElse OR caseException) ;
12755 INC (i)
12757 END doCaseLabelListC ;
12761 doCaseIfLabels -
12764 PROCEDURE doCaseIfLabels (p: pretty; e, n: node;
12765 i, h: CARDINAL) ;
12766 BEGIN
12767 assert (isCaseLabelList (n)) ;
12768 IF i > 1
12769 THEN
12770 outText (p, "else") ;
12771 setNeedSpace (p) ;
12772 END ;
12773 outText (p, "if") ;
12774 setNeedSpace (p) ;
12775 outText (p, "(") ;
12776 doRangeIfListC (p, e, n^.caselabellistF.caseList) ;
12777 outText (p, ")\n") ;
12778 IF h = 1
12779 THEN
12780 doCompoundStmt (p, n^.caselabellistF.statements)
12781 ELSE
12782 outText (p, "{\n") ;
12783 doStatementSequenceC (p, n^.caselabellistF.statements) ;
12784 outText (p, "}\n")
12786 END doCaseIfLabels ;
12790 doCaseIfLabelListC -
12793 PROCEDURE doCaseIfLabelListC (p: pretty; n: node) ;
12795 i, h: CARDINAL ;
12796 c : node ;
12797 BEGIN
12798 assert (isCase (n)) ;
12799 i := 1 ;
12800 h := HighIndice (n^.caseF.caseLabelList) ;
12801 WHILE i<=h DO
12802 c := GetIndice (n^.caseF.caseLabelList, i) ;
12803 doCaseIfLabels (p, n^.caseF.expression, c, i, h) ;
12804 INC (i)
12806 END doCaseIfLabelListC ;
12810 doCaseElseC -
12813 PROCEDURE doCaseElseC (p: pretty; n: node) ;
12814 BEGIN
12815 assert (isCase (n)) ;
12816 IF n^.caseF.else = NIL
12817 THEN
12818 IF caseException
12819 THEN
12820 outText (p, "\ndefault:\n") ;
12821 p := pushPretty (p) ;
12822 setindent (p, getindent (p) + indentationC) ;
12823 doException (p, 'CaseException', n) ;
12824 p := popPretty (p)
12826 ELSE
12827 outText (p, "\ndefault:\n") ;
12828 doCaseStatementC (p, n^.caseF.else, TRUE)
12830 END doCaseElseC ;
12834 doCaseIfElseC -
12837 PROCEDURE doCaseIfElseC (p: pretty; n: node) ;
12838 BEGIN
12839 assert (isCase (n)) ;
12840 IF n^.caseF.else = NIL
12841 THEN
12842 IF TRUE
12843 THEN
12844 outText (p, "\n") ;
12845 outText (p, "else {\n") ;
12846 p := pushPretty (p) ;
12847 setindent (p, getindent (p) + indentationC) ;
12848 doException (p, 'CaseException', n) ;
12849 p := popPretty (p) ;
12850 outText (p, "}\n")
12852 ELSE
12853 outText (p, "\n") ;
12854 outText (p, "else {\n") ;
12855 doCaseStatementC (p, n^.caseF.else, FALSE) ;
12856 outText (p, "}\n")
12858 END doCaseIfElseC ;
12862 canUseSwitchCaseLabels - returns TRUE if all the case labels are
12863 single values and not ranges.
12866 PROCEDURE canUseSwitchCaseLabels (n: node) : BOOLEAN ;
12868 i, h: CARDINAL ;
12869 r, l: node ;
12870 BEGIN
12871 assert (isCaseLabelList (n)) ;
12872 l := n^.caselabellistF.caseList ;
12873 i := 1 ;
12874 h := HighIndice (l^.caselistF.rangePairs) ;
12875 WHILE i<=h DO
12876 r := GetIndice (l^.caselistF.rangePairs, i) ;
12877 IF (r^.rangeF.hi # NIL) AND (r^.rangeF.lo # r^.rangeF.hi)
12878 THEN
12879 RETURN FALSE
12880 END ;
12881 INC (i)
12882 END ;
12883 RETURN TRUE
12884 END canUseSwitchCaseLabels ;
12888 canUseSwitch - returns TRUE if the case statement can be implement
12889 by a switch statement. This will be TRUE if all case
12890 selectors are single values rather than ranges.
12893 PROCEDURE canUseSwitch (n: node) : BOOLEAN ;
12895 i, h: CARDINAL ;
12896 c : node ;
12897 BEGIN
12898 assert (isCase (n)) ;
12899 i := 1 ;
12900 h := HighIndice (n^.caseF.caseLabelList) ;
12901 WHILE i<=h DO
12902 c := GetIndice (n^.caseF.caseLabelList, i) ;
12903 IF NOT canUseSwitchCaseLabels (c)
12904 THEN
12905 RETURN FALSE
12906 END ;
12907 INC (i)
12908 END ;
12909 RETURN TRUE
12910 END canUseSwitch ;
12914 doCaseC -
12917 PROCEDURE doCaseC (p: pretty; n: node) ;
12919 i: CARDINAL ;
12920 BEGIN
12921 assert (isCase (n)) ;
12922 IF canUseSwitch (n)
12923 THEN
12924 i := getindent (p) ;
12925 outText (p, "switch") ;
12926 setNeedSpace (p) ;
12927 outText (p, "(") ;
12928 doExprC (p, n^.caseF.expression) ;
12929 p := pushPretty (p) ;
12930 outText (p, ")") ;
12931 setindent (p, i + indentationC) ;
12932 outText (p, "\n{\n") ;
12933 p := pushPretty (p) ;
12934 setindent (p, getindent (p) + indentationC) ;
12935 doCaseLabelListC (p, n, n^.caseF.else # NIL) ;
12936 doCaseElseC (p, n) ;
12937 p := popPretty (p) ;
12938 outText (p, "}\n") ;
12939 p := popPretty (p)
12940 ELSE
12941 doCaseIfLabelListC (p, n) ;
12942 doCaseIfElseC (p, n)
12944 END doCaseC ;
12948 doLoopC -
12951 PROCEDURE doLoopC (p: pretty; s: node) ;
12952 BEGIN
12953 assert (isLoop (s)) ;
12954 outText (p, 'for (;;)\n') ;
12955 outText (p, "{\n") ;
12956 p := pushPretty (p) ;
12957 setindent (p, getindent (p) + indentationC) ;
12958 doStatementSequenceC (p, s^.loopF.statements) ;
12959 p := popPretty (p) ;
12960 outText (p, "}\n")
12961 END doLoopC ;
12965 doExitC -
12968 PROCEDURE doExitC (p: pretty; s: node) ;
12969 BEGIN
12970 assert (isExit (s)) ;
12971 outText (p, "/* exit. */\n")
12972 END doExitC ;
12976 doStatementsC -
12979 PROCEDURE doStatementsC (p: pretty; s: node) ;
12980 BEGIN
12981 IF s = NIL
12982 THEN
12983 (* do nothing. *)
12984 ELSIF isStatementSequence (s)
12985 THEN
12986 doStatementSequenceC (p, s)
12987 ELSIF isComment (s)
12988 THEN
12989 doCommentC (p, s)
12990 ELSIF isExit (s)
12991 THEN
12992 doExitC (p, s)
12993 ELSIF isReturn (s)
12994 THEN
12995 doReturnC (p, s)
12996 ELSIF isAssignment (s)
12997 THEN
12998 doAssignmentC (p, s)
12999 ELSIF isIf (s)
13000 THEN
13001 doIfC (p, s)
13002 ELSIF isFor (s)
13003 THEN
13004 doForC (p, s)
13005 ELSIF isRepeat (s)
13006 THEN
13007 doRepeatC (p, s)
13008 ELSIF isWhile (s)
13009 THEN
13010 doWhileC (p, s)
13011 ELSIF isIntrinsic (s)
13012 THEN
13013 doIntrinsicC (p, s)
13014 ELSIF isFuncCall (s)
13015 THEN
13016 doFuncCallC (p, s)
13017 ELSIF isCase (s)
13018 THEN
13019 doCaseC (p, s)
13020 ELSIF isLoop (s)
13021 THEN
13022 doLoopC (p, s)
13023 ELSIF isExit (s)
13024 THEN
13025 doExitC (p, s)
13026 ELSE
13027 HALT (* need to handle another s^.kind. *)
13029 END doStatementsC ;
13032 PROCEDURE localstop ;
13033 END localstop ;
13037 doLocalVarC -
13040 PROCEDURE doLocalVarC (p: pretty; s: scopeT) ;
13041 BEGIN
13042 includeVarProcedure (s) ;
13043 debugLists ;
13044 topologicallyOut (doConstC, doTypesC, doVarC,
13045 outputPartial,
13046 doNone, doCompletePartialC, doNone)
13047 END doLocalVarC ;
13051 doLocalConstTypesC -
13054 PROCEDURE doLocalConstTypesC (p: pretty; s: scopeT) ;
13055 BEGIN
13056 simplifyTypes (s) ;
13057 includeConstType (s) ;
13059 doP := p ;
13061 topologicallyOut (doConstC, doTypesC, doVarC,
13062 outputPartial,
13063 doNone, doCompletePartialC, doNone) ;
13065 END doLocalConstTypesC ;
13069 addParamDone -
13072 PROCEDURE addParamDone (n: node) ;
13073 BEGIN
13074 IF isVar (n) AND n^.varF.isParameter
13075 THEN
13076 addDone (n) ;
13077 addDone (getType (n))
13079 END addParamDone ;
13083 includeParameters -
13086 PROCEDURE includeParameters (n: node) ;
13087 BEGIN
13088 assert (isProcedure (n)) ;
13089 ForeachIndiceInIndexDo (n^.procedureF.decls.variables, addParamDone)
13090 END includeParameters ;
13094 isHalt -
13097 PROCEDURE isHalt (n: node) : BOOLEAN ;
13098 BEGIN
13099 RETURN n^.kind = halt
13100 END isHalt ;
13104 isReturnOrHalt -
13107 PROCEDURE isReturnOrHalt (n: node) : BOOLEAN ;
13108 BEGIN
13109 RETURN isHalt (n) OR isReturn (n)
13110 END isReturnOrHalt ;
13114 isLastStatementReturn -
13117 PROCEDURE isLastStatementReturn (n: node) : BOOLEAN ;
13118 BEGIN
13119 RETURN isLastStatement (n, isReturnOrHalt)
13120 END isLastStatementReturn ;
13124 isLastStatementSequence -
13127 PROCEDURE isLastStatementSequence (n: node; q: isNodeF) : BOOLEAN ;
13129 h : CARDINAL ;
13130 BEGIN
13131 assert (isStatementSequence (n)) ;
13132 h := HighIndice (n^.stmtF.statements) ;
13133 IF h > 0
13134 THEN
13135 RETURN isLastStatement (GetIndice (n^.stmtF.statements, h), q)
13136 END ;
13137 RETURN FALSE
13138 END isLastStatementSequence ;
13142 isLastStatementIf -
13145 PROCEDURE isLastStatementIf (n: node; q: isNodeF) : BOOLEAN ;
13147 ret: BOOLEAN ;
13148 BEGIN
13149 assert (isIf (n)) ;
13150 ret := TRUE ;
13151 IF (n^.ifF.elsif # NIL) AND ret
13152 THEN
13153 ret := isLastStatement (n^.ifF.elsif, q)
13154 END ;
13155 IF (n^.ifF.then # NIL) AND ret
13156 THEN
13157 ret := isLastStatement (n^.ifF.then, q)
13158 END ;
13159 IF (n^.ifF.else # NIL) AND ret
13160 THEN
13161 ret := isLastStatement (n^.ifF.else, q)
13162 END ;
13163 RETURN ret
13164 END isLastStatementIf ;
13168 isLastStatementElsif -
13171 PROCEDURE isLastStatementElsif (n: node; q: isNodeF) : BOOLEAN ;
13173 ret: BOOLEAN ;
13174 BEGIN
13175 assert (isElsif (n)) ;
13176 ret := TRUE ;
13177 IF (n^.elsifF.elsif # NIL) AND ret
13178 THEN
13179 ret := isLastStatement (n^.elsifF.elsif, q)
13180 END ;
13181 IF (n^.elsifF.then # NIL) AND ret
13182 THEN
13183 ret := isLastStatement (n^.elsifF.then, q)
13184 END ;
13185 IF (n^.elsifF.else # NIL) AND ret
13186 THEN
13187 ret := isLastStatement (n^.elsifF.else, q)
13188 END ;
13189 RETURN ret
13190 END isLastStatementElsif ;
13194 isLastStatementCase -
13197 PROCEDURE isLastStatementCase (n: node; q: isNodeF) : BOOLEAN ;
13199 ret : BOOLEAN ;
13200 i, h: CARDINAL ;
13201 c : node ;
13202 BEGIN
13203 ret := TRUE ;
13204 assert (isCase (n)) ;
13205 i := 1 ;
13206 h := HighIndice (n^.caseF.caseLabelList) ;
13207 WHILE i<=h DO
13208 c := GetIndice (n^.caseF.caseLabelList, i) ;
13209 assert (isCaseLabelList (c)) ;
13210 ret := ret AND isLastStatement (c^.caselabellistF.statements, q) ;
13211 INC (i)
13212 END ;
13213 IF n^.caseF.else # NIL
13214 THEN
13215 ret := ret AND isLastStatement (n^.caseF.else, q)
13216 END ;
13217 RETURN ret
13218 END isLastStatementCase ;
13222 isLastStatement - returns TRUE if the last statement in, n, is, q.
13225 PROCEDURE isLastStatement (n: node; q: isNodeF) : BOOLEAN ;
13227 ret: BOOLEAN ;
13228 BEGIN
13229 IF n = NIL
13230 THEN
13231 RETURN FALSE
13232 ELSIF isStatementSequence (n)
13233 THEN
13234 RETURN isLastStatementSequence (n, q)
13235 ELSIF isProcedure (n)
13236 THEN
13237 assert (isProcedure (n)) ;
13238 RETURN isLastStatement (n^.procedureF.beginStatements, q)
13239 ELSIF isIf (n)
13240 THEN
13241 RETURN isLastStatementIf (n, q)
13242 ELSIF isElsif (n)
13243 THEN
13244 RETURN isLastStatementElsif (n, q)
13245 ELSIF isCase (n)
13246 THEN
13247 RETURN isLastStatementCase (n, q)
13248 ELSIF q (n)
13249 THEN
13250 RETURN TRUE
13251 END ;
13252 RETURN FALSE
13253 END isLastStatement ;
13257 doProcedureC -
13260 PROCEDURE doProcedureC (n: node) ;
13262 s: CARDINAL ;
13263 BEGIN
13264 outText (doP, "\n") ;
13265 includeParameters (n) ;
13267 keyc.enterScope (n) ;
13269 doProcedureHeadingC (n, FALSE) ;
13270 outText (doP, "\n") ;
13271 doP := outKc (doP, "{\n") ;
13272 s := getcurline (doP) ;
13273 doLocalConstTypesC (doP, n^.procedureF.decls) ;
13274 doLocalVarC (doP, n^.procedureF.decls) ;
13275 doUnboundedParamCopyC (doP, n) ;
13277 IF s # getcurline (doP)
13278 THEN
13279 outText (doP, "\n")
13280 END ;
13282 doStatementsC (doP, n^.procedureF.beginStatements) ;
13283 IF n^.procedureF.returnType # NIL
13284 THEN
13285 IF returnException
13286 THEN
13287 IF isLastStatementReturn (n)
13288 THEN
13289 outText (doP, "/* static analysis guarentees a RETURN statement will be used before here. */\n") ;
13290 outText (doP, "__builtin_unreachable ();\n") ;
13291 ELSE
13292 doException (doP, 'ReturnException', n)
13295 END ;
13296 doP := outKc (doP, "}\n") ;
13297 keyc.leaveScope (n)
13298 END doProcedureC ;
13302 outProceduresC -
13305 PROCEDURE outProceduresC (p: pretty; s: scopeT) ;
13306 BEGIN
13307 doP := p ;
13308 IF debugDecl
13309 THEN
13310 printf ("seen %d procedures\n", HighIndice (s.procedures))
13311 END ;
13313 ForeachIndiceInIndexDo (s.procedures, doProcedureC)
13314 END outProceduresC ;
13318 output -
13321 PROCEDURE output (n: node; c, t, v: nodeProcedure) ;
13322 BEGIN
13323 IF isConst (n)
13324 THEN
13325 c (n)
13326 ELSIF isVar (n)
13327 THEN
13328 v (n)
13329 ELSE
13330 t (n)
13332 END output ;
13336 allDependants -
13339 PROCEDURE allDependants (n: node) : dependentState ;
13341 l: alist ;
13342 s: dependentState ;
13343 BEGIN
13344 l := alists.initList () ;
13345 s := walkDependants (l, n) ;
13346 alists.killList (l) ;
13347 RETURN s
13348 END allDependants ;
13352 walkDependants -
13355 PROCEDURE walkDependants (l: alist; n: node) : dependentState ;
13356 BEGIN
13357 IF (n=NIL) OR alists.isItemInList (globalGroup^.doneQ, n)
13358 THEN
13359 RETURN completed
13360 ELSIF alists.isItemInList (l, n)
13361 THEN
13362 RETURN recursive
13363 ELSE
13364 alists.includeItemIntoList (l, n) ;
13365 RETURN doDependants (l, n)
13367 END walkDependants ;
13371 walkType -
13374 PROCEDURE walkType (l: alist; n: node) : dependentState ;
13376 t: node ;
13377 BEGIN
13378 t := getType (n) ;
13379 IF alists.isItemInList (globalGroup^.doneQ, t)
13380 THEN
13381 RETURN completed
13382 ELSIF alists.isItemInList (globalGroup^.partialQ, t)
13383 THEN
13384 RETURN blocked
13385 ELSE
13386 queueBlocked (t) ;
13387 RETURN blocked
13389 END walkType ;
13393 db -
13396 PROCEDURE db (a: ARRAY OF CHAR; n: node) ;
13397 BEGIN
13398 IF getDebugTopological ()
13399 THEN
13400 outText (doP, a) ;
13401 IF n#NIL
13402 THEN
13403 outTextS (doP, gen (n))
13406 END db ;
13410 dbt -
13413 PROCEDURE dbt (a: ARRAY OF CHAR) ;
13414 BEGIN
13415 IF getDebugTopological ()
13416 THEN
13417 outText (doP, a)
13419 END dbt ;
13423 dbs -
13426 PROCEDURE dbs (s: dependentState; n: node) ;
13427 BEGIN
13428 IF getDebugTopological ()
13429 THEN
13430 CASE s OF
13432 completed: outText (doP, '{completed ') |
13433 blocked : outText (doP, '{blocked ') |
13434 partial : outText (doP, '{partial ') |
13435 recursive: outText (doP, '{recursive ')
13437 END ;
13438 IF n#NIL
13439 THEN
13440 outTextS (doP, gen (n))
13441 END ;
13442 outText (doP, '}\n')
13444 END dbs ;
13448 dbq -
13451 PROCEDURE dbq (n: node) ;
13452 BEGIN
13453 IF getDebugTopological ()
13454 THEN
13455 IF alists.isItemInList (globalGroup^.todoQ, n)
13456 THEN
13457 db ('{T', n) ; outText (doP, '}')
13458 ELSIF alists.isItemInList (globalGroup^.partialQ, n)
13459 THEN
13460 db ('{P', n) ; outText (doP, '}')
13461 ELSIF alists.isItemInList (globalGroup^.doneQ, n)
13462 THEN
13463 db ('{D', n) ; outText (doP, '}')
13466 END dbq ;
13470 walkRecord -
13473 PROCEDURE walkRecord (l: alist; n: node) : dependentState ;
13475 s : dependentState ;
13477 i, t: CARDINAL ;
13478 q : node ;
13479 BEGIN
13480 i := LowIndice (n^.recordF.listOfSons) ;
13481 t := HighIndice (n^.recordF.listOfSons) ;
13482 db ('\nwalking ', n) ; o := getindent (doP) ; setindent (doP, getcurpos (doP)+3) ;
13483 dbq (n) ;
13484 WHILE i<=t DO
13485 q := GetIndice (n^.recordF.listOfSons, i) ;
13486 db ('', q) ;
13487 IF isRecordField (q) AND q^.recordfieldF.tag
13488 THEN
13489 (* do nothing as it is a tag selector processed in the varient. *)
13490 ELSE
13491 s := walkDependants (l, q) ;
13492 IF s#completed
13493 THEN
13494 dbs (s, q) ;
13495 addTodo (n) ;
13496 dbq (n) ;
13497 db ('\n', NIL) ;
13498 setindent (doP, o) ;
13499 RETURN s
13501 END ;
13502 INC (i)
13503 END ;
13504 db ('{completed', n) ; dbt ('}\n') ;
13505 setindent (doP, o) ;
13506 RETURN completed
13507 END walkRecord ;
13511 walkVarient -
13514 PROCEDURE walkVarient (l: alist; n: node) : dependentState ;
13516 s : dependentState ;
13517 i, t: CARDINAL ;
13518 q : node ;
13519 BEGIN
13520 db ('\nwalking', n) ;
13521 s := walkDependants (l, n^.varientF.tag) ;
13522 IF s#completed
13523 THEN
13524 dbs (s, n^.varientF.tag) ;
13525 dbq (n^.varientF.tag) ;
13526 db ('\n', NIL) ;
13527 RETURN s
13528 END ;
13529 i := LowIndice (n^.varientF.listOfSons) ;
13530 t := HighIndice (n^.varientF.listOfSons) ;
13531 WHILE i<=t DO
13532 q := GetIndice (n^.varientF.listOfSons, i) ;
13533 db ('', q) ;
13534 s := walkDependants (l, q) ;
13535 IF s#completed
13536 THEN
13537 dbs (s, q) ;
13538 db ('\n', NIL) ;
13539 RETURN s
13540 END ;
13541 INC (i)
13542 END ;
13543 db ('{completed', n) ; dbt ('}\n') ;
13544 RETURN completed
13545 END walkVarient ;
13549 queueBlocked -
13552 PROCEDURE queueBlocked (n: node) ;
13553 BEGIN
13554 IF NOT (alists.isItemInList (globalGroup^.doneQ, n) OR
13555 alists.isItemInList (globalGroup^.partialQ, n))
13556 THEN
13557 addTodo (n)
13559 END queueBlocked ;
13563 walkVar -
13566 PROCEDURE walkVar (l: alist; n: node) : dependentState ;
13568 t: node ;
13569 BEGIN
13570 t := getType (n) ;
13571 IF alists.isItemInList (globalGroup^.doneQ, t)
13572 THEN
13573 RETURN completed
13574 ELSE
13575 queueBlocked (t) ;
13576 RETURN blocked
13578 END walkVar ;
13582 walkEnumeration -
13585 PROCEDURE walkEnumeration (l: alist; n: node) : dependentState ;
13587 s : dependentState ;
13588 i, t: CARDINAL ;
13589 q : node ;
13590 BEGIN
13591 i := LowIndice (n^.enumerationF.listOfSons) ;
13592 t := HighIndice (n^.enumerationF.listOfSons) ;
13593 s := completed ;
13594 WHILE i<=t DO
13595 q := GetIndice (n^.enumerationF.listOfSons, i) ;
13596 s := walkDependants (l, q) ;
13597 IF s#completed
13598 THEN
13599 RETURN s
13600 END ;
13601 INC (i)
13602 END ;
13603 RETURN s
13604 END walkEnumeration ;
13608 walkSubrange -
13611 PROCEDURE walkSubrange (l: alist; n: node) : dependentState ;
13613 s: dependentState ;
13614 BEGIN
13615 WITH n^.subrangeF DO
13616 s := walkDependants (l, low) ;
13617 IF s#completed
13618 THEN
13619 RETURN s
13620 END ;
13621 s := walkDependants (l, high) ;
13622 IF s#completed
13623 THEN
13624 RETURN s
13625 END ;
13626 s := walkDependants (l, type) ;
13627 IF s#completed
13628 THEN
13629 RETURN s
13631 END ;
13632 RETURN completed
13633 END walkSubrange ;
13637 walkSubscript -
13640 PROCEDURE walkSubscript (l: alist; n: node) : dependentState ;
13642 s: dependentState ;
13643 BEGIN
13644 WITH n^.subscriptF DO
13645 s := walkDependants (l, expr) ;
13646 IF s#completed
13647 THEN
13648 RETURN s
13649 END ;
13650 s := walkDependants (l, type) ;
13651 IF s#completed
13652 THEN
13653 RETURN s
13655 END ;
13656 RETURN completed
13657 END walkSubscript ;
13661 walkPointer -
13664 PROCEDURE walkPointer (l: alist; n: node) : dependentState ;
13666 t: node ;
13667 BEGIN
13668 (* if the type of, n, is done or partial then we can output pointer. *)
13669 t := getType (n) ;
13670 IF alists.isItemInList (globalGroup^.partialQ, t) OR
13671 alists.isItemInList (globalGroup^.doneQ, t)
13672 THEN
13673 (* pointer to partial can always generate a complete type. *)
13674 RETURN completed
13675 END ;
13676 RETURN walkType (l, n)
13677 END walkPointer ;
13681 walkArray -
13684 PROCEDURE walkArray (l: alist; n: node) : dependentState ;
13686 s: dependentState ;
13687 BEGIN
13688 WITH n^.arrayF DO
13690 s := walkDependants (l, type) ;
13691 IF s#completed
13692 THEN
13693 RETURN s
13694 END ;
13696 (* an array can only be declared if its data type has already been emitted. *)
13697 IF NOT alists.isItemInList (globalGroup^.doneQ, type)
13698 THEN
13699 s := walkDependants (l, type) ;
13700 queueBlocked (type) ;
13701 IF s=completed
13702 THEN
13703 (* downgrade the completed to partial as it has not yet been written. *)
13704 RETURN partial
13705 ELSE
13706 RETURN s
13708 END ;
13709 RETURN walkDependants (l, subr)
13711 END walkArray ;
13715 walkConst -
13718 PROCEDURE walkConst (l: alist; n: node) : dependentState ;
13720 s: dependentState ;
13721 BEGIN
13722 WITH n^.constF DO
13723 s := walkDependants (l, type) ;
13724 IF s#completed
13725 THEN
13726 RETURN s
13727 END ;
13728 s := walkDependants (l, value) ;
13729 IF s#completed
13730 THEN
13731 RETURN s
13733 END ;
13734 RETURN completed
13735 END walkConst ;
13739 walkVarParam -
13742 PROCEDURE walkVarParam (l: alist; n: node) : dependentState ;
13744 t: node ;
13745 BEGIN
13746 t := getType (n) ;
13747 IF alists.isItemInList (globalGroup^.partialQ, t)
13748 THEN
13749 (* parameter can be issued from a partial. *)
13750 RETURN completed
13751 END ;
13752 RETURN walkDependants (l, t)
13753 END walkVarParam ;
13757 walkParam -
13760 PROCEDURE walkParam (l: alist; n: node) : dependentState ;
13762 t: node ;
13763 BEGIN
13764 t := getType (n) ;
13765 IF alists.isItemInList (globalGroup^.partialQ, t)
13766 THEN
13767 (* parameter can be issued from a partial. *)
13768 RETURN completed
13769 END ;
13770 RETURN walkDependants (l, t)
13771 END walkParam ;
13775 walkOptarg -
13778 PROCEDURE walkOptarg (l: alist; n: node) : dependentState ;
13780 t: node ;
13781 BEGIN
13782 t := getType (n) ;
13783 IF alists.isItemInList (globalGroup^.partialQ, t)
13784 THEN
13785 (* parameter can be issued from a partial. *)
13786 RETURN completed
13787 END ;
13788 RETURN walkDependants (l, t)
13789 END walkOptarg ;
13793 walkRecordField -
13796 PROCEDURE walkRecordField (l: alist; n: node) : dependentState ;
13798 t: node ;
13799 s: dependentState ;
13800 BEGIN
13801 assert (isRecordField (n)) ;
13802 t := getType (n) ;
13803 IF alists.isItemInList (globalGroup^.partialQ, t)
13804 THEN
13805 dbs (partial, n) ;
13806 RETURN partial
13807 ELSIF alists.isItemInList (globalGroup^.doneQ, t)
13808 THEN
13809 dbs (completed, n) ;
13810 RETURN completed
13811 ELSE
13812 addTodo (t) ;
13813 dbs (blocked, n) ;
13814 dbq (n) ;
13815 dbq (t) ;
13816 (* s := walkDependants (l, t) *)
13817 RETURN blocked
13819 END walkRecordField ;
13823 walkVarientField -
13826 PROCEDURE walkVarientField (l: alist; n: node) : dependentState ;
13828 s : dependentState ;
13829 i, t: CARDINAL ;
13830 q : node ;
13831 BEGIN
13832 i := LowIndice (n^.varientfieldF.listOfSons) ;
13833 t := HighIndice (n^.varientfieldF.listOfSons) ;
13834 s := completed ;
13835 WHILE i<=t DO
13836 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
13837 s := walkDependants (l, q) ;
13838 IF s#completed
13839 THEN
13840 dbs (s, n) ;
13841 RETURN s
13842 END ;
13843 INC (i)
13844 END ;
13845 n^.varientfieldF.simple := (t <= 1) ;
13846 dbs (s, n) ;
13847 RETURN s
13848 END walkVarientField ;
13852 walkEnumerationField -
13855 PROCEDURE walkEnumerationField (l: alist; n: node) : dependentState ;
13856 BEGIN
13857 RETURN completed
13858 END walkEnumerationField ;
13862 walkSet -
13865 PROCEDURE walkSet (l: alist; n: node) : dependentState ;
13866 BEGIN
13867 RETURN walkDependants (l, getType (n))
13868 END walkSet ;
13872 walkProcType -
13875 PROCEDURE walkProcType (l: alist; n: node) : dependentState ;
13877 s: dependentState ;
13878 t: node ;
13879 BEGIN
13880 t := getType (n) ;
13881 IF alists.isItemInList (globalGroup^.partialQ, t)
13882 THEN
13883 (* proctype can be generated from partial types. *)
13884 ELSE
13885 s := walkDependants (l, t) ;
13886 IF s#completed
13887 THEN
13888 RETURN s
13890 END ;
13891 RETURN walkParameters (l, n^.proctypeF.parameters)
13892 END walkProcType ;
13896 walkProcedure -
13899 PROCEDURE walkProcedure (l: alist; n: node) : dependentState ;
13901 s: dependentState ;
13902 BEGIN
13903 s := walkDependants (l, getType (n)) ;
13904 IF s#completed
13905 THEN
13906 RETURN s
13907 END ;
13908 RETURN walkParameters (l, n^.procedureF.parameters)
13909 END walkProcedure ;
13913 walkParameters -
13916 PROCEDURE walkParameters (l: alist; p: Index) : dependentState ;
13918 s : dependentState ;
13919 i, h: CARDINAL ;
13920 q : node ;
13921 BEGIN
13922 i := LowIndice (p) ;
13923 h := HighIndice (p) ;
13924 WHILE i<=h DO
13925 q := GetIndice (p, i) ;
13926 s := walkDependants (l, q) ;
13927 IF s#completed
13928 THEN
13929 RETURN s
13930 END ;
13931 INC (i)
13932 END ;
13933 RETURN completed
13934 END walkParameters ;
13938 walkFuncCall -
13941 PROCEDURE walkFuncCall (l: alist; n: node) : dependentState ;
13942 BEGIN
13943 RETURN completed
13944 END walkFuncCall ;
13948 walkUnary -
13951 PROCEDURE walkUnary (l: alist; n: node) : dependentState ;
13953 s: dependentState ;
13954 BEGIN
13955 WITH n^.unaryF DO
13956 s := walkDependants (l, arg) ;
13957 IF s#completed
13958 THEN
13959 RETURN s
13960 END ;
13961 RETURN walkDependants (l, resultType)
13963 END walkUnary ;
13967 walkBinary -
13970 PROCEDURE walkBinary (l: alist; n: node) : dependentState ;
13972 s: dependentState ;
13973 BEGIN
13974 WITH n^.binaryF DO
13975 s := walkDependants (l, left) ;
13976 IF s#completed
13977 THEN
13978 RETURN s
13979 END ;
13980 s := walkDependants (l, right) ;
13981 IF s#completed
13982 THEN
13983 RETURN s
13984 END ;
13985 RETURN walkDependants (l, resultType)
13987 END walkBinary ;
13991 walkComponentRef -
13994 PROCEDURE walkComponentRef (l: alist; n: node) : dependentState ;
13996 s: dependentState ;
13997 BEGIN
13998 WITH n^.componentrefF DO
13999 s := walkDependants (l, rec) ;
14000 IF s#completed
14001 THEN
14002 RETURN s
14003 END ;
14004 s := walkDependants (l, field) ;
14005 IF s#completed
14006 THEN
14007 RETURN s
14008 END ;
14009 RETURN walkDependants (l, resultType)
14011 END walkComponentRef ;
14015 walkPointerRef -
14018 PROCEDURE walkPointerRef (l: alist; n: node) : dependentState ;
14020 s: dependentState ;
14021 BEGIN
14022 WITH n^.pointerrefF DO
14023 s := walkDependants (l, ptr) ;
14024 IF s#completed
14025 THEN
14026 RETURN s
14027 END ;
14028 s := walkDependants (l, field) ;
14029 IF s#completed
14030 THEN
14031 RETURN s
14032 END ;
14033 RETURN walkDependants (l, resultType)
14035 END walkPointerRef ;
14039 walkSetValue -
14042 PROCEDURE walkSetValue (l: alist; n: node) : dependentState ;
14044 s : dependentState ;
14045 i, j: CARDINAL ;
14046 BEGIN
14047 assert (isSetValue (n)) ;
14048 WITH n^.setvalueF DO
14049 s := walkDependants (l, type) ;
14050 IF s#completed
14051 THEN
14052 RETURN s
14053 END ;
14054 i := LowIndice (values) ;
14055 j := HighIndice (values) ;
14056 WHILE i <= j DO
14057 s := walkDependants (l, GetIndice (values, i)) ;
14058 IF s#completed
14059 THEN
14060 RETURN s
14061 END ;
14062 INC (i)
14064 END ;
14065 RETURN completed
14066 END walkSetValue ;
14070 doDependants - return the dependentState depending upon whether
14071 all dependants have been declared.
14074 PROCEDURE doDependants (l: alist; n: node) : dependentState ;
14075 BEGIN
14076 WITH n^ DO
14077 CASE kind OF
14079 throw, (* --fixme-- *)
14080 varargs,
14081 address,
14082 loc,
14083 byte,
14084 word,
14085 csizet,
14086 cssizet,
14087 (* base types. *)
14088 boolean,
14089 char,
14090 cardinal,
14091 longcard,
14092 shortcard,
14093 integer,
14094 longint,
14095 shortint,
14096 real,
14097 longreal,
14098 shortreal,
14099 bitset,
14100 ztype,
14101 rtype,
14102 complex,
14103 longcomplex,
14104 shortcomplex,
14105 proc : RETURN completed |
14106 (* language features and compound type attributes. *)
14107 type : RETURN walkType (l, n) |
14108 record : RETURN walkRecord (l, n) |
14109 varient : RETURN walkVarient (l, n) |
14110 var : RETURN walkVar (l, n) |
14111 enumeration : RETURN walkEnumeration (l, n) |
14112 subrange : RETURN walkSubrange (l, n) |
14113 pointer : RETURN walkPointer (l, n) |
14114 array : RETURN walkArray (l, n) |
14115 string : RETURN completed |
14116 const : RETURN walkConst (l, n) |
14117 literal : RETURN completed |
14118 varparam : RETURN walkVarParam (l, n) |
14119 param : RETURN walkParam (l, n) |
14120 optarg : RETURN walkOptarg (l, n) |
14121 recordfield : RETURN walkRecordField (l, n) |
14122 varientfield : RETURN walkVarientField (l, n) |
14123 enumerationfield: RETURN walkEnumerationField (l, n) |
14124 set : RETURN walkSet (l, n) |
14125 proctype : RETURN walkProcType (l, n) |
14126 subscript : RETURN walkSubscript (l, n) |
14127 (* blocks. *)
14128 procedure : RETURN walkProcedure (l, n) |
14129 def,
14130 imp,
14131 module,
14132 (* statements. *)
14133 loop,
14134 while,
14135 for,
14136 repeat,
14138 elsif,
14139 assignment : HALT |
14140 (* expressions. *)
14141 componentref : RETURN walkComponentRef (l, n) |
14142 pointerref : RETURN walkPointerRef (l, n) |
14143 not,
14144 abs,
14145 min,
14146 max,
14147 chr,
14148 cap,
14149 ord,
14150 float,
14151 trunc,
14152 high : RETURN walkUnary (l, n) |
14153 cast,
14154 val,
14155 plus,
14156 sub,
14157 div,
14158 mod,
14159 mult,
14160 divide : RETURN walkBinary (l, n) |
14161 constexp,
14162 neg,
14163 adr,
14164 size,
14165 tsize,
14166 deref : RETURN walkUnary (l, n) |
14167 equal,
14168 notequal,
14169 less,
14170 greater,
14171 greequal,
14172 lessequal : RETURN walkBinary (l, n) |
14173 funccall : RETURN walkFuncCall (l, n) |
14174 setvalue : RETURN walkSetValue (l, n)
14178 END doDependants ;
14182 tryComplete - returns TRUE if node, n, can be and was completed.
14185 PROCEDURE tryComplete (n: node; c, t, v: nodeProcedure) : BOOLEAN ;
14186 BEGIN
14187 IF isEnumeration (n)
14188 THEN
14189 (* can always emit enumerated types. *)
14190 output (n, c, t, v) ;
14191 RETURN TRUE
14192 ELSIF isType (n) AND isTypeHidden (n) AND (getType (n)=NIL)
14193 THEN
14194 (* can always emit hidden types. *)
14195 outputHidden (n) ;
14196 RETURN TRUE
14197 ELSIF allDependants (n) = completed
14198 THEN
14199 output (n, c, t, v) ;
14200 RETURN TRUE
14201 END ;
14202 RETURN FALSE
14203 END tryComplete ;
14207 tryCompleteFromPartial -
14210 PROCEDURE tryCompleteFromPartial (n: node; t: nodeProcedure) : BOOLEAN ;
14211 BEGIN
14212 IF isType (n) AND (getType (n)#NIL) AND isPointer (getType (n)) AND (allDependants (getType (n)) = completed)
14213 THEN
14214 (* alists.includeItemIntoList (globalGroup^.partialQ, getType (n)) ; *)
14215 outputHiddenComplete (n) ;
14216 RETURN TRUE
14217 ELSIF allDependants (n) = completed
14218 THEN
14219 t (n) ;
14220 RETURN TRUE
14221 END ;
14222 RETURN FALSE
14223 END tryCompleteFromPartial ;
14227 visitIntrinsicFunction -
14230 PROCEDURE visitIntrinsicFunction (v: alist; n: node; p: nodeProcedure) ;
14231 BEGIN
14232 assert (isIntrinsicFunction (n)) ;
14233 CASE n^.kind OF
14235 val,
14236 cmplx: WITH n^.binaryF DO
14237 visitNode (v, left, p) ;
14238 visitNode (v, right, p) ;
14239 visitNode (v, resultType, p)
14240 END |
14241 length,
14242 adr,
14243 size,
14244 tsize,
14245 float,
14246 trunc,
14247 ord,
14248 chr,
14249 cap,
14250 abs,
14251 high,
14252 min,
14253 max,
14255 im : WITH n^.unaryF DO
14256 visitNode (v, arg, p) ;
14257 visitNode (v, resultType, p)
14261 END visitIntrinsicFunction ;
14265 visitUnary -
14268 PROCEDURE visitUnary (v: alist; n: node; p: nodeProcedure) ;
14269 BEGIN
14270 assert (isUnary (n)) ;
14271 WITH n^.unaryF DO
14272 visitNode (v, arg, p) ;
14273 visitNode (v, resultType, p)
14275 END visitUnary ;
14279 visitBinary -
14282 PROCEDURE visitBinary (v: alist; n: node; p: nodeProcedure) ;
14283 BEGIN
14284 WITH n^.binaryF DO
14285 visitNode (v, left, p) ;
14286 visitNode (v, right, p) ;
14287 visitNode (v, resultType, p)
14289 END visitBinary ;
14293 visitBoolean -
14296 PROCEDURE visitBoolean (v: alist; n: node; p: nodeProcedure) ;
14297 BEGIN
14298 visitNode (v, falseN, p) ;
14299 visitNode (v, trueN, p)
14300 END visitBoolean ;
14304 visitScope -
14307 PROCEDURE visitScope (v: alist; n: node; p: nodeProcedure) ;
14308 BEGIN
14309 IF mustVisitScope
14310 THEN
14311 visitNode (v, n, p)
14313 END visitScope ;
14317 visitType -
14320 PROCEDURE visitType (v: alist; n: node; p: nodeProcedure) ;
14321 BEGIN
14322 assert (isType (n)) ;
14323 visitNode (v, n^.typeF.type, p) ;
14324 visitScope (v, n^.typeF.scope, p)
14325 END visitType ;
14329 visitIndex -
14332 PROCEDURE visitIndex (v: alist; i: Index; p: nodeProcedure) ;
14334 j, h: CARDINAL ;
14335 BEGIN
14336 j := 1 ;
14337 h := HighIndice (i) ;
14338 WHILE j <= h DO
14339 visitNode (v, GetIndice (i, j), p) ;
14340 INC (j)
14342 END visitIndex ;
14346 visitRecord -
14349 PROCEDURE visitRecord (v: alist; n: node; p: nodeProcedure) ;
14350 BEGIN
14351 assert (isRecord (n)) ;
14352 visitScope (v, n^.recordF.scope, p) ;
14353 visitIndex (v, n^.recordF.listOfSons, p)
14354 END visitRecord ;
14358 visitVarient -
14361 PROCEDURE visitVarient (v: alist; n: node; p: nodeProcedure) ;
14362 BEGIN
14363 assert (isVarient (n)) ;
14364 visitIndex (v, n^.varientF.listOfSons, p) ;
14365 visitNode (v, n^.varientF.varient, p) ;
14366 visitNode (v, n^.varientF.tag, p) ;
14367 visitScope (v, n^.varientF.scope, p)
14368 END visitVarient ;
14372 visitVar -
14375 PROCEDURE visitVar (v: alist; n: node; p: nodeProcedure) ;
14376 BEGIN
14377 assert (isVar (n)) ;
14378 visitNode (v, n^.varF.type, p) ;
14379 visitNode (v, n^.varF.decl, p) ;
14380 visitScope (v, n^.varF.scope, p)
14381 END visitVar ;
14385 visitEnumeration -
14388 PROCEDURE visitEnumeration (v: alist; n: node; p: nodeProcedure) ;
14389 BEGIN
14390 assert (isEnumeration (n)) ;
14391 visitIndex (v, n^.enumerationF.listOfSons, p) ;
14392 visitScope (v, n^.enumerationF.scope, p)
14393 END visitEnumeration ;
14397 visitSubrange -
14400 PROCEDURE visitSubrange (v: alist; n: node; p: nodeProcedure) ;
14401 BEGIN
14402 assert (isSubrange (n)) ;
14403 visitNode (v, n^.subrangeF.low, p) ;
14404 visitNode (v, n^.subrangeF.high, p) ;
14405 visitNode (v, n^.subrangeF.type, p) ;
14406 visitScope (v, n^.subrangeF.scope, p)
14407 END visitSubrange ;
14411 visitPointer -
14414 PROCEDURE visitPointer (v: alist; n: node; p: nodeProcedure) ;
14415 BEGIN
14416 assert (isPointer (n)) ;
14417 visitNode (v, n^.pointerF.type, p) ;
14418 visitScope (v, n^.pointerF.scope, p)
14419 END visitPointer ;
14423 visitArray -
14426 PROCEDURE visitArray (v: alist; n: node; p: nodeProcedure) ;
14427 BEGIN
14428 assert (isArray (n)) ;
14429 visitNode (v, n^.arrayF.subr, p) ;
14430 visitNode (v, n^.arrayF.type, p) ;
14431 visitScope (v, n^.arrayF.scope, p)
14432 END visitArray ;
14436 visitConst -
14439 PROCEDURE visitConst (v: alist; n: node; p: nodeProcedure) ;
14440 BEGIN
14441 assert (isConst (n)) ;
14442 visitNode (v, n^.constF.type, p) ;
14443 visitNode (v, n^.constF.value, p) ;
14444 visitScope (v, n^.constF.scope, p)
14445 END visitConst ;
14449 visitVarParam -
14452 PROCEDURE visitVarParam (v: alist; n: node; p: nodeProcedure) ;
14453 BEGIN
14454 assert (isVarParam (n)) ;
14455 visitNode (v, n^.varparamF.namelist, p) ;
14456 visitNode (v, n^.varparamF.type, p) ;
14457 visitScope (v, n^.varparamF.scope, p)
14458 END visitVarParam ;
14462 visitParam -
14465 PROCEDURE visitParam (v: alist; n: node; p: nodeProcedure) ;
14466 BEGIN
14467 assert (isParam (n)) ;
14468 visitNode (v, n^.paramF.namelist, p) ;
14469 visitNode (v, n^.paramF.type, p) ;
14470 visitScope (v, n^.paramF.scope, p)
14471 END visitParam ;
14475 visitOptarg -
14478 PROCEDURE visitOptarg (v: alist; n: node; p: nodeProcedure) ;
14479 BEGIN
14480 assert (isOptarg (n)) ;
14481 visitNode (v, n^.optargF.namelist, p) ;
14482 visitNode (v, n^.optargF.type, p) ;
14483 visitNode (v, n^.optargF.init, p) ;
14484 visitScope (v, n^.optargF.scope, p)
14485 END visitOptarg ;
14489 visitRecordField -
14492 PROCEDURE visitRecordField (v: alist; n: node; p: nodeProcedure) ;
14493 BEGIN
14494 assert (isRecordField (n)) ;
14495 visitNode (v, n^.recordfieldF.type, p) ;
14496 visitNode (v, n^.recordfieldF.parent, p) ;
14497 visitNode (v, n^.recordfieldF.varient, p) ;
14498 visitScope (v, n^.recordfieldF.scope, p)
14499 END visitRecordField ;
14503 visitVarientField -
14506 PROCEDURE visitVarientField (v: alist; n: node; p: nodeProcedure) ;
14507 BEGIN
14508 assert (isVarientField (n)) ;
14509 visitNode (v, n^.varientfieldF.parent, p) ;
14510 visitNode (v, n^.varientfieldF.varient, p) ;
14511 visitIndex (v, n^.varientfieldF.listOfSons, p) ;
14512 visitScope (v, n^.varientfieldF.scope, p)
14513 END visitVarientField ;
14517 visitEnumerationField -
14520 PROCEDURE visitEnumerationField (v: alist; n: node; p: nodeProcedure) ;
14521 BEGIN
14522 assert (isEnumerationField (n)) ;
14523 visitNode (v, n^.enumerationfieldF.type, p) ;
14524 visitScope (v, n^.enumerationfieldF.scope, p)
14525 END visitEnumerationField ;
14529 visitSet -
14532 PROCEDURE visitSet (v: alist; n: node; p: nodeProcedure) ;
14533 BEGIN
14534 assert (isSet (n)) ;
14535 visitNode (v, n^.setF.type, p) ;
14536 visitScope (v, n^.setF.scope, p)
14537 END visitSet ;
14541 visitProcType -
14544 PROCEDURE visitProcType (v: alist; n: node; p: nodeProcedure) ;
14545 BEGIN
14546 assert (isProcType (n)) ;
14547 visitIndex (v, n^.proctypeF.parameters, p) ;
14548 visitNode (v, n^.proctypeF.optarg, p) ;
14549 visitNode (v, n^.proctypeF.returnType, p) ;
14550 visitScope (v, n^.proctypeF.scope, p)
14551 END visitProcType ;
14555 visitSubscript -
14558 PROCEDURE visitSubscript (v: alist; n: node; p: nodeProcedure) ;
14559 BEGIN
14561 assert (isSubscript (n)) ;
14562 visitNode (v, n^.subscriptF.type, p) ;
14563 visitNode (v, n^.subscriptF.expr, p)
14565 END visitSubscript ;
14569 visitDecls -
14572 PROCEDURE visitDecls (v: alist; s: scopeT; p: nodeProcedure) ;
14573 BEGIN
14574 visitIndex (v, s.constants, p) ;
14575 visitIndex (v, s.types, p) ;
14576 visitIndex (v, s.procedures, p) ;
14577 visitIndex (v, s.variables, p)
14578 END visitDecls ;
14582 visitProcedure -
14585 PROCEDURE visitProcedure (v: alist; n: node; p: nodeProcedure) ;
14586 BEGIN
14587 assert (isProcedure (n)) ;
14588 visitDecls (v, n^.procedureF.decls, p) ;
14589 visitScope (v, n^.procedureF.scope, p) ;
14590 visitIndex (v, n^.procedureF.parameters, p) ;
14591 visitNode (v, n^.procedureF.optarg, p) ;
14592 visitNode (v, n^.procedureF.returnType, p) ;
14593 visitNode (v, n^.procedureF.beginStatements, p)
14594 END visitProcedure ;
14598 visitDef -
14601 PROCEDURE visitDef (v: alist; n: node; p: nodeProcedure) ;
14602 BEGIN
14603 assert (isDef (n)) ;
14604 visitDecls (v, n^.defF.decls, p)
14605 END visitDef ;
14609 visitImp -
14612 PROCEDURE visitImp (v: alist; n: node; p: nodeProcedure) ;
14613 BEGIN
14614 assert (isImp (n)) ;
14615 visitDecls (v, n^.impF.decls, p) ;
14616 visitNode (v, n^.impF.beginStatements, p) ;
14617 visitNode (v, n^.impF.finallyStatements, p)
14618 (* --fixme-- do we need to visit definitionModule? *)
14619 END visitImp ;
14623 visitModule -
14626 PROCEDURE visitModule (v: alist; n: node; p: nodeProcedure) ;
14627 BEGIN
14628 assert (isModule (n)) ;
14629 visitDecls (v, n^.moduleF.decls, p) ;
14630 visitNode (v, n^.moduleF.beginStatements, p) ;
14631 visitNode (v, n^.moduleF.finallyStatements, p)
14632 END visitModule ;
14636 visitLoop -
14639 PROCEDURE visitLoop (v: alist; n: node; p: nodeProcedure) ;
14640 BEGIN
14641 assert (isLoop (n)) ;
14642 visitNode (v, n^.loopF.statements, p)
14643 END visitLoop ;
14647 visitWhile -
14650 PROCEDURE visitWhile (v: alist; n: node; p: nodeProcedure) ;
14651 BEGIN
14652 assert (isWhile (n)) ;
14653 visitNode (v, n^.whileF.expr, p) ;
14654 visitNode (v, n^.whileF.statements, p)
14655 END visitWhile ;
14659 visitRepeat -
14662 PROCEDURE visitRepeat (v: alist; n: node; p: nodeProcedure) ;
14663 BEGIN
14664 assert (isRepeat (n)) ;
14665 visitNode (v, n^.repeatF.expr, p) ;
14666 visitNode (v, n^.repeatF.statements, p)
14667 END visitRepeat ;
14671 visitCase -
14674 PROCEDURE visitCase (v: alist; n: node; p: nodeProcedure) ;
14675 BEGIN
14676 assert (isCase (n)) ;
14677 visitNode (v, n^.caseF.expression, p) ;
14678 visitIndex (v, n^.caseF.caseLabelList, p) ;
14679 visitNode (v, n^.caseF.else, p)
14680 END visitCase ;
14684 visitCaseLabelList -
14687 PROCEDURE visitCaseLabelList (v: alist; n: node; p: nodeProcedure) ;
14688 BEGIN
14689 assert (isCaseLabelList (n)) ;
14690 visitNode (v, n^.caselabellistF.caseList, p) ;
14691 visitNode (v, n^.caselabellistF.statements, p)
14692 END visitCaseLabelList ;
14696 visitCaseList -
14699 PROCEDURE visitCaseList (v: alist; n: node; p: nodeProcedure) ;
14700 BEGIN
14701 assert (isCaseList (n)) ;
14702 visitIndex (v, n^.caselistF.rangePairs, p)
14703 END visitCaseList ;
14707 visitRange -
14710 PROCEDURE visitRange (v: alist; n: node; p: nodeProcedure) ;
14711 BEGIN
14712 assert (isRange (n)) ;
14713 visitNode (v, n^.rangeF.lo, p) ;
14714 visitNode (v, n^.rangeF.hi, p)
14715 END visitRange ;
14719 visitIf -
14722 PROCEDURE visitIf (v: alist; n: node; p: nodeProcedure) ;
14723 BEGIN
14724 assert (isIf (n)) ;
14725 visitNode (v, n^.ifF.expr, p) ;
14726 visitNode (v, n^.ifF.elsif, p) ;
14727 visitNode (v, n^.ifF.then, p) ;
14728 visitNode (v, n^.ifF.else, p)
14729 END visitIf ;
14733 visitElsif -
14736 PROCEDURE visitElsif (v: alist; n: node; p: nodeProcedure) ;
14737 BEGIN
14738 assert (isElsif (n)) ;
14739 visitNode (v, n^.elsifF.expr, p) ;
14740 visitNode (v, n^.elsifF.elsif, p) ;
14741 visitNode (v, n^.elsifF.then, p) ;
14742 visitNode (v, n^.elsifF.else, p)
14743 END visitElsif ;
14747 visitFor -
14750 PROCEDURE visitFor (v: alist; n: node; p: nodeProcedure) ;
14751 BEGIN
14752 assert (isFor (n)) ;
14753 visitNode (v, n^.forF.des, p) ;
14754 visitNode (v, n^.forF.start, p) ;
14755 visitNode (v, n^.forF.end, p) ;
14756 visitNode (v, n^.forF.increment, p) ;
14757 visitNode (v, n^.forF.statements, p)
14758 END visitFor ;
14762 visitAssignment -
14765 PROCEDURE visitAssignment (v: alist; n: node; p: nodeProcedure) ;
14766 BEGIN
14767 assert (isAssignment (n)) ;
14768 visitNode (v, n^.assignmentF.des, p) ;
14769 visitNode (v, n^.assignmentF.expr, p)
14770 END visitAssignment ;
14774 visitComponentRef -
14777 PROCEDURE visitComponentRef (v: alist; n: node; p: nodeProcedure) ;
14778 BEGIN
14779 assert (isComponentRef (n)) ;
14780 visitNode (v, n^.componentrefF.rec, p) ;
14781 visitNode (v, n^.componentrefF.field, p) ;
14782 visitNode (v, n^.componentrefF.resultType, p)
14783 END visitComponentRef ;
14787 visitPointerRef -
14790 PROCEDURE visitPointerRef (v: alist; n: node; p: nodeProcedure) ;
14791 BEGIN
14792 assert (isPointerRef (n)) ;
14793 visitNode (v, n^.pointerrefF.ptr, p) ;
14794 visitNode (v, n^.pointerrefF.field, p) ;
14795 visitNode (v, n^.pointerrefF.resultType, p)
14796 END visitPointerRef ;
14800 visitArrayRef -
14803 PROCEDURE visitArrayRef (v: alist; n: node; p: nodeProcedure) ;
14804 BEGIN
14805 assert (isArrayRef (n)) ;
14806 visitNode (v, n^.arrayrefF.array, p) ;
14807 visitNode (v, n^.arrayrefF.index, p) ;
14808 visitNode (v, n^.arrayrefF.resultType, p)
14809 END visitArrayRef ;
14813 visitFunccall -
14816 PROCEDURE visitFunccall (v: alist; n: node; p: nodeProcedure) ;
14817 BEGIN
14818 assert (isFuncCall (n)) ;
14819 visitNode (v, n^.funccallF.function, p) ;
14820 visitNode (v, n^.funccallF.args, p) ;
14821 visitNode (v, n^.funccallF.type, p)
14822 END visitFunccall ;
14826 visitVarDecl -
14829 PROCEDURE visitVarDecl (v: alist; n: node; p: nodeProcedure) ;
14830 BEGIN
14831 assert (isVarDecl (n)) ;
14832 visitNode (v, n^.vardeclF.type, p) ;
14833 visitScope (v, n^.vardeclF.scope, p)
14834 END visitVarDecl ;
14838 visitExplist -
14841 PROCEDURE visitExplist (v: alist; n: node; p: nodeProcedure) ;
14842 BEGIN
14843 assert (isExpList (n)) ;
14844 visitIndex (v, n^.explistF.exp, p)
14845 END visitExplist ;
14849 visitExit -
14852 PROCEDURE visitExit (v: alist; n: node; p: nodeProcedure) ;
14853 BEGIN
14854 assert (isExit (n)) ;
14855 visitNode (v, n^.exitF.loop, p)
14856 END visitExit ;
14860 visitReturn -
14863 PROCEDURE visitReturn (v: alist; n: node; p: nodeProcedure) ;
14864 BEGIN
14865 assert (isReturn (n)) ;
14866 visitNode (v, n^.returnF.exp, p)
14867 END visitReturn ;
14871 visitStmtSeq -
14874 PROCEDURE visitStmtSeq (v: alist; n: node; p: nodeProcedure) ;
14875 BEGIN
14876 assert (isStatementSequence (n)) ;
14877 visitIndex (v, n^.stmtF.statements, p)
14878 END visitStmtSeq ;
14882 visitVarargs -
14885 PROCEDURE visitVarargs (v: alist; n: node; p: nodeProcedure) ;
14886 BEGIN
14887 assert (isVarargs (n)) ;
14888 visitScope (v, n^.varargsF.scope, p)
14889 END visitVarargs ;
14893 visitSetValue -
14896 PROCEDURE visitSetValue (v: alist; n: node; p: nodeProcedure) ;
14897 BEGIN
14898 assert (isSetValue (n)) ;
14899 visitNode (v, n^.setvalueF.type, p) ;
14900 visitIndex (v, n^.setvalueF.values, p)
14901 END visitSetValue ;
14905 visitIntrinsic -
14908 PROCEDURE visitIntrinsic (v: alist; n: node; p: nodeProcedure) ;
14909 BEGIN
14910 assert (isIntrinsic (n)) ;
14911 visitNode (v, n^.intrinsicF.args, p)
14912 END visitIntrinsic ;
14916 visitDependants - helper procedure function called from visitNode.
14917 node n has just been visited, this procedure will
14918 visit node, n, dependants.
14921 PROCEDURE visitDependants (v: alist; n: node; p: nodeProcedure) ;
14922 BEGIN
14923 assert (n # NIL) ;
14924 assert (alists.isItemInList (v, n)) ;
14925 CASE n^.kind OF
14927 explist : visitExplist (v, n, p) |
14928 funccall : visitFunccall (v, n, p) |
14929 exit : visitExit (v, n, p) |
14930 return : visitReturn (v, n, p) |
14931 stmtseq : visitStmtSeq (v, n, p) |
14932 comment : |
14933 length : visitIntrinsicFunction (v, n, p) |
14934 unreachable,
14935 throw,
14936 halt,
14937 new,
14938 dispose,
14939 inc,
14940 dec,
14941 incl,
14942 excl : visitIntrinsic (v, n, p) |
14943 boolean : visitBoolean (v, n, p) |
14944 nil,
14945 false,
14946 true : |
14947 varargs : visitVarargs (v, n, p) |
14948 address,
14949 loc,
14950 byte,
14951 word,
14952 csizet,
14953 cssizet,
14954 (* base types. *)
14955 char,
14956 cardinal,
14957 longcard,
14958 shortcard,
14959 integer,
14960 longint,
14961 shortint,
14962 real,
14963 longreal,
14964 shortreal,
14965 bitset,
14966 ztype,
14967 rtype,
14968 complex,
14969 longcomplex,
14970 shortcomplex,
14971 proc : |
14972 (* language features and compound type attributes. *)
14973 type : visitType (v, n, p) |
14974 record : visitRecord (v, n, p) |
14975 varient : visitVarient (v, n, p) |
14976 var : visitVar (v, n, p) |
14977 enumeration : visitEnumeration (v, n, p) |
14978 subrange : visitSubrange (v, n, p) |
14979 pointer : visitPointer (v, n, p) |
14980 array : visitArray (v, n, p) |
14981 string : |
14982 const : visitConst (v, n, p) |
14983 literal : |
14984 varparam : visitVarParam (v, n, p) |
14985 param : visitParam (v, n, p) |
14986 optarg : visitOptarg (v, n, p) |
14987 recordfield : visitRecordField (v, n, p) |
14988 varientfield : visitVarientField (v, n, p) |
14989 enumerationfield: visitEnumerationField (v, n, p) |
14990 set : visitSet (v, n, p) |
14991 proctype : visitProcType (v, n, p) |
14992 subscript : visitSubscript (v, n, p) |
14993 (* blocks. *)
14994 procedure : visitProcedure (v, n, p) |
14995 def : visitDef (v, n, p) |
14996 imp : visitImp (v, n, p) |
14997 module : visitModule (v, n, p) |
14998 (* statements. *)
14999 loop : visitLoop (v, n, p) |
15000 while : visitWhile (v, n, p) |
15001 for : visitFor (v, n, p) |
15002 repeat : visitRepeat (v, n, p) |
15003 case : visitCase (v, n, p) |
15004 caselabellist : visitCaseLabelList (v, n, p) |
15005 caselist : visitCaseList (v, n, p) |
15006 range : visitRange (v, n, p) |
15007 if : visitIf (v, n, p) |
15008 elsif : visitElsif (v, n, p) |
15009 assignment : visitAssignment (v, n, p) |
15010 (* expressions. *)
15011 componentref : visitComponentRef (v, n, p) |
15012 pointerref : visitPointerRef (v, n, p) |
15013 arrayref : visitArrayRef (v, n, p) |
15014 cmplx,
15015 equal,
15016 notequal,
15017 less,
15018 greater,
15019 greequal,
15020 lessequal,
15021 and,
15024 cast,
15025 val,
15026 plus,
15027 sub,
15028 div,
15029 mod,
15030 mult,
15031 divide : visitBinary (v, n, p) |
15032 re : visitUnary (v, n, p) |
15033 im : visitUnary (v, n, p) |
15034 abs : visitUnary (v, n, p) |
15035 chr : visitUnary (v, n, p) |
15036 cap : visitUnary (v, n, p) |
15037 high : visitUnary (v, n, p) |
15038 ord : visitUnary (v, n, p) |
15039 float : visitUnary (v, n, p) |
15040 trunc : visitUnary (v, n, p) |
15041 not : visitUnary (v, n, p) |
15042 neg : visitUnary (v, n, p) |
15043 adr : visitUnary (v, n, p) |
15044 size : visitUnary (v, n, p) |
15045 tsize : visitUnary (v, n, p) |
15046 min : visitUnary (v, n, p) |
15047 max : visitUnary (v, n, p) |
15048 constexp : visitUnary (v, n, p) |
15049 deref : visitUnary (v, n, p) |
15050 identlist : |
15051 vardecl : visitVarDecl (v, n, p) |
15052 setvalue : visitSetValue (v, n, p)
15055 END visitDependants ;
15059 visitNode - visits node, n, if it is not already in the alist, v.
15060 It calls p(n) if the node is unvisited.
15063 PROCEDURE visitNode (v: alist; n: node; p: nodeProcedure) ;
15064 BEGIN
15065 IF (n#NIL) AND (NOT alists.isItemInList (v, n))
15066 THEN
15067 alists.includeItemIntoList (v, n) ;
15068 p (n) ;
15069 visitDependants (v, n, p)
15071 END visitNode ;
15075 genKind - returns a string depending upon the kind of node, n.
15078 PROCEDURE genKind (n: node) : String ;
15079 BEGIN
15080 CASE n^.kind OF
15082 (* types, no need to generate a kind string as it it contained in the name. *)
15083 nil,
15084 true,
15085 false,
15086 address,
15087 loc,
15088 byte,
15089 word,
15090 csizet,
15091 cssizet,
15092 char,
15093 cardinal,
15094 longcard,
15095 shortcard,
15096 integer,
15097 longint,
15098 shortint,
15099 real,
15100 longreal,
15101 shortreal,
15102 bitset,
15103 boolean,
15104 proc,
15105 ztype,
15106 rtype,
15107 complex,
15108 longcomplex,
15109 shortcomplex : RETURN NIL |
15111 (* language features and compound type attributes. *)
15112 type : RETURN InitString ('type') |
15113 record : RETURN InitString ('record') |
15114 varient : RETURN InitString ('varient') |
15115 var : RETURN InitString ('var') |
15116 enumeration : RETURN InitString ('enumeration') |
15117 subrange : RETURN InitString ('subrange') |
15118 array : RETURN InitString ('array') |
15119 subscript : RETURN InitString ('subscript') |
15120 string : RETURN InitString ('string') |
15121 const : RETURN InitString ('const') |
15122 literal : RETURN InitString ('literal') |
15123 varparam : RETURN InitString ('varparam') |
15124 param : RETURN InitString ('param') |
15125 varargs : RETURN InitString ('varargs') |
15126 pointer : RETURN InitString ('pointer') |
15127 recordfield : RETURN InitString ('recordfield') |
15128 varientfield : RETURN InitString ('varientfield') |
15129 enumerationfield: RETURN InitString ('enumerationfield') |
15130 set : RETURN InitString ('set') |
15131 proctype : RETURN InitString ('proctype') |
15132 (* blocks. *)
15133 procedure : RETURN InitString ('procedure') |
15134 def : RETURN InitString ('def') |
15135 imp : RETURN InitString ('imp') |
15136 module : RETURN InitString ('module') |
15137 (* statements. *)
15138 loop : RETURN InitString ('loop') |
15139 while : RETURN InitString ('while') |
15140 for : RETURN InitString ('for') |
15141 repeat : RETURN InitString ('repeat') |
15142 assignment : RETURN InitString ('assignment') |
15143 if : RETURN InitString ('if') |
15144 elsif : RETURN InitString ('elsif') |
15145 (* expressions. *)
15146 constexp : RETURN InitString ('constexp') |
15147 neg : RETURN InitString ('neg') |
15148 cast : RETURN InitString ('cast') |
15149 val : RETURN InitString ('val') |
15150 plus : RETURN InitString ('plus') |
15151 sub : RETURN InitString ('sub') |
15152 div : RETURN InitString ('div') |
15153 mod : RETURN InitString ('mod') |
15154 mult : RETURN InitString ('mult') |
15155 divide : RETURN InitString ('divide') |
15156 adr : RETURN InitString ('adr') |
15157 size : RETURN InitString ('size') |
15158 tsize : RETURN InitString ('tsize') |
15159 chr : RETURN InitString ('chr') |
15160 ord : RETURN InitString ('ord') |
15161 float : RETURN InitString ('float') |
15162 trunc : RETURN InitString ('trunc') |
15163 high : RETURN InitString ('high') |
15164 componentref : RETURN InitString ('componentref') |
15165 pointerref : RETURN InitString ('pointerref') |
15166 arrayref : RETURN InitString ('arrayref') |
15167 deref : RETURN InitString ('deref') |
15168 equal : RETURN InitString ('equal') |
15169 notequal : RETURN InitString ('notequal') |
15170 less : RETURN InitString ('less') |
15171 greater : RETURN InitString ('greater') |
15172 greequal : RETURN InitString ('greequal') |
15173 lessequal : RETURN InitString ('lessequal') |
15174 lsl : RETURN InitString ('lsl') |
15175 lsr : RETURN InitString ('lsr') |
15176 lor : RETURN InitString ('lor') |
15177 land : RETURN InitString ('land') |
15178 lnot : RETURN InitString ('lnot') |
15179 lxor : RETURN InitString ('lxor') |
15180 and : RETURN InitString ('and') |
15181 or : RETURN InitString ('or') |
15182 not : RETURN InitString ('not') |
15183 identlist : RETURN InitString ('identlist') |
15184 vardecl : RETURN InitString ('vardecl')
15186 END ;
15187 HALT
15188 END genKind ;
15192 gen - generate a small string describing node, n.
15195 PROCEDURE gen (n: node) : String ;
15197 s: String ;
15198 d: CARDINAL ;
15199 BEGIN
15200 d := VAL (CARDINAL, VAL (LONGCARD, n)) ;
15201 s := Sprintf1 (InitString ('< %d '), d) ; (* use 0x%x once FormatStrings has been released. *)
15202 s := ConCat (s, genKind (n)) ;
15203 s := ConCat (s, InitString (' ')) ;
15204 s := ConCat (s, getFQstring (n)) ;
15205 s := ConCat (s, InitString (' >')) ;
15206 RETURN s
15207 END gen ;
15211 dumpQ -
15214 PROCEDURE dumpQ (q: ARRAY OF CHAR; l: alist) ;
15216 m : String ;
15217 n : node ;
15219 h, i: CARDINAL ;
15220 BEGIN
15221 m := Sprintf0 (InitString ('Queue ')) ;
15222 m := KillString (WriteS (StdOut, m)) ;
15223 m := Sprintf0 (InitString (q)) ;
15224 m := KillString (WriteS (StdOut, m)) ;
15225 m := Sprintf0 (InitString ('\n')) ;
15226 m := KillString (WriteS (StdOut, m)) ;
15227 i := 1 ;
15228 h := alists.noOfItemsInList (l) ;
15229 WHILE i<=h DO
15230 n := alists.getItemFromList (l, i) ;
15231 m := KillString (WriteS (StdOut, gen (n))) ;
15232 INC (i)
15233 END ;
15234 m := Sprintf0 (InitString ('\n')) ;
15235 m := KillString (WriteS (StdOut, m))
15236 END dumpQ ;
15240 dumpLists -
15243 PROCEDURE dumpLists ;
15244 BEGIN
15245 IF getDebugTopological () AND FALSE
15246 THEN
15247 dumpQ ('todo', globalGroup^.todoQ) ;
15248 dumpQ ('partial', globalGroup^.partialQ) ;
15249 dumpQ ('done', globalGroup^.doneQ)
15251 END dumpLists ;
15255 outputHidden -
15258 PROCEDURE outputHidden (n: node) ;
15259 BEGIN
15260 outText (doP, "#if !defined (") ; doFQNameC (doP, n) ; outText (doP, "_D)\n") ;
15261 outText (doP, "# define ") ; doFQNameC (doP, n) ; outText (doP, "_D\n") ;
15262 outText (doP, " typedef void *") ; doFQNameC (doP, n) ; outText (doP, ";\n") ;
15263 outText (doP, "#endif\n\n")
15264 END outputHidden ;
15268 outputHiddenComplete -
15271 PROCEDURE outputHiddenComplete (n: node) ;
15273 t: node ;
15274 BEGIN
15275 assert (isType (n)) ;
15276 t := getType (n) ;
15277 assert (isPointer (t)) ;
15278 outText (doP, "#define ") ; doFQNameC (doP, n) ; outText (doP, "_D\n") ;
15279 outText (doP, "typedef ") ; doTypeNameC (doP, getType (t)) ;
15280 setNeedSpace (doP) ; outText (doP, "*") ; doFQNameC (doP, n) ; outText (doP, ";\n")
15281 END outputHiddenComplete ;
15285 tryPartial -
15288 PROCEDURE tryPartial (n: node; pt: nodeProcedure) : BOOLEAN ;
15290 q : node ;
15291 seenPointer: BOOLEAN ;
15292 BEGIN
15293 IF (n#NIL) AND isType (n)
15294 THEN
15295 seenPointer := FALSE ;
15296 q := getType (n) ;
15297 WHILE isPointer (q) DO
15298 seenPointer := TRUE ;
15299 q := getType (q)
15300 END ;
15301 IF q # NIL
15302 THEN
15303 IF isRecord (q) OR isProcType (q)
15304 THEN
15305 pt (n) ;
15306 addTodo (q) ;
15307 RETURN TRUE
15308 ELSIF isArray (q) AND (seenPointer OR
15309 alists.isItemInList (globalGroup^.doneQ, getType (q)))
15310 THEN
15311 pt (n) ;
15312 addTodo (q) ;
15313 RETURN TRUE
15314 ELSIF isType (q) AND seenPointer
15315 THEN
15316 pt (n) ;
15317 addTodo (q) ;
15318 RETURN TRUE
15321 END ;
15322 RETURN FALSE
15323 END tryPartial ;
15328 tryPartial -
15331 PROCEDURE tryPartial (n: node; pt: nodeProcedure) : BOOLEAN ;
15333 q: node ;
15334 BEGIN
15335 IF (n#NIL) AND isType (n)
15336 THEN
15337 q := getType (n) ;
15338 WHILE isPointer (q) DO
15339 q := getType (q)
15340 END ;
15341 IF q # NIL
15342 THEN
15343 IF isRecord (q) OR isProcType (q)
15344 THEN
15345 pt (n) ;
15346 addTodo (q) ;
15347 RETURN TRUE
15348 ELSIF isArray (q)
15349 THEN
15350 pt (n) ;
15351 addTodo (q) ;
15352 RETURN TRUE
15355 END ;
15356 RETURN FALSE
15357 END tryPartial ;
15361 outputPartialRecordArrayProcType -
15364 PROCEDURE outputPartialRecordArrayProcType (n, q: node; indirection: CARDINAL) ;
15366 s: String ;
15367 BEGIN
15368 outText (doP, "typedef struct") ; setNeedSpace (doP) ;
15369 s := getFQstring (n) ;
15370 IF isRecord (q)
15371 THEN
15372 s := ConCat (s, Mark (InitString ("_r")))
15373 ELSIF isArray (q)
15374 THEN
15375 s := ConCat (s, Mark (InitString ("_a")))
15376 ELSIF isProcType (q)
15377 THEN
15378 s := ConCat (s, Mark (InitString ("_p")))
15379 END ;
15380 outTextS (doP, s) ;
15381 setNeedSpace (doP) ;
15382 s := KillString (s) ;
15383 WHILE indirection>0 DO
15384 outText (doP, "*") ;
15385 DEC (indirection)
15386 END ;
15387 doFQNameC (doP, n) ;
15388 outText (doP, ";\n\n")
15389 END outputPartialRecordArrayProcType ;
15393 outputPartial -
15396 PROCEDURE outputPartial (n: node) ;
15398 q : node ;
15399 indirection: CARDINAL ;
15400 BEGIN
15401 q := getType (n) ;
15402 indirection := 0 ;
15403 WHILE isPointer (q) DO
15404 q := getType (q) ;
15405 INC (indirection)
15406 END ;
15407 outputPartialRecordArrayProcType (n, q, indirection)
15408 END outputPartial ;
15412 tryOutputTodo -
15415 PROCEDURE tryOutputTodo (c, t, v, pt: nodeProcedure) ;
15417 i, n: CARDINAL ;
15418 d : node ;
15419 BEGIN
15420 i := 1 ;
15421 n := alists.noOfItemsInList (globalGroup^.todoQ) ;
15422 WHILE i<=n DO
15423 d := alists.getItemFromList (globalGroup^.todoQ, i) ;
15424 IF tryComplete (d, c, t, v)
15425 THEN
15426 alists.removeItemFromList (globalGroup^.todoQ, d) ;
15427 addDone (d) ;
15428 i := 1
15429 ELSIF tryPartial (d, pt)
15430 THEN
15431 alists.removeItemFromList (globalGroup^.todoQ, d) ;
15432 alists.includeItemIntoList (globalGroup^.partialQ, d) ;
15433 i := 1
15434 ELSE
15435 INC (i)
15436 END ;
15437 n := alists.noOfItemsInList (globalGroup^.todoQ)
15439 END tryOutputTodo ;
15443 tryOutputPartial -
15446 PROCEDURE tryOutputPartial (t: nodeProcedure) ;
15448 i, n: CARDINAL ;
15449 d : node ;
15450 BEGIN
15451 i := 1 ;
15452 n := alists.noOfItemsInList (globalGroup^.partialQ) ;
15453 WHILE i<=n DO
15454 d := alists.getItemFromList (globalGroup^.partialQ, i) ;
15455 IF tryCompleteFromPartial (d, t)
15456 THEN
15457 alists.removeItemFromList (globalGroup^.partialQ, d) ;
15458 addDone (d) ;
15459 i := 1 ;
15460 DEC (n)
15461 ELSE
15462 INC (i)
15465 END tryOutputPartial ;
15469 debugList -
15472 PROCEDURE debugList (listName, symName: ARRAY OF CHAR; l: alist) ;
15474 i, h: CARDINAL ;
15475 n : node ;
15476 BEGIN
15477 h := alists.noOfItemsInList (l) ;
15478 IF h>0
15479 THEN
15480 i := 1 ;
15481 REPEAT
15482 n := alists.getItemFromList (l, i) ;
15483 dbg (listName, symName, n) ;
15484 INC (i)
15485 UNTIL i > h
15487 END debugList ;
15491 debugLists -
15494 PROCEDURE debugLists ;
15495 BEGIN
15496 IF getDebugTopological ()
15497 THEN
15498 debugList ('todo', 'decl_node', globalGroup^.todoQ) ;
15499 debugList ('partial', 'decl_node', globalGroup^.partialQ) ;
15500 debugList ('done', 'decl_node', globalGroup^.doneQ)
15502 END debugLists ;
15506 addEnumConst -
15509 PROCEDURE addEnumConst (n: node) ;
15511 s: String ;
15512 BEGIN
15513 IF isConst (n) OR isEnumeration (n)
15514 THEN
15515 addTodo (n)
15517 END addEnumConst ;
15521 populateTodo -
15524 PROCEDURE populateTodo (p: nodeProcedure) ;
15526 n : node ;
15527 i, h: CARDINAL ;
15528 l : alist ;
15529 BEGIN
15530 h := alists.noOfItemsInList (globalGroup^.todoQ) ;
15531 i := 1 ;
15532 WHILE i <= h DO
15533 n := alists.getItemFromList (globalGroup^.todoQ, i) ;
15534 l := alists.initList () ;
15535 visitNode (l, n, p) ;
15536 alists.killList (l) ;
15537 h := alists.noOfItemsInList (globalGroup^.todoQ) ;
15538 INC (i)
15540 END populateTodo ;
15544 topologicallyOut - keep trying to resolve the todoQ and partialQ
15545 until there is no change from the global group.
15548 PROCEDURE topologicallyOut (c, t, v, tp,
15549 pc, pt, pv: nodeProcedure) ;
15551 before: group ;
15552 BEGIN
15553 populateTodo (addEnumConst) ;
15554 before := NIL ;
15555 REPEAT
15556 before := dupGroup (before) ; (* Get a copy of the globalGroup and free before. *)
15557 dumpLists ;
15558 tryOutputTodo (c, t, v, tp) ;
15559 dumpLists ;
15560 tryOutputPartial (pt)
15561 UNTIL equalGroup (before, globalGroup) ;
15562 killGroup (before) ;
15563 dumpLists ;
15564 debugLists
15565 END topologicallyOut ;
15569 scaffoldStatic -
15572 PROCEDURE scaffoldStatic (p: pretty; n: node) ;
15573 BEGIN
15574 outText (p, "\n") ;
15575 doExternCP (p) ;
15576 outText (p, "void") ;
15577 setNeedSpace (p) ;
15578 outText (p, "_M2_") ;
15579 doFQNameC (p, n) ;
15580 outText (p, "_init") ;
15581 setNeedSpace (p) ;
15582 outText (p, "(__attribute__((unused)) int argc,") ;
15583 setNeedSpace (p) ;
15584 outText (p, "__attribute__((unused)) char *argv[],") ;
15585 setNeedSpace (p) ;
15586 outText (p, "__attribute__((unused)) char *envp[])\n");
15587 p := outKc (p, "{\n") ;
15588 doStatementsC (p, n^.impF.beginStatements) ;
15589 p := outKc (p, "}\n") ;
15590 outText (p, "\n") ;
15591 doExternCP (p) ;
15592 outText (p, "void") ;
15593 setNeedSpace (p) ;
15594 outText (p, "_M2_") ;
15595 doFQNameC (p, n) ;
15596 outText (p, "_fini") ;
15597 setNeedSpace (p) ;
15598 outText (p, "(__attribute__((unused)) int argc,") ;
15599 setNeedSpace (p) ;
15600 outText (p, "__attribute__((unused)) char *argv[],") ;
15601 setNeedSpace (p) ;
15602 outText (p, "__attribute__((unused)) char *envp[])\n");
15603 p := outKc (p, "{\n") ;
15604 doStatementsC (p, n^.impF.finallyStatements) ;
15605 p := outKc (p, "}\n")
15606 END scaffoldStatic ;
15610 emitCtor -
15613 PROCEDURE emitCtor (p: pretty; n: node) ;
15615 s: String ;
15616 BEGIN
15617 outText (p, "\n") ;
15618 outText (p, "static void") ;
15619 setNeedSpace (p) ;
15620 outText (p, "ctorFunction ()\n") ;
15621 doFQNameC (p, n) ;
15622 p := outKc (p, "{\n") ;
15623 outText (p, 'M2RTS_RegisterModule ("') ;
15624 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15625 prints (p, s) ;
15626 outText (p, '",\n') ;
15627 outText (p, 'init, fini, dependencies);\n') ;
15628 p := outKc (p, "}\n\n") ;
15629 p := outKc (p, "struct ") ;
15630 prints (p, s) ;
15631 p := outKc (p, "_module_m2 { ") ;
15632 prints (p, s) ;
15633 p := outKc (p, "_module_m2 (); ~") ;
15634 prints (p, s) ;
15635 p := outKc (p, "_module_m2 (); } global_module_") ;
15636 prints (p, s) ;
15637 outText (p, ';\n\n') ;
15638 prints (p, s) ;
15639 p := outKc (p, "_module_m2::") ;
15640 prints (p, s) ;
15641 p := outKc (p, "_module_m2 ()\n") ;
15642 p := outKc (p, "{\n") ;
15643 outText (p, 'M2RTS_RegisterModule ("') ;
15644 prints (p, s) ;
15645 outText (p, '", init, fini, dependencies);') ;
15646 p := outKc (p, "}\n") ;
15647 prints (p, s) ;
15648 p := outKc (p, "_module_m2::~") ;
15649 prints (p, s) ;
15650 p := outKc (p, "_module_m2 ()\n") ;
15651 p := outKc (p, "{\n") ;
15652 p := outKc (p, "}\n") ;
15653 s := KillString (s)
15654 END emitCtor ;
15658 scaffoldDynamic -
15661 PROCEDURE scaffoldDynamic (p: pretty; n: node) ;
15662 BEGIN
15663 outText (p, "\n") ;
15664 doExternCP (p) ;
15665 outText (p, "void") ;
15666 setNeedSpace (p) ;
15667 outText (p, "_M2_") ;
15668 doFQNameC (p, n) ;
15669 outText (p, "_init") ;
15670 setNeedSpace (p) ;
15671 outText (p, "(__attribute__((unused)) int argc,") ;
15672 setNeedSpace (p) ;
15673 outText (p, "__attribute__((unused)) char *argv[],") ;
15674 setNeedSpace (p) ;
15675 outText (p, "__attribute__((unused)) char *envp[])\n") ;
15676 p := outKc (p, "{\n") ;
15677 doStatementsC (p, n^.impF.beginStatements) ;
15678 p := outKc (p, "}\n") ;
15679 outText (p, "\n") ;
15680 doExternCP (p) ;
15681 outText (p, "void") ;
15682 setNeedSpace (p) ;
15683 outText (p, "_M2_") ;
15684 doFQNameC (p, n) ;
15685 outText (p, "_fini") ;
15686 setNeedSpace (p) ;
15687 outText (p, "(__attribute__((unused)) int argc,") ;
15688 setNeedSpace (p) ;
15689 outText (p, "__attribute__((unused)) char *argv[],") ;
15690 setNeedSpace (p) ;
15691 outText (p, "__attribute__((unused)) char *envp[])\n") ;
15692 p := outKc (p, "{\n") ;
15693 doStatementsC (p, n^.impF.finallyStatements) ;
15694 p := outKc (p, "}\n") ;
15695 emitCtor (p, n)
15696 END scaffoldDynamic ;
15700 scaffoldMain -
15703 PROCEDURE scaffoldMain (p: pretty; n: node) ;
15705 s: String ;
15706 BEGIN
15707 outText (p, "int\n") ;
15708 outText (p, "main") ;
15709 setNeedSpace (p) ;
15710 outText (p, "(int argc, char *argv[], char *envp[])\n") ;
15711 p := outKc (p, "{\n") ;
15712 outText (p, "M2RTS_ConstructModules (") ;
15713 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15714 prints (p, s) ;
15715 outText (p, ", argc, argv, envp);\n");
15716 outText (p, "M2RTS_DeconstructModules (") ;
15717 prints (p, s) ;
15718 outText (p, ", argc, argv, envp);\n");
15719 outText (p, "return 0;") ;
15720 p := outKc (p, "}\n") ;
15721 s := KillString (s)
15722 END scaffoldMain ;
15726 outImpInitC - emit the init/fini functions and main function if required.
15729 PROCEDURE outImpInitC (p: pretty; n: node) ;
15730 BEGIN
15731 IF getScaffoldDynamic ()
15732 THEN
15733 scaffoldDynamic (p, n)
15734 ELSE
15735 scaffoldStatic (p, n)
15736 END ;
15737 IF getScaffoldMain ()
15738 THEN
15739 scaffoldMain (p, n)
15741 END outImpInitC ;
15745 runSimplifyTypes -
15748 PROCEDURE runSimplifyTypes (n: node) ;
15749 BEGIN
15750 IF isImp (n)
15751 THEN
15752 simplifyTypes (n^.impF.decls)
15753 ELSIF isModule (n)
15754 THEN
15755 simplifyTypes (n^.moduleF.decls)
15756 ELSIF isDef (n)
15757 THEN
15758 simplifyTypes (n^.defF.decls)
15760 END runSimplifyTypes ;
15764 outDefC -
15767 PROCEDURE outDefC (p: pretty; n: node) ;
15769 s: String ;
15770 BEGIN
15771 assert (isDef (n)) ;
15772 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15773 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15774 print (p, "/* do not edit automatically generated by mc from ") ;
15775 prints (p, s) ; print (p, ". */\n") ;
15776 writeGPLheader (outputFile) ;
15777 doCommentC (p, n^.defF.com.body) ;
15778 print (p, "\n\n#if !defined (_") ; prints (p, s) ; print (p, "_H)\n") ;
15779 print (p, "# define _") ; prints (p, s) ; print (p, "_H\n\n") ;
15781 keyc.genConfigSystem (p) ;
15783 print (p, "# ifdef __cplusplus\n") ;
15784 print (p, 'extern "C" {\n') ;
15785 print (p, "# endif\n") ;
15787 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15789 doP := p ;
15790 ForeachIndiceInIndexDo (n^.defF.importedModules, doIncludeC) ;
15792 print (p, "\n") ;
15793 print (p, "# if defined (_") ; prints (p, s) ; print (p, "_C)\n") ;
15794 print (p, "# define EXTERN\n") ;
15795 print (p, "# else\n") ;
15796 print (p, '# define EXTERN extern\n') ;
15797 print (p, "# endif\n\n") ;
15799 outDeclsDefC (p, n) ;
15800 runPrototypeDefC (n) ;
15802 print (p, "# ifdef __cplusplus\n") ;
15803 print (p, "}\n") ;
15804 print (p, "# endif\n") ;
15806 print (p, "\n") ;
15807 print (p, "# undef EXTERN\n") ;
15808 print (p, "#endif\n") ;
15810 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
15811 keyc.genDefs (p) ;
15813 s := KillString (s)
15814 END outDefC ;
15818 runPrototypeExported -
15821 PROCEDURE runPrototypeExported (n: node) ;
15822 BEGIN
15823 IF isExported (n)
15824 THEN
15825 keyc.enterScope (n) ;
15826 doProcedureHeadingC (n, TRUE) ;
15827 print (doP, ";\n") ;
15828 keyc.leaveScope (n)
15830 END runPrototypeExported ;
15834 runPrototypeDefC -
15837 PROCEDURE runPrototypeDefC (n: node) ;
15838 BEGIN
15839 IF isDef (n)
15840 THEN
15841 ForeachIndiceInIndexDo (n^.defF.decls.procedures, runPrototypeExported)
15843 END runPrototypeDefC ;
15847 outImpC -
15850 PROCEDURE outImpC (p: pretty; n: node) ;
15852 s : String ;
15853 defModule: node ;
15854 BEGIN
15855 assert (isImp (n)) ;
15856 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15857 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15858 print (p, "/* do not edit automatically generated by mc from ") ;
15859 prints (p, s) ; print (p, ". */\n") ;
15860 writeGPLheader (outputFile) ;
15861 doCommentC (p, n^.impF.com.body) ;
15862 outText (p, "\n") ;
15863 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15864 IF getExtendedOpaque ()
15865 THEN
15866 doP := p ;
15867 (* ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeC) ; *)
15869 includeExternals (n) ;
15870 foreachModuleDo (n, runSimplifyTypes) ;
15871 printf ("/* --extended-opaque seen therefore no #include will be used and everything will be declared in full. */\n") ;
15872 foreachDefModuleDo (runIncludeDefConstType) ;
15873 includeDefVarProcedure (n) ;
15874 outDeclsImpC (p, n^.impF.decls) ;
15875 foreachDefModuleDo (runPrototypeDefC)
15876 ELSE
15877 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15878 (* Inform the source that this code belongs to the implementation module. *)
15879 print (p, "#define _") ; prints (p, s) ; print (p, "_C\n\n") ;
15880 (* Include the definition module for any opaque types. *)
15881 print (doP, '#include "') ;
15882 prints (p, getHPrefix ()) ;
15883 prints (p, s) ;
15884 print (p, '.h"\n') ;
15885 s := KillString (s) ;
15887 doP := p ;
15888 ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeC) ;
15889 print (p, "\n") ;
15890 includeDefConstType (n) ;
15891 includeDefVarProcedure (n) ;
15892 outDeclsImpC (p, n^.impF.decls) ;
15894 defModule := lookupDef (getSymName (n)) ;
15895 IF defModule # NIL
15896 THEN
15897 runPrototypeDefC (defModule)
15899 END ;
15901 ForeachIndiceInIndexDo (n^.impF.decls.procedures, doPrototypeC) ;
15903 outProceduresC (p, n^.impF.decls) ;
15904 outImpInitC (p, n) ;
15906 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
15907 keyc.genConfigSystem (p) ;
15908 keyc.genDefs (p)
15909 END outImpC ;
15913 outDeclsModuleC -
15916 PROCEDURE outDeclsModuleC (p: pretty; s: scopeT) ;
15917 BEGIN
15918 simplifyTypes (s) ;
15919 includeConstType (s) ;
15921 doP := p ;
15923 topologicallyOut (doConstC, doTypesC, doVarC,
15924 outputPartial,
15925 doNone, doCompletePartialC, doNone) ;
15927 (* try and output types, constants before variables and procedures. *)
15928 includeVarProcedure (s) ;
15930 topologicallyOut (doConstC, doTypesC, doVarC,
15931 outputPartial,
15932 doNone, doCompletePartialC, doNone) ;
15934 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
15935 END outDeclsModuleC ;
15939 outModuleInitC -
15942 PROCEDURE outModuleInitC (p: pretty; n: node) ;
15943 BEGIN
15944 outText (p, "\n") ;
15945 doExternCP (p) ;
15946 outText (p, "void") ;
15947 setNeedSpace (p) ;
15948 outText (p, "_M2_") ;
15949 doFQNameC (p, n) ;
15950 outText (p, "_init") ;
15951 setNeedSpace (p) ;
15952 outText (p, "(__attribute__((unused)) int argc") ;
15953 outText (p, ",__attribute__((unused)) char *argv[]") ;
15954 outText (p, ",__attribute__((unused)) char *envp[])\n");
15955 p := outKc (p, "{\n") ;
15956 doStatementsC (p, n^.moduleF.beginStatements) ;
15957 p := outKc (p, "}\n") ;
15958 outText (p, "\n") ;
15959 doExternCP (p) ;
15960 outText (p, "void") ;
15961 setNeedSpace (p) ;
15962 outText (p, "_M2_") ;
15963 doFQNameC (p, n) ;
15964 outText (p, "_fini") ;
15965 setNeedSpace (p) ;
15966 outText (p, "(__attribute__((unused)) int argc") ;
15967 outText (p, ",__attribute__((unused)) char *argv[]") ;
15968 outText (p, ",__attribute__((unused)) char *envp[])\n");
15969 p := outKc (p, "{\n") ;
15970 doStatementsC (p, n^.moduleF.finallyStatements) ;
15971 p := outKc (p, "}\n")
15972 END outModuleInitC ;
15976 outModuleC -
15979 PROCEDURE outModuleC (p: pretty; n: node) ;
15981 s: String ;
15982 BEGIN
15983 assert (isModule (n)) ;
15984 outputFile := mcStream.openFrag (1) ; (* first fragment. *)
15985 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
15986 print (p, "/* do not edit automatically generated by mc from ") ;
15987 prints (p, s) ; print (p, ". */\n") ;
15988 writeGPLheader (outputFile) ;
15989 doCommentC (p, n^.moduleF.com.body) ;
15990 outText (p, "\n") ;
15991 outputFile := mcStream.openFrag (3) ; (* third fragment. *)
15992 IF getExtendedOpaque ()
15993 THEN
15994 doP := p ;
15995 includeExternals (n) ;
15996 foreachModuleDo (n, runSimplifyTypes) ;
15997 printf ("/* --extended-opaque seen therefore no #include will be used and everything will be declared in full. */\n") ;
15998 foreachDefModuleDo (runIncludeDefConstType) ;
15999 outDeclsModuleC (p, n^.moduleF.decls) ;
16000 foreachDefModuleDo (runPrototypeDefC)
16001 ELSE
16002 doP := p ;
16003 ForeachIndiceInIndexDo (n^.moduleF.importedModules, doIncludeC) ;
16004 print (p, "\n") ;
16005 outDeclsModuleC (p, n^.moduleF.decls)
16006 END ;
16008 ForeachIndiceInIndexDo (n^.moduleF.decls.procedures, doPrototypeC) ;
16010 outProceduresC (p, n^.moduleF.decls) ;
16011 outModuleInitC (p, n) ;
16013 outputFile := mcStream.openFrag (2) ; (* second fragment. *)
16014 keyc.genConfigSystem (p) ;
16015 keyc.genDefs (p)
16016 END outModuleC ;
16020 outC -
16023 PROCEDURE outC (p: pretty; n: node) ;
16024 BEGIN
16025 keyc.enterScope (n) ;
16026 IF isDef (n)
16027 THEN
16028 outDefC (p, n)
16029 ELSIF isImp (n)
16030 THEN
16031 outImpC (p, n)
16032 ELSIF isModule (n)
16033 THEN
16034 outModuleC (p, n)
16035 ELSE
16036 HALT
16037 END ;
16038 keyc.leaveScope (n)
16039 END outC ;
16043 doIncludeM2 - include modules in module, n.
16046 PROCEDURE doIncludeM2 (n: node) ;
16048 s: String ;
16049 BEGIN
16050 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
16051 print (doP, 'IMPORT ') ;
16052 prints (doP, s) ;
16053 print (doP, ' ;\n') ;
16054 s := KillString (s) ;
16056 IF isDef (n)
16057 THEN
16058 foreachNodeDo (n^.defF.decls.symbols, addDone)
16059 ELSIF isImp (n)
16060 THEN
16061 foreachNodeDo (n^.impF.decls.symbols, addDone)
16062 ELSIF isModule (n)
16063 THEN
16064 foreachNodeDo (n^.moduleF.decls.symbols, addDone)
16066 END doIncludeM2 ;
16070 doConstM2 -
16073 PROCEDURE doConstM2 (n: node) ;
16074 BEGIN
16075 print (doP, "CONST\n") ;
16076 doFQNameC (doP, n) ;
16077 setNeedSpace (doP) ;
16078 doExprC (doP, n^.constF.value) ;
16079 print (doP, '\n')
16080 END doConstM2 ;
16084 doProcTypeM2 -
16087 PROCEDURE doProcTypeM2 (p: pretty; n: node) ;
16088 BEGIN
16089 outText (p, "proc type to do..")
16090 END doProcTypeM2 ;
16094 doRecordFieldM2 -
16097 PROCEDURE doRecordFieldM2 (p: pretty; f: node) ;
16098 BEGIN
16099 doNameM2 (p, f) ;
16100 outText (p, ":") ;
16101 setNeedSpace (p) ;
16102 doTypeM2 (p, getType (f)) ;
16103 setNeedSpace (p)
16104 END doRecordFieldM2 ;
16108 doVarientFieldM2 -
16111 PROCEDURE doVarientFieldM2 (p: pretty; n: node) ;
16113 i, t: CARDINAL ;
16114 q : node ;
16115 BEGIN
16116 assert (isVarientField (n)) ;
16117 doNameM2 (p, n) ;
16118 outText (p, ":") ;
16119 setNeedSpace (p) ;
16120 i := LowIndice (n^.varientfieldF.listOfSons) ;
16121 t := HighIndice (n^.varientfieldF.listOfSons) ;
16122 WHILE i<=t DO
16123 q := GetIndice (n^.varientfieldF.listOfSons, i) ;
16124 IF isRecordField (q)
16125 THEN
16126 doRecordFieldM2 (p, q) ;
16127 outText (p, ";\n")
16128 ELSIF isVarient (q)
16129 THEN
16130 doVarientM2 (p, q) ;
16131 outText (p, ";\n")
16132 ELSE
16133 HALT
16134 END ;
16135 INC (i)
16137 END doVarientFieldM2 ;
16141 doVarientM2 -
16144 PROCEDURE doVarientM2 (p: pretty; n: node) ;
16146 i, t: CARDINAL ;
16147 q : node ;
16148 BEGIN
16149 assert (isVarient (n)) ;
16150 outText (p, "CASE") ; setNeedSpace (p) ;
16151 IF n^.varientF.tag # NIL
16152 THEN
16153 IF isRecordField (n^.varientF.tag)
16154 THEN
16155 doRecordFieldM2 (p, n^.varientF.tag)
16156 ELSIF isVarientField (n^.varientF.tag)
16157 THEN
16158 doVarientFieldM2 (p, n^.varientF.tag)
16159 ELSE
16160 HALT
16162 END ;
16163 setNeedSpace (p) ;
16164 outText (p, "OF\n") ;
16165 i := LowIndice (n^.varientF.listOfSons) ;
16166 t := HighIndice (n^.varientF.listOfSons) ;
16167 WHILE i<=t DO
16168 q := GetIndice (n^.varientF.listOfSons, i) ;
16169 IF isRecordField (q)
16170 THEN
16171 IF NOT q^.recordfieldF.tag
16172 THEN
16173 doRecordFieldM2 (p, q) ;
16174 outText (p, ";\n")
16176 ELSIF isVarientField (q)
16177 THEN
16178 doVarientFieldM2 (p, q)
16179 ELSE
16180 HALT
16181 END ;
16182 INC (i)
16183 END ;
16184 outText (p, "END") ; setNeedSpace (p)
16185 END doVarientM2 ;
16189 doRecordM2 -
16192 PROCEDURE doRecordM2 (p: pretty; n: node) ;
16194 i, h: CARDINAL ;
16195 f : node ;
16196 BEGIN
16197 assert (isRecord (n)) ;
16198 p := outKm2 (p, "RECORD") ;
16199 i := LowIndice (n^.recordF.listOfSons) ;
16200 h := HighIndice (n^.recordF.listOfSons) ;
16201 outText (p, "\n") ;
16202 WHILE i<=h DO
16203 f := GetIndice (n^.recordF.listOfSons, i) ;
16204 IF isRecordField (f)
16205 THEN
16206 IF NOT f^.recordfieldF.tag
16207 THEN
16208 doRecordFieldM2 (p, f) ;
16209 outText (p, ";\n")
16211 ELSIF isVarient (f)
16212 THEN
16213 doVarientM2 (p, f) ;
16214 outText (p, ";\n")
16215 ELSIF isVarientField (f)
16216 THEN
16217 doVarientFieldM2 (p, f)
16218 END ;
16219 INC (i)
16220 END ;
16221 p := outKm2 (p, "END") ; setNeedSpace (p)
16222 END doRecordM2 ;
16226 doPointerM2 -
16229 PROCEDURE doPointerM2 (p: pretty; n: node) ;
16230 BEGIN
16231 outText (p, "POINTER TO") ;
16232 setNeedSpace (doP) ;
16233 doTypeM2 (p, getType (n)) ;
16234 setNeedSpace (p) ;
16235 outText (p, ";\n")
16236 END doPointerM2 ;
16240 doTypeAliasM2 -
16243 PROCEDURE doTypeAliasM2 (p: pretty; n: node) ;
16244 BEGIN
16245 doTypeNameC (p, n) ;
16246 setNeedSpace (p) ;
16247 outText (doP, "=") ;
16248 setNeedSpace (p) ;
16249 doTypeM2 (p, getType (n)) ;
16250 setNeedSpace (p) ;
16251 outText (p, "\n")
16252 END doTypeAliasM2 ;
16256 doEnumerationM2 -
16259 PROCEDURE doEnumerationM2 (p: pretty; n: node) ;
16261 i, h: CARDINAL ;
16262 s : node ;
16263 t : String ;
16264 BEGIN
16265 outText (p, "(") ;
16266 i := LowIndice (n^.enumerationF.listOfSons) ;
16267 h := HighIndice (n^.enumerationF.listOfSons) ;
16268 WHILE i <= h DO
16269 s := GetIndice (n^.enumerationF.listOfSons, i) ;
16270 doFQNameC (p, s) ;
16271 IF i < h
16272 THEN
16273 outText (p, ",") ; setNeedSpace (p)
16274 END ;
16275 INC (i)
16276 END ;
16277 outText (p, ")")
16278 END doEnumerationM2 ;
16282 doBaseM2 -
16285 PROCEDURE doBaseM2 (p: pretty; n: node) ;
16286 BEGIN
16287 CASE n^.kind OF
16289 char,
16290 cardinal,
16291 longcard,
16292 shortcard,
16293 integer,
16294 longint,
16295 shortint,
16296 complex,
16297 longcomplex,
16298 shortcomplex,
16299 real,
16300 longreal,
16301 shortreal,
16302 bitset,
16303 boolean,
16304 proc : doNameM2 (p, n)
16306 END ;
16307 setNeedSpace (p)
16308 END doBaseM2 ;
16312 doSystemM2 -
16315 PROCEDURE doSystemM2 (p: pretty; n: node) ;
16316 BEGIN
16317 CASE n^.kind OF
16319 address,
16320 loc,
16321 byte ,
16322 word ,
16323 csizet ,
16324 cssizet: doNameM2 (p, n)
16327 END doSystemM2 ;
16331 doTypeM2 -
16334 PROCEDURE doTypeM2 (p: pretty; n: node) ;
16335 BEGIN
16336 IF isBase (n)
16337 THEN
16338 doBaseM2 (p, n)
16339 ELSIF isSystem (n)
16340 THEN
16341 doSystemM2 (p, n)
16342 ELSIF isType (n)
16343 THEN
16344 doTypeAliasM2 (p, n)
16345 ELSIF isProcType (n)
16346 THEN
16347 doProcTypeM2 (p, n)
16348 ELSIF isPointer (n)
16349 THEN
16350 doPointerM2 (p, n)
16351 ELSIF isEnumeration (n)
16352 THEN
16353 doEnumerationM2 (p, n)
16354 ELSIF isRecord (n)
16355 THEN
16356 doRecordM2 (p, n)
16358 END doTypeM2 ;
16362 doTypesM2 -
16365 PROCEDURE doTypesM2 (n: node) ;
16367 m: node ;
16368 BEGIN
16369 outText (doP, "TYPE\n") ;
16370 doTypeM2 (doP, n)
16371 END doTypesM2 ;
16375 doVarM2 -
16378 PROCEDURE doVarM2 (n: node) ;
16379 BEGIN
16380 assert (isVar (n)) ;
16381 doNameC (doP, n) ;
16382 outText (doP, ":") ;
16383 setNeedSpace (doP) ;
16384 doTypeM2 (doP, getType (n)) ;
16385 setNeedSpace (doP) ;
16386 outText (doP, ";\n")
16387 END doVarM2 ;
16391 doVarsM2 -
16394 PROCEDURE doVarsM2 (n: node) ;
16396 m: node ;
16397 BEGIN
16398 outText (doP, "VAR\n") ;
16399 doVarM2 (n)
16400 END doVarsM2 ;
16404 doTypeNameM2 -
16407 PROCEDURE doTypeNameM2 (p: pretty; n: node) ;
16408 BEGIN
16409 doNameM2 (p, n)
16410 END doTypeNameM2 ;
16414 doParamM2 -
16417 PROCEDURE doParamM2 (p: pretty; n: node) ;
16419 ptype: node ;
16420 i : Name ;
16421 c, t : CARDINAL ;
16422 l : wlist ;
16423 BEGIN
16424 assert (isParam (n)) ;
16425 ptype := getType (n) ;
16426 IF n^.paramF.namelist = NIL
16427 THEN
16428 doTypeNameM2 (p, ptype)
16429 ELSE
16430 assert (isIdentList (n^.paramF.namelist)) ;
16431 l := n^.paramF.namelist^.identlistF.names ;
16432 IF l=NIL
16433 THEN
16434 doTypeNameM2 (p, ptype)
16435 ELSE
16436 t := wlists.noOfItemsInList (l) ;
16437 c := 1 ;
16438 WHILE c <= t DO
16439 i := wlists.getItemFromList (l, c) ;
16440 setNeedSpace (p) ;
16441 doNamesC (p, i) ;
16442 IF c<t
16443 THEN
16444 outText (p, ',') ; setNeedSpace (p)
16445 END ;
16446 INC (c)
16447 END ;
16448 outText (p, ':') ; setNeedSpace (p) ;
16449 doTypeNameM2 (p, ptype)
16452 END doParamM2 ;
16456 doVarParamM2 -
16459 PROCEDURE doVarParamM2 (p: pretty; n: node) ;
16461 ptype: node ;
16462 i : Name ;
16463 c, t : CARDINAL ;
16464 l : wlist ;
16465 BEGIN
16466 assert (isVarParam (n)) ;
16467 outText (p, 'VAR') ; setNeedSpace (p) ;
16468 ptype := getType (n) ;
16469 IF n^.varparamF.namelist = NIL
16470 THEN
16471 doTypeNameM2 (p, ptype)
16472 ELSE
16473 assert (isIdentList (n^.varparamF.namelist)) ;
16474 l := n^.varparamF.namelist^.identlistF.names ;
16475 IF l=NIL
16476 THEN
16477 doTypeNameM2 (p, ptype)
16478 ELSE
16479 t := wlists.noOfItemsInList (l) ;
16480 c := 1 ;
16481 WHILE c <= t DO
16482 i := wlists.getItemFromList (l, c) ;
16483 setNeedSpace (p) ;
16484 doNamesC (p, i) ;
16485 IF c<t
16486 THEN
16487 outText (p, ',') ; setNeedSpace (p)
16488 END ;
16489 INC (c)
16490 END ;
16491 outText (p, ':') ; setNeedSpace (p) ;
16492 doTypeNameM2 (p, ptype)
16495 END doVarParamM2 ;
16499 doParameterM2 -
16502 PROCEDURE doParameterM2 (p: pretty; n: node) ;
16503 BEGIN
16504 IF isParam (n)
16505 THEN
16506 doParamM2 (p, n)
16507 ELSIF isVarParam (n)
16508 THEN
16509 doVarParamM2 (p, n)
16510 ELSIF isVarargs (n)
16511 THEN
16512 print (p, "...")
16514 END doParameterM2 ;
16518 doPrototypeM2 -
16521 PROCEDURE doPrototypeM2 (n: node) ;
16523 i, h: CARDINAL ;
16524 p : node ;
16525 BEGIN
16526 assert (isProcedure (n)) ;
16527 noSpace (doP) ;
16529 doNameM2 (doP, n) ;
16530 setNeedSpace (doP) ;
16531 outText (doP, "(") ;
16532 i := LowIndice (n^.procedureF.parameters) ;
16533 h := HighIndice (n^.procedureF.parameters) ;
16534 WHILE i <= h DO
16535 p := GetIndice (n^.procedureF.parameters, i) ;
16536 doParameterM2 (doP, p) ;
16537 noSpace (doP) ;
16538 IF i < h
16539 THEN
16540 print (doP, ";") ; setNeedSpace (doP)
16541 END ;
16542 INC (i)
16543 END ;
16544 outText (doP, ")") ;
16545 IF n^.procedureF.returnType#NIL
16546 THEN
16547 setNeedSpace (doP) ;
16548 outText (doP, ":") ;
16549 doTypeM2 (doP, n^.procedureF.returnType) ; setNeedSpace (doP)
16550 END ;
16551 outText (doP, ";\n")
16552 END doPrototypeM2 ;
16556 outputPartialM2 - just writes out record, array, and proctypes.
16557 No need for forward declarations in Modula-2
16558 but we need to keep topological sort happy.
16559 So when asked to output partial we emit the
16560 full type for these types and then do nothing
16561 when trying to complete partial to full.
16564 PROCEDURE outputPartialM2 (n: node) ;
16566 q: node ;
16567 BEGIN
16568 q := getType (n) ;
16569 IF isRecord (q)
16570 THEN
16571 doTypeM2 (doP, n)
16572 ELSIF isArray (q)
16573 THEN
16574 doTypeM2 (doP, n)
16575 ELSIF isProcType (q)
16576 THEN
16577 doTypeM2 (doP, n)
16579 END outputPartialM2 ;
16583 outDeclsDefM2 -
16586 PROCEDURE outDeclsDefM2 (p: pretty; s: scopeT) ;
16587 BEGIN
16588 simplifyTypes (s) ;
16589 includeConstType (s) ;
16591 doP := p ;
16593 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16594 outputPartialM2,
16595 doNothing, doNothing, doNothing) ;
16597 includeVarProcedure (s) ;
16599 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16600 outputPartialM2,
16601 doNothing, doNothing, doNothing) ;
16603 ForeachIndiceInIndexDo (s.procedures, doPrototypeM2)
16604 END outDeclsDefM2 ;
16608 outDefM2 -
16611 PROCEDURE outDefM2 (p: pretty; n: node) ;
16613 s: String ;
16614 BEGIN
16615 s := InitStringCharStar (keyToCharStar (getSource (n))) ;
16616 print (p, "(* automatically created by mc from ") ; prints (p, s) ; print (p, ". *)\n\n") ;
16617 s := KillString (s) ;
16618 s := InitStringCharStar (keyToCharStar (getSymName (n))) ;
16619 print (p, "DEFINITION MODULE ") ; prints (p, s) ; print (p, " ;\n\n") ;
16621 doP := p ;
16622 ForeachIndiceInIndexDo (n^.defF.importedModules, doIncludeM2) ;
16624 print (p, "\n") ;
16626 outDeclsDefM2 (p, n^.defF.decls) ;
16628 print (p, "\n") ;
16629 print (p, "END ") ;
16630 prints (p, s) ;
16631 print (p, ".\n") ;
16632 s := KillString (s)
16633 END outDefM2 ;
16637 outDeclsImpM2 -
16640 PROCEDURE outDeclsImpM2 (p: pretty; s: scopeT) ;
16641 BEGIN
16642 simplifyTypes (s) ;
16643 includeConstType (s) ;
16645 doP := p ;
16647 topologicallyOut (doConstM2, doTypesM2, doVarM2,
16648 outputPartialM2,
16649 doNothing, doNothing, doNothing) ;
16651 includeVarProcedure (s) ;
16653 topologicallyOut (doConstM2, doTypesM2, doVarsM2,
16654 outputPartialM2,
16655 doNothing, doNothing, doNothing) ;
16657 outText (p, "\n") ;
16658 ForeachIndiceInIndexDo (s.procedures, doPrototypeC)
16659 END outDeclsImpM2 ;
16663 outImpM2 -
16666 PROCEDURE outImpM2 (p: pretty; n: node) ;
16668 s: String ;
16669 BEGIN
16670 s := InitStringCharStar (keyToCharStar (getSource (n))) ;
16671 print (p, "(* automatically created by mc from ") ; prints (p, s) ; print (p, ". *)\n\n") ;
16672 print (p, "IMPLEMENTATION MODULE ") ; prints (p, s) ; print (p, " ;\n\n") ;
16674 doP := p ;
16675 ForeachIndiceInIndexDo (n^.impF.importedModules, doIncludeM2) ;
16676 print (p, "\n") ;
16678 includeDefConstType (n) ;
16679 outDeclsImpM2 (p, n^.impF.decls) ;
16681 print (p, "\n") ;
16682 print (p, "END ") ;
16683 prints (p, s) ;
16684 print (p, ".\n") ;
16686 s := KillString (s)
16687 END outImpM2 ;
16691 outModuleM2 -
16694 PROCEDURE outModuleM2 (p: pretty; n: node) ;
16695 BEGIN
16697 END outModuleM2 ;
16701 outM2 -
16704 PROCEDURE outM2 (p: pretty; n: node) ;
16705 BEGIN
16706 IF isDef (n)
16707 THEN
16708 outDefM2 (p, n)
16709 ELSIF isImp (n)
16710 THEN
16711 outImpM2 (p, n)
16712 ELSIF isModule (n)
16713 THEN
16714 outModuleM2 (p, n)
16715 ELSE
16716 HALT
16718 END outM2 ;
16722 out - walks the tree of node declarations for the main module
16723 and writes the output to the outputFile specified in
16724 mcOptions. It outputs the declarations in the language
16725 specified above.
16728 PROCEDURE out ;
16730 p: pretty ;
16731 BEGIN
16732 openOutput ;
16733 p := initPretty (write, writeln) ;
16734 CASE lang OF
16736 ansiC : outC (p, getMainModule ()) |
16737 ansiCP: outC (p, getMainModule ()) |
16738 pim4 : outM2 (p, getMainModule ())
16740 END ;
16741 closeOutput
16742 END out ;
16746 setLangC -
16749 PROCEDURE setLangC ;
16750 BEGIN
16751 lang := ansiC
16752 END setLangC ;
16756 setLangCP -
16759 PROCEDURE setLangCP ;
16760 BEGIN
16761 lang := ansiCP ;
16762 keyc.cp
16763 END setLangCP ;
16767 setLangM2 -
16770 PROCEDURE setLangM2 ;
16771 BEGIN
16772 lang := pim4
16773 END setLangM2 ;
16777 addDone - adds node, n, to the doneQ.
16780 PROCEDURE addDone (n: node) ;
16782 s: String ;
16783 BEGIN
16784 alists.includeItemIntoList (globalGroup^.doneQ, n) ;
16785 IF isVar (n) OR isParameter (n)
16786 THEN
16787 initNodeOpaqueState (n)
16788 END ;
16789 debugLists
16790 END addDone ;
16794 addDoneDef - adds node, n, to the doneQ providing
16795 it is not an opaque of the main module we are compiling.
16798 PROCEDURE addDoneDef (n: node) ;
16799 BEGIN
16800 IF isDef (n)
16801 THEN
16802 addDone (n) ;
16803 RETURN
16804 END ;
16805 IF FALSE AND (lookupImp (getSymName (getScope (n))) = getMainModule ())
16806 THEN
16807 metaError1 ('cyclic dependancy found between another module using {%1ad} from the definition module of the implementation main being compiled, use the --extended-opaque option to compile', n) ;
16808 flushErrors ;
16809 errorAbort0 ('terminating compilation')
16810 ELSIF isType (n) AND isDeclInImp (n)
16811 THEN
16812 (* Ignore an opaque type which is declared in this implementation module as it
16813 will be fully declared in C/C++ with the __opaque postfix. Whereas the
16814 void * non prefixed typedef will be declared in the .h file. *)
16815 ELSE
16816 addDone (n)
16818 END addDoneDef ;
16822 dbgAdd -
16825 PROCEDURE dbgAdd (l: alist; n: node) : node ;
16826 BEGIN
16827 IF n#NIL
16828 THEN
16829 alists.includeItemIntoList (l, n)
16830 END ;
16831 RETURN n
16832 END dbgAdd ;
16836 dbgType -
16839 PROCEDURE dbgType (l: alist; n: node) ;
16841 t: node ;
16842 BEGIN
16843 t := dbgAdd (l, getType (n)) ;
16844 out1 ("<%s type", n) ;
16845 IF t = NIL
16846 THEN
16847 out0 (", type = NIL\n")
16848 ELSE
16849 out1 (", type = %s>\n", t)
16851 END dbgType ;
16855 dbgPointer -
16858 PROCEDURE dbgPointer (l: alist; n: node) ;
16860 t: node ;
16861 BEGIN
16862 t := dbgAdd (l, getType (n)) ;
16863 out1 ("<%s pointer", n) ;
16864 out1 (" to %s>\n", t)
16865 END dbgPointer ;
16869 dbgRecord -
16872 PROCEDURE dbgRecord (l: alist; n: node) ;
16874 i, t: CARDINAL ;
16875 q : node ;
16876 BEGIN
16877 out1 ("<%s record:\n", n) ;
16878 i := LowIndice (n^.recordF.listOfSons) ;
16879 t := HighIndice (n^.recordF.listOfSons) ;
16880 WHILE i<=t DO
16881 q := GetIndice (n^.recordF.listOfSons, i) ;
16882 IF isRecordField (q)
16883 THEN
16884 out1 (" <recordfield %s", q)
16885 ELSIF isVarientField (q)
16886 THEN
16887 out1 (" <varientfield %s", q)
16888 ELSIF isVarient (q)
16889 THEN
16890 out1 (" <varient %s", q)
16891 ELSE
16892 HALT
16893 END ;
16894 q := dbgAdd (l, getType (q)) ;
16895 out1 (": %s>\n", q) ;
16896 INC (i)
16897 END ;
16898 outText (doP, ">\n")
16899 END dbgRecord ;
16903 dbgVarient -
16906 PROCEDURE dbgVarient (l: alist; n: node) ;
16908 i, t: CARDINAL ;
16909 q : node ;
16910 BEGIN
16911 out1 ("<%s varient: ", n) ;
16912 out1 ("tag %s", n^.varientF.tag) ;
16913 q := getType (n^.varientF.tag) ;
16914 IF q=NIL
16915 THEN
16916 outText (doP, "\n")
16917 ELSE
16918 out1 (": %s\n", q) ;
16919 q := dbgAdd (l, q)
16920 END ;
16921 i := LowIndice (n^.varientF.listOfSons) ;
16922 t := HighIndice (n^.varientF.listOfSons) ;
16923 WHILE i<=t DO
16924 q := GetIndice (n^.varientF.listOfSons, i) ;
16925 IF isRecordField (q)
16926 THEN
16927 out1 (" <recordfield %s", q)
16928 ELSIF isVarientField (q)
16929 THEN
16930 out1 (" <varientfield %s", q)
16931 ELSIF isVarient (q)
16932 THEN
16933 out1 (" <varient %s", q)
16934 ELSE
16935 HALT
16936 END ;
16937 q := dbgAdd (l, getType (q)) ;
16938 out1 (": %s>\n", q) ;
16939 INC (i)
16940 END ;
16941 outText (doP, ">\n")
16942 END dbgVarient ;
16946 dbgEnumeration -
16949 PROCEDURE dbgEnumeration (l: alist; n: node) ;
16951 e : node ;
16952 i, h: CARDINAL ;
16953 BEGIN
16954 outText (doP, "< enumeration ") ;
16955 i := LowIndice (n^.enumerationF.listOfSons) ;
16956 h := HighIndice (n^.enumerationF.listOfSons) ;
16957 WHILE i<=h DO
16958 e := GetIndice (n^.enumerationF.listOfSons, i) ;
16959 out1 ("%s, ", e) ;
16960 INC (i)
16961 END ;
16962 outText (doP, ">\n")
16963 END dbgEnumeration ;
16967 dbgVar -
16970 PROCEDURE dbgVar (l: alist; n: node) ;
16972 t: node ;
16973 BEGIN
16974 t := dbgAdd (l, getType (n)) ;
16975 out1 ("<%s var", n) ;
16976 out1 (", type = %s>\n", t)
16977 END dbgVar ;
16981 dbgSubrange -
16984 PROCEDURE dbgSubrange (l: alist; n: node) ;
16985 BEGIN
16986 IF n^.subrangeF.low = NIL
16987 THEN
16988 out1 ('%s', n^.subrangeF.type)
16989 ELSE
16990 out1 ('[%s', n^.subrangeF.low) ;
16991 out1 ('..%s]', n^.subrangeF.high)
16993 END dbgSubrange ;
16997 dbgArray -
17000 PROCEDURE dbgArray (l: alist; n: node) ;
17002 t: node ;
17003 BEGIN
17004 t := dbgAdd (l, getType (n)) ;
17005 out1 ("<%s array ", n) ;
17006 IF n^.arrayF.subr # NIL
17007 THEN
17008 dbgSubrange (l, n^.arrayF.subr)
17009 END ;
17010 out1 (" of %s>\n", t)
17011 END dbgArray ;
17015 doDbg -
17018 PROCEDURE doDbg (l: alist; n: node) ;
17019 BEGIN
17020 IF n=NIL
17021 THEN
17022 (* do nothing. *)
17023 ELSIF isSubrange (n)
17024 THEN
17025 dbgSubrange (l, n)
17026 ELSIF isType (n)
17027 THEN
17028 dbgType (l, n)
17029 ELSIF isRecord (n)
17030 THEN
17031 dbgRecord (l, n)
17032 ELSIF isVarient (n)
17033 THEN
17034 dbgVarient (l, n)
17035 ELSIF isEnumeration (n)
17036 THEN
17037 dbgEnumeration (l, n)
17038 ELSIF isPointer (n)
17039 THEN
17040 dbgPointer (l, n)
17041 ELSIF isArray (n)
17042 THEN
17043 dbgArray (l, n)
17044 ELSIF isVar (n)
17045 THEN
17046 dbgVar (l, n)
17048 END doDbg ;
17052 dbg -
17055 PROCEDURE dbg (listName, symName: ARRAY OF CHAR; n: node) ;
17057 l: alist ;
17058 o: pretty ;
17059 f: File ;
17060 s: String ;
17061 i: CARDINAL ;
17062 BEGIN
17063 o := doP ;
17064 f := outputFile ;
17065 outputFile := StdOut ;
17066 doP := initPretty (write, writeln) ;
17068 l := alists.initList () ;
17069 alists.includeItemIntoList (l, n) ;
17070 i := 1 ;
17071 REPEAT
17072 n := alists.getItemFromList (l, i) ;
17073 IF isType (n)
17074 THEN
17075 s := getFQstring (n) ;
17076 IF EqualArray (s, symName)
17077 THEN
17078 out0 ("list ") ;
17079 out0 (listName) ;
17080 out0 (": ") ;
17081 doDbg (l, n)
17082 END ;
17083 s := KillString (s)
17084 END ;
17085 INC (i)
17086 UNTIL i>alists.noOfItemsInList (l) ;
17087 doP := o ;
17088 outputFile := f
17089 END dbg ;
17093 makeStatementSequence - create and return a statement sequence node.
17096 PROCEDURE makeStatementSequence () : node ;
17098 n: node ;
17099 BEGIN
17100 n := newNode (stmtseq) ;
17101 n^.stmtF.statements := InitIndex (1) ;
17102 RETURN n
17103 END makeStatementSequence ;
17107 addStatement - adds node, n, as a statement to statememt sequence, s.
17110 PROCEDURE addStatement (s: node; n: node) ;
17111 BEGIN
17112 IF n#NIL
17113 THEN
17114 assert (isStatementSequence (s)) ;
17115 PutIndice (s^.stmtF.statements, HighIndice (s^.stmtF.statements) + 1, n) ;
17116 IF isIntrinsic (n) AND (n^.intrinsicF.postUnreachable)
17117 THEN
17118 n^.intrinsicF.postUnreachable := FALSE ;
17119 addStatement (s, makeIntrinsicProc (unreachable, 0, NIL))
17122 END addStatement ;
17126 isStatementSequence - returns TRUE if node, n, is a statement sequence.
17129 PROCEDURE isStatementSequence (n: node) : BOOLEAN ;
17130 BEGIN
17131 RETURN n^.kind = stmtseq
17132 END isStatementSequence ;
17136 addGenericBody - adds comment node to funccall, return, assignment
17137 nodes.
17140 PROCEDURE addGenericBody (n, c: node);
17141 BEGIN
17142 CASE n^.kind OF
17144 unreachable,
17145 throw,
17146 halt,
17147 new,
17148 dispose,
17149 inc,
17150 dec,
17151 incl,
17152 excl : n^.intrinsicF.intrinsicComment.body := c |
17153 funccall : n^.funccallF.funccallComment.body := c |
17154 return : n^.returnF.returnComment.body := c |
17155 assignment: n^.assignmentF.assignComment.body := c |
17156 module : n^.moduleF.com.body := c |
17157 def : n^.defF.com.body := c |
17158 imp : n^.impF.com.body := c
17160 ELSE
17162 END addGenericBody;
17166 addGenericAfter - adds comment node to funccall, return, assignment
17167 nodes.
17170 PROCEDURE addGenericAfter (n, c: node);
17171 BEGIN
17172 CASE n^.kind OF
17174 unreachable,
17175 throw,
17176 halt,
17177 new,
17178 dispose,
17179 inc,
17180 dec,
17181 incl,
17182 excl : n^.intrinsicF.intrinsicComment.after := c |
17183 funccall : n^.funccallF.funccallComment.after := c |
17184 return : n^.returnF.returnComment.after := c |
17185 assignment: n^.assignmentF.assignComment.after := c |
17186 module : n^.moduleF.com.after := c |
17187 def : n^.defF.com.after := c |
17188 imp : n^.impF.com.after := c
17190 ELSE
17192 END addGenericAfter ;
17196 addCommentBody - adds a body comment to a statement sequence node.
17199 PROCEDURE addCommentBody (n: node) ;
17201 b: commentDesc ;
17202 BEGIN
17203 IF n # NIL
17204 THEN
17205 b := getBodyComment () ;
17206 IF b # NIL
17207 THEN
17208 addGenericBody (n, makeCommentS (b))
17211 END addCommentBody ;
17215 addCommentAfter - adds an after comment to a statement sequence node.
17218 PROCEDURE addCommentAfter (n: node) ;
17220 a: commentDesc ;
17221 BEGIN
17222 IF n # NIL
17223 THEN
17224 a := getAfterComment () ;
17225 IF a # NIL
17226 THEN
17227 addGenericAfter (n, makeCommentS (a))
17230 END addCommentAfter ;
17234 addIfComments - adds the, body, and, after, comments to if node, n.
17237 PROCEDURE addIfComments (n: node; body, after: node) ;
17238 BEGIN
17239 assert (isIf (n)) ;
17240 n^.ifF.ifComment.after := after ;
17241 n^.ifF.ifComment.body := body
17242 END addIfComments ;
17246 addElseComments - adds the, body, and, after, comments to an, if, or an elsif, node, n.
17249 PROCEDURE addElseComments (n: node; body, after: node) ;
17250 BEGIN
17251 assert (isIf (n) OR isElsif (n)) ;
17252 IF isIf (n)
17253 THEN
17254 n^.ifF.elseComment.after := after ;
17255 n^.ifF.elseComment.body := body
17256 ELSE
17257 n^.elsifF.elseComment.after := after ;
17258 n^.elsifF.elseComment.body := body
17260 END addElseComments ;
17264 addIfEndComments - adds the, body, and, after, comments to an, if, node, n.
17267 PROCEDURE addIfEndComments (n: node; body, after: node) ;
17268 BEGIN
17269 assert (isIf (n)) ;
17270 n^.ifF.endComment.after := after ;
17271 n^.ifF.endComment.body := body
17272 END addIfEndComments ;
17276 makeReturn - creates and returns a return node.
17279 PROCEDURE makeReturn () : node ;
17281 type,
17282 n : node ;
17283 BEGIN
17284 n := newNode (return) ;
17285 n^.returnF.exp := NIL ;
17286 IF isProcedure (getDeclScope ())
17287 THEN
17288 n^.returnF.scope := getDeclScope ()
17289 ELSE
17290 n^.returnF.scope := NIL
17291 END ;
17292 initPair (n^.returnF.returnComment) ;
17293 RETURN n
17294 END makeReturn ;
17298 isReturn - returns TRUE if node, n, is a return.
17301 PROCEDURE isReturn (n: node) : BOOLEAN ;
17302 BEGIN
17303 assert (n # NIL) ;
17304 RETURN n^.kind = return
17305 END isReturn ;
17309 putReturn - assigns node, e, as the expression on the return node.
17312 PROCEDURE putReturn (n: node; e: node) ;
17313 BEGIN
17314 assert (isReturn (n)) ;
17315 n^.returnF.exp := e
17316 END putReturn ;
17320 makeWhile - creates and returns a while node.
17323 PROCEDURE makeWhile () : node ;
17325 n: node ;
17326 BEGIN
17327 n := newNode (while) ;
17328 n^.whileF.expr := NIL ;
17329 n^.whileF.statements := NIL ;
17330 initPair (n^.whileF.doComment) ;
17331 initPair (n^.whileF.endComment) ;
17332 RETURN n
17333 END makeWhile ;
17337 putWhile - places an expression, e, and statement sequence, s, into the while
17338 node, n.
17341 PROCEDURE putWhile (n: node; e, s: node) ;
17342 BEGIN
17343 assert (isWhile (n)) ;
17344 n^.whileF.expr := e ;
17345 n^.whileF.statements := s
17346 END putWhile ;
17350 isWhile - returns TRUE if node, n, is a while.
17353 PROCEDURE isWhile (n: node) : BOOLEAN ;
17354 BEGIN
17355 RETURN n^.kind = while
17356 END isWhile ;
17360 addWhileDoComment - adds body and after comments to while node, w.
17363 PROCEDURE addWhileDoComment (w: node; body, after: node) ;
17364 BEGIN
17365 assert (isWhile (w)) ;
17366 w^.whileF.doComment.after := after ;
17367 w^.whileF.doComment.body := body
17368 END addWhileDoComment ;
17372 addWhileEndComment - adds body and after comments to the end of a while node, w.
17375 PROCEDURE addWhileEndComment (w: node; body, after: node) ;
17376 BEGIN
17377 assert (isWhile (w)) ;
17378 w^.whileF.endComment.after := after ;
17379 w^.whileF.endComment.body := body
17380 END addWhileEndComment ;
17384 makeAssignment - creates and returns an assignment node.
17385 The designator is, d, and expression, e.
17388 PROCEDURE makeAssignment (d, e: node) : node ;
17390 n: node ;
17391 BEGIN
17392 n := newNode (assignment) ;
17393 n^.assignmentF.des := d ;
17394 n^.assignmentF.expr := e ;
17395 initPair (n^.assignmentF.assignComment) ;
17396 RETURN n
17397 END makeAssignment ;
17401 isAssignment -
17404 PROCEDURE isAssignment (n: node) : BOOLEAN ;
17405 BEGIN
17406 RETURN n^.kind = assignment
17407 END isAssignment ;
17411 putBegin - assigns statements, s, to be the normal part in
17412 block, b. The block may be a procedure or module,
17413 or implementation node.
17416 PROCEDURE putBegin (b: node; s: node) ;
17417 BEGIN
17418 assert (isImp (b) OR isProcedure (b) OR isModule (b)) ;
17419 CASE b^.kind OF
17421 imp : b^.impF.beginStatements := s |
17422 module : b^.moduleF.beginStatements := s |
17423 procedure: b^.procedureF.beginStatements := s
17426 END putBegin ;
17430 putFinally - assigns statements, s, to be the final part in
17431 block, b. The block may be a module
17432 or implementation node.
17435 PROCEDURE putFinally (b: node; s: node) ;
17436 BEGIN
17437 assert (isImp (b) OR isProcedure (b) OR isModule (b)) ;
17438 CASE b^.kind OF
17440 imp : b^.impF.finallyStatements := s |
17441 module : b^.moduleF.finallyStatements := s
17444 END putFinally ;
17448 makeExit - creates and returns an exit node.
17451 PROCEDURE makeExit (l: node; n: CARDINAL) : node ;
17453 e: node ;
17454 BEGIN
17455 assert (isLoop (l)) ;
17456 e := newNode (exit) ;
17457 e^.exitF.loop := l ;
17458 l^.loopF.labelno := n ;
17459 RETURN e
17460 END makeExit ;
17464 isExit - returns TRUE if node, n, is an exit.
17467 PROCEDURE isExit (n: node) : BOOLEAN ;
17468 BEGIN
17469 assert (n # NIL) ;
17470 RETURN n^.kind = exit
17471 END isExit ;
17475 makeLoop - creates and returns a loop node.
17478 PROCEDURE makeLoop () : node ;
17480 l: node ;
17481 BEGIN
17482 l := newNode (loop) ;
17483 l^.loopF.statements := NIL ;
17484 l^.loopF.labelno := 0 ;
17485 RETURN l
17486 END makeLoop ;
17490 putLoop - places statement sequence, s, into loop, l.
17493 PROCEDURE putLoop (l, s: node) ;
17494 BEGIN
17495 assert (isLoop (l)) ;
17496 l^.loopF.statements := s
17497 END putLoop ;
17501 isLoop - returns TRUE if, n, is a loop node.
17504 PROCEDURE isLoop (n: node) : BOOLEAN ;
17505 BEGIN
17506 assert (n # NIL) ;
17507 RETURN n^.kind = loop
17508 END isLoop ;
17512 makeComment - creates and returns a comment node.
17515 PROCEDURE makeComment (a: ARRAY OF CHAR) : node ;
17517 c: commentDesc ;
17518 s: String ;
17519 BEGIN
17520 c := initComment (TRUE) ;
17521 s := InitString (a) ;
17522 addText (c, DynamicStrings.string (s)) ;
17523 s := KillString (s) ;
17524 RETURN makeCommentS (c)
17525 END makeComment ;
17529 makeCommentS - creates and returns a comment node.
17532 PROCEDURE makeCommentS (c: commentDesc) : node ;
17534 n: node ;
17535 BEGIN
17536 IF c = NIL
17537 THEN
17538 RETURN NIL
17539 ELSE
17540 n := newNode (comment) ;
17541 n^.commentF.content := c ;
17542 RETURN n
17544 END makeCommentS ;
17548 isComment - returns TRUE if node, n, is a comment.
17551 PROCEDURE isComment (n: node) : BOOLEAN ;
17552 BEGIN
17553 assert (n # NIL) ;
17554 RETURN n^.kind = comment
17555 END isComment ;
17559 initPair - initialise the commentPair, c.
17562 PROCEDURE initPair (VAR c: commentPair) ;
17563 BEGIN
17564 c.after := NIL ;
17565 c.body := NIL
17566 END initPair ;
17570 makeIf - creates and returns an if node. The if node
17571 will have expression, e, and statement sequence, s,
17572 as the then component.
17575 PROCEDURE makeIf (e, s: node) : node ;
17577 n: node ;
17578 BEGIN
17579 n := newNode (if) ;
17580 n^.ifF.expr := e ;
17581 n^.ifF.then := s ;
17582 n^.ifF.else := NIL ;
17583 n^.ifF.elsif := NIL ;
17584 initPair (n^.ifF.ifComment) ;
17585 initPair (n^.ifF.elseComment) ;
17586 initPair (n^.ifF.endComment) ;
17587 RETURN n
17588 END makeIf ;
17592 isIf - returns TRUE if, n, is an if node.
17595 PROCEDURE isIf (n: node) : BOOLEAN ;
17596 BEGIN
17597 RETURN n^.kind = if
17598 END isIf ;
17602 makeElsif - creates and returns an elsif node.
17603 This node has an expression, e, and statement
17604 sequence, s.
17607 PROCEDURE makeElsif (i, e, s: node) : node ;
17609 n: node ;
17610 BEGIN
17611 n := newNode (elsif) ;
17612 n^.elsifF.expr := e ;
17613 n^.elsifF.then := s ;
17614 n^.elsifF.elsif := NIL ;
17615 n^.elsifF.else := NIL ;
17616 initPair (n^.elsifF.elseComment) ;
17617 assert (isIf (i) OR isElsif (i)) ;
17618 IF isIf (i)
17619 THEN
17620 i^.ifF.elsif := n ;
17621 assert (i^.ifF.else = NIL)
17622 ELSE
17623 i^.elsifF.elsif := n ;
17624 assert (i^.elsifF.else = NIL)
17625 END ;
17626 RETURN n
17627 END makeElsif ;
17631 isElsif - returns TRUE if node, n, is an elsif node.
17634 PROCEDURE isElsif (n: node) : BOOLEAN ;
17635 BEGIN
17636 RETURN n^.kind = elsif
17637 END isElsif ;
17641 putElse - the else is grafted onto the if/elsif node, i,
17642 and the statement sequence will be, s.
17645 PROCEDURE putElse (i, s: node) ;
17646 BEGIN
17647 assert (isIf (i) OR isElsif (i)) ;
17648 IF isIf (i)
17649 THEN
17650 assert (i^.ifF.elsif = NIL) ;
17651 assert (i^.ifF.else = NIL) ;
17652 i^.ifF.else := s
17653 ELSE
17654 assert (i^.elsifF.elsif = NIL) ;
17655 assert (i^.elsifF.else = NIL) ;
17656 i^.elsifF.else := s
17658 END putElse ;
17662 makeFor - creates and returns a for node.
17665 PROCEDURE makeFor () : node ;
17667 n: node ;
17668 BEGIN
17669 n := newNode (for) ;
17670 n^.forF.des := NIL ;
17671 n^.forF.start := NIL ;
17672 n^.forF.end := NIL ;
17673 n^.forF.increment := NIL ;
17674 n^.forF.statements := NIL ;
17675 RETURN n
17676 END makeFor ;
17680 isFor - returns TRUE if node, n, is a for node.
17683 PROCEDURE isFor (n: node) : BOOLEAN ;
17684 BEGIN
17685 assert (n # NIL) ;
17686 RETURN n^.kind = for
17687 END isFor ;
17691 putFor - assigns the fields of the for node with
17692 ident, i,
17693 start, s,
17694 end, e,
17695 increment, i,
17696 statements, sq.
17699 PROCEDURE putFor (f, i, s, e, b, sq: node) ;
17700 BEGIN
17701 assert (isFor (f)) ;
17702 f^.forF.des := i ;
17703 f^.forF.start := s ;
17704 f^.forF.end := e ;
17705 f^.forF.increment := b ;
17706 f^.forF.statements := sq
17707 END putFor ;
17711 makeRepeat - creates and returns a repeat node.
17714 PROCEDURE makeRepeat () : node ;
17716 n: node ;
17717 BEGIN
17718 n := newNode (repeat) ;
17719 n^.repeatF.expr := NIL ;
17720 n^.repeatF.statements := NIL ;
17721 initPair (n^.repeatF.repeatComment) ;
17722 initPair (n^.repeatF.untilComment) ;
17723 RETURN n
17724 END makeRepeat ;
17728 isRepeat - returns TRUE if node, n, is a repeat node.
17731 PROCEDURE isRepeat (n: node) : BOOLEAN ;
17732 BEGIN
17733 assert (n # NIL) ;
17734 RETURN n^.kind = repeat
17735 END isRepeat ;
17739 putRepeat - places statements, s, and expression, e, into
17740 repeat statement, n.
17743 PROCEDURE putRepeat (n, s, e: node) ;
17744 BEGIN
17745 n^.repeatF.expr := e ;
17746 n^.repeatF.statements := s
17747 END putRepeat ;
17751 addRepeatComment - adds body and after comments to repeat node, r.
17754 PROCEDURE addRepeatComment (r: node; body, after: node) ;
17755 BEGIN
17756 assert (isRepeat (r)) ;
17757 r^.repeatF.repeatComment.after := after ;
17758 r^.repeatF.repeatComment.body := body
17759 END addRepeatComment ;
17763 addUntilComment - adds body and after comments to the until section of a repeat node, r.
17766 PROCEDURE addUntilComment (r: node; body, after: node) ;
17767 BEGIN
17768 assert (isRepeat (r)) ;
17769 r^.repeatF.untilComment.after := after ;
17770 r^.repeatF.untilComment.body := body
17771 END addUntilComment ;
17775 makeCase - builds and returns a case statement node.
17778 PROCEDURE makeCase () : node ;
17780 n: node ;
17781 BEGIN
17782 n := newNode (case) ;
17783 n^.caseF.expression := NIL ;
17784 n^.caseF.caseLabelList := InitIndex (1) ;
17785 n^.caseF.else := NIL ;
17786 RETURN n
17787 END makeCase ;
17791 isCase - returns TRUE if node, n, is a case statement.
17794 PROCEDURE isCase (n: node) : BOOLEAN ;
17795 BEGIN
17796 assert (n # NIL) ;
17797 RETURN n^.kind = case
17798 END isCase ;
17802 putCaseExpression - places expression, e, into case statement, n.
17803 n is returned.
17806 PROCEDURE putCaseExpression (n: node; e: node) : node ;
17807 BEGIN
17808 assert (isCase (n)) ;
17809 n^.caseF.expression := e ;
17810 RETURN n
17811 END putCaseExpression ;
17815 putCaseElse - places else statement, e, into case statement, n.
17816 n is returned.
17819 PROCEDURE putCaseElse (n: node; e: node) : node ;
17820 BEGIN
17821 assert (isCase (n)) ;
17822 n^.caseF.else := e ;
17823 RETURN n
17824 END putCaseElse ;
17828 putCaseStatement - places a caselist, l, and associated
17829 statement sequence, s, into case statement, n.
17830 n is returned.
17833 PROCEDURE putCaseStatement (n: node; l: node; s: node) : node ;
17834 BEGIN
17835 assert (isCase (n)) ;
17836 assert (isCaseList (l)) ;
17837 IncludeIndiceIntoIndex (n^.caseF.caseLabelList, makeCaseLabelList (l, s)) ;
17838 RETURN n
17839 END putCaseStatement ;
17843 makeCaseLabelList - creates and returns a caselabellist node.
17846 PROCEDURE makeCaseLabelList (l, s: node) : node ;
17848 n: node ;
17849 BEGIN
17850 n := newNode (caselabellist) ;
17851 n^.caselabellistF.caseList := l ;
17852 n^.caselabellistF.statements := s ;
17853 RETURN n
17854 END makeCaseLabelList ;
17858 isCaseLabelList - returns TRUE if, n, is a caselabellist.
17861 PROCEDURE isCaseLabelList (n: node) : BOOLEAN ;
17862 BEGIN
17863 assert (n # NIL) ;
17864 RETURN n^.kind = caselabellist
17865 END isCaseLabelList ;
17869 makeCaseList - creates and returns a case statement node.
17872 PROCEDURE makeCaseList () : node ;
17874 n: node ;
17875 BEGIN
17876 n := newNode (caselist) ;
17877 n^.caselistF.rangePairs := InitIndex (1) ;
17878 RETURN n
17879 END makeCaseList ;
17883 isCaseList - returns TRUE if, n, is a case list.
17886 PROCEDURE isCaseList (n: node) : BOOLEAN ;
17887 BEGIN
17888 assert (n # NIL) ;
17889 RETURN n^.kind = caselist
17890 END isCaseList ;
17894 putCaseRange - places the case range lo..hi into caselist, n.
17897 PROCEDURE putCaseRange (n: node; lo, hi: node) : node ;
17898 BEGIN
17899 assert (isCaseList (n)) ;
17900 IncludeIndiceIntoIndex (n^.caselistF.rangePairs, makeRange (lo, hi)) ;
17901 RETURN n
17902 END putCaseRange ;
17906 makeRange - creates and returns a case range.
17909 PROCEDURE makeRange (lo, hi: node) : node ;
17911 n: node ;
17912 BEGIN
17913 n := newNode (range) ;
17914 n^.rangeF.lo := lo ;
17915 n^.rangeF.hi := hi ;
17916 RETURN n
17917 END makeRange ;
17921 isRange - returns TRUE if node, n, is a range.
17924 PROCEDURE isRange (n: node) : BOOLEAN ;
17925 BEGIN
17926 assert (n # NIL) ;
17927 RETURN n^.kind = range
17928 END isRange ;
17932 dupExplist -
17935 PROCEDURE dupExplist (n: node) : node ;
17937 m: node ;
17938 i: CARDINAL ;
17939 BEGIN
17940 assert (isExpList (n)) ;
17941 m := makeExpList () ;
17942 i := LowIndice (n^.explistF.exp) ;
17943 WHILE i <= HighIndice (n^.explistF.exp) DO
17944 putExpList (m, dupExpr (GetIndice (n^.explistF.exp, i))) ;
17945 INC (i)
17946 END ;
17947 RETURN m
17948 END dupExplist ;
17952 dupArrayref -
17955 PROCEDURE dupArrayref (n: node) : node ;
17956 BEGIN
17957 assert (isArrayRef (n)) ;
17958 RETURN makeArrayRef (dupExpr (n^.arrayrefF.array), dupExpr (n^.arrayrefF.index))
17959 END dupArrayref ;
17963 dupPointerref -
17966 PROCEDURE dupPointerref (n: node) : node ;
17967 BEGIN
17968 assert (isPointerRef (n)) ;
17969 RETURN makePointerRef (dupExpr (n^.pointerrefF.ptr), dupExpr (n^.pointerrefF.field))
17970 END dupPointerref ;
17974 dupComponentref -
17977 PROCEDURE dupComponentref (n: node) : node ;
17978 BEGIN
17979 assert (isComponentRef (n)) ;
17980 RETURN doMakeComponentRef (dupExpr (n^.componentrefF.rec), dupExpr (n^.componentrefF.field))
17981 END dupComponentref ;
17985 dupBinary -
17988 PROCEDURE dupBinary (n: node) : node ;
17989 BEGIN
17990 (* assert (isBinary (n)) ; *)
17991 RETURN makeBinary (n^.kind,
17992 dupExpr (n^.binaryF.left), dupExpr (n^.binaryF.right),
17993 n^.binaryF.resultType)
17994 END dupBinary ;
17998 dupUnary -
18001 PROCEDURE dupUnary (n: node) : node ;
18002 BEGIN
18003 (* assert (isUnary (n)) ; *)
18004 RETURN makeUnary (n^.kind, dupExpr (n^.unaryF.arg), n^.unaryF.resultType)
18005 END dupUnary ;
18009 dupFunccall -
18012 PROCEDURE dupFunccall (n: node) : node ;
18014 m: node ;
18015 BEGIN
18016 assert (isFuncCall (n)) ;
18017 m := makeFuncCall (dupExpr (n^.funccallF.function), dupExpr (n^.funccallF.args)) ;
18018 m^.funccallF.type := n^.funccallF.type ;
18019 assignNodeOpaqueCastState (m, n) ;
18020 RETURN m
18021 END dupFunccall ;
18025 dupSetValue -
18028 PROCEDURE dupSetValue (n: node) : node ;
18030 m: node ;
18031 i: CARDINAL ;
18032 BEGIN
18033 m := newNode (setvalue) ;
18034 m^.setvalueF.type := n^.setvalueF.type ;
18035 i := LowIndice (n^.setvalueF.values) ;
18036 WHILE i <= HighIndice (n^.setvalueF.values) DO
18037 m := putSetValue (m, dupExpr (GetIndice (n^.setvalueF.values, i))) ;
18038 INC (i)
18039 END ;
18040 RETURN m
18041 END dupSetValue ;
18045 dupExpr - duplicate the expression nodes, it does not duplicate
18046 variables, literals, constants but only the expression
18047 operators (including function calls and parameter lists).
18050 PROCEDURE dupExpr (n: node) : node ;
18051 BEGIN
18052 IF n = NIL
18053 THEN
18054 RETURN NIL
18055 ELSE
18056 RETURN doDupExpr (n)
18058 END dupExpr ;
18062 doDupExpr -
18065 PROCEDURE doDupExpr (n: node) : node ;
18066 BEGIN
18067 assert (n # NIL) ;
18068 CASE n^.kind OF
18070 explist : RETURN dupExplist (n) |
18071 exit,
18072 return,
18073 stmtseq,
18074 comment : HALT | (* should not be duplicating code. *)
18075 length : HALT | (* length should have been converted into unary. *)
18076 (* base constants. *)
18077 nil,
18078 true,
18079 false,
18080 (* system types. *)
18081 address,
18082 loc,
18083 byte,
18084 word,
18085 csizet,
18086 cssizet,
18087 (* base types. *)
18088 boolean,
18089 proc,
18090 char,
18091 integer,
18092 cardinal,
18093 longcard,
18094 shortcard,
18095 longint,
18096 shortint,
18097 real,
18098 longreal,
18099 shortreal,
18100 bitset,
18101 ztype,
18102 rtype,
18103 complex,
18104 longcomplex,
18105 shortcomplex : RETURN n |
18106 (* language features and compound type attributes. *)
18107 type,
18108 record,
18109 varient,
18110 var,
18111 enumeration,
18112 subrange,
18113 subscript,
18114 array,
18115 string,
18116 const,
18117 literal,
18118 varparam,
18119 param,
18120 varargs,
18121 optarg,
18122 pointer,
18123 recordfield,
18124 varientfield,
18125 enumerationfield,
18126 set,
18127 proctype : RETURN n |
18128 (* blocks. *)
18129 procedure,
18130 def,
18131 imp,
18132 module : RETURN n |
18133 (* statements. *)
18134 loop,
18135 while,
18136 for,
18137 repeat,
18138 case,
18139 caselabellist,
18140 caselist,
18141 range,
18143 elsif,
18144 assignment : RETURN n |
18145 (* expressions. *)
18146 arrayref : RETURN dupArrayref (n) |
18147 pointerref : RETURN dupPointerref (n) |
18148 componentref : RETURN dupComponentref (n) |
18149 cmplx,
18150 and,
18152 equal,
18153 notequal,
18154 less,
18155 greater,
18156 greequal,
18157 lessequal,
18158 cast,
18159 val,
18160 plus,
18161 sub,
18162 div,
18163 mod,
18164 mult,
18165 divide,
18166 in : RETURN dupBinary (n) |
18169 constexp,
18170 deref,
18171 abs,
18172 chr,
18173 cap,
18174 high,
18175 float,
18176 trunc,
18177 ord,
18178 not,
18179 neg,
18180 adr,
18181 size,
18182 tsize,
18183 min,
18184 max : RETURN dupUnary (n) |
18185 identlist : RETURN n |
18186 vardecl : RETURN n |
18187 funccall : RETURN dupFunccall (n) |
18188 setvalue : RETURN dupSetValue (n)
18191 END doDupExpr ;
18195 setNoReturn - sets noreturn field inside procedure.
18198 PROCEDURE setNoReturn (n: node; value: BOOLEAN) ;
18199 BEGIN
18200 assert (n#NIL) ;
18201 assert (isProcedure (n)) ;
18202 IF n^.procedureF.noreturnused AND (n^.procedureF.noreturn # value)
18203 THEN
18204 metaError1 ('{%1DMad} definition module and implementation module have different <* noreturn *> attributes', n) ;
18205 END ;
18206 n^.procedureF.noreturn := value ;
18207 n^.procedureF.noreturnused := TRUE
18208 END setNoReturn ;
18212 makeSystem -
18215 PROCEDURE makeSystem ;
18216 BEGIN
18217 systemN := lookupDef (makeKey ('SYSTEM')) ;
18219 addressN := makeBase (address) ;
18220 locN := makeBase (loc) ;
18221 byteN := makeBase (byte) ;
18222 wordN := makeBase (word) ;
18223 csizetN := makeBase (csizet) ;
18224 cssizetN := makeBase (cssizet) ;
18226 adrN := makeBase (adr) ;
18227 tsizeN := makeBase (tsize) ;
18228 throwN := makeBase (throw) ;
18230 enterScope (systemN) ;
18231 addressN := addToScope (addressN) ;
18232 locN := addToScope (locN) ;
18233 byteN := addToScope (byteN) ;
18234 wordN := addToScope (wordN) ;
18235 csizetN := addToScope (csizetN) ;
18236 cssizetN := addToScope (cssizetN) ;
18237 adrN := addToScope (adrN) ;
18238 tsizeN := addToScope (tsizeN) ;
18239 throwN := addToScope (throwN) ;
18241 assert (sizeN#NIL) ; (* assumed to be built already. *)
18242 sizeN := addToScope (sizeN) ; (* also export size from system. *)
18243 leaveScope ;
18245 addDone (addressN) ;
18246 addDone (locN) ;
18247 addDone (byteN) ;
18248 addDone (wordN) ;
18249 addDone (csizetN) ;
18250 addDone (cssizetN)
18251 END makeSystem ;
18255 makeM2rts -
18258 PROCEDURE makeM2rts ;
18259 BEGIN
18260 m2rtsN := lookupDef (makeKey ('M2RTS'))
18261 END makeM2rts ;
18265 makeBitnum -
18268 PROCEDURE makeBitnum () : node ;
18270 b: node ;
18271 BEGIN
18272 b := newNode (subrange) ;
18273 b^.subrangeF.type := NIL ;
18274 b^.subrangeF.scope := NIL ;
18275 b^.subrangeF.low := lookupConst (b, makeKey ('0')) ;
18276 b^.subrangeF.high := lookupConst (b, makeKey ('31')) ;
18277 RETURN b
18278 END makeBitnum ;
18282 makeBaseSymbols -
18285 PROCEDURE makeBaseSymbols ;
18286 BEGIN
18287 baseSymbols := initTree () ;
18289 booleanN := makeBase (boolean) ;
18290 charN := makeBase (char) ;
18291 procN := makeBase (proc) ;
18292 cardinalN := makeBase (cardinal) ;
18293 longcardN := makeBase (longcard) ;
18294 shortcardN := makeBase (shortcard) ;
18295 integerN := makeBase (integer) ;
18296 longintN := makeBase (longint) ;
18297 shortintN := makeBase (shortint) ;
18298 bitsetN := makeBase (bitset) ;
18299 bitnumN := makeBitnum () ;
18300 ztypeN := makeBase (ztype) ;
18301 rtypeN := makeBase (rtype) ;
18302 complexN := makeBase (complex) ;
18303 longcomplexN := makeBase (longcomplex) ;
18304 shortcomplexN := makeBase (shortcomplex) ;
18305 realN := makeBase (real) ;
18306 longrealN := makeBase (longreal) ;
18307 shortrealN := makeBase (shortreal) ;
18309 nilN := makeBase (nil) ;
18310 trueN := makeBase (true) ;
18311 falseN := makeBase (false) ;
18313 sizeN := makeBase (size) ;
18314 minN := makeBase (min) ;
18315 maxN := makeBase (max) ;
18316 floatN := makeBase (float) ;
18317 truncN := makeBase (trunc) ;
18318 ordN := makeBase (ord) ;
18319 valN := makeBase (val) ;
18320 chrN := makeBase (chr) ;
18321 capN := makeBase (cap) ;
18322 absN := makeBase (abs) ;
18323 newN := makeBase (new) ;
18324 disposeN := makeBase (dispose) ;
18325 lengthN := makeBase (length) ;
18326 incN := makeBase (inc) ;
18327 decN := makeBase (dec) ;
18328 inclN := makeBase (incl) ;
18329 exclN := makeBase (excl) ;
18330 highN := makeBase (high) ;
18331 imN := makeBase (im) ;
18332 reN := makeBase (re) ;
18333 cmplxN := makeBase (cmplx) ;
18335 putSymKey (baseSymbols, makeKey ('BOOLEAN'), booleanN) ;
18336 putSymKey (baseSymbols, makeKey ('PROC'), procN) ;
18337 putSymKey (baseSymbols, makeKey ('CHAR'), charN) ;
18338 putSymKey (baseSymbols, makeKey ('CARDINAL'), cardinalN) ;
18339 putSymKey (baseSymbols, makeKey ('SHORTCARD'), shortcardN) ;
18340 putSymKey (baseSymbols, makeKey ('LONGCARD'), longcardN) ;
18341 putSymKey (baseSymbols, makeKey ('INTEGER'), integerN) ;
18342 putSymKey (baseSymbols, makeKey ('LONGINT'), longintN) ;
18343 putSymKey (baseSymbols, makeKey ('SHORTINT'), shortintN) ;
18344 putSymKey (baseSymbols, makeKey ('BITSET'), bitsetN) ;
18345 putSymKey (baseSymbols, makeKey ('REAL'), realN) ;
18346 putSymKey (baseSymbols, makeKey ('SHORTREAL'), shortrealN) ;
18347 putSymKey (baseSymbols, makeKey ('LONGREAL'), longrealN) ;
18348 putSymKey (baseSymbols, makeKey ('COMPLEX'), complexN) ;
18349 putSymKey (baseSymbols, makeKey ('LONGCOMPLEX'), longcomplexN) ;
18350 putSymKey (baseSymbols, makeKey ('SHORTCOMPLEX'), shortcomplexN) ;
18352 putSymKey (baseSymbols, makeKey ('NIL'), nilN) ;
18353 putSymKey (baseSymbols, makeKey ('TRUE'), trueN) ;
18354 putSymKey (baseSymbols, makeKey ('FALSE'), falseN) ;
18355 putSymKey (baseSymbols, makeKey ('SIZE'), sizeN) ;
18356 putSymKey (baseSymbols, makeKey ('MIN'), minN) ;
18357 putSymKey (baseSymbols, makeKey ('MAX'), maxN) ;
18358 putSymKey (baseSymbols, makeKey ('FLOAT'), floatN) ;
18359 putSymKey (baseSymbols, makeKey ('TRUNC'), truncN) ;
18360 putSymKey (baseSymbols, makeKey ('ORD'), ordN) ;
18361 putSymKey (baseSymbols, makeKey ('VAL'), valN) ;
18362 putSymKey (baseSymbols, makeKey ('CHR'), chrN) ;
18363 putSymKey (baseSymbols, makeKey ('CAP'), capN) ;
18364 putSymKey (baseSymbols, makeKey ('ABS'), absN) ;
18365 putSymKey (baseSymbols, makeKey ('NEW'), newN) ;
18366 putSymKey (baseSymbols, makeKey ('DISPOSE'), disposeN) ;
18367 putSymKey (baseSymbols, makeKey ('LENGTH'), lengthN) ;
18368 putSymKey (baseSymbols, makeKey ('INC'), incN) ;
18369 putSymKey (baseSymbols, makeKey ('DEC'), decN) ;
18370 putSymKey (baseSymbols, makeKey ('INCL'), inclN) ;
18371 putSymKey (baseSymbols, makeKey ('EXCL'), exclN) ;
18372 putSymKey (baseSymbols, makeKey ('HIGH'), highN) ;
18373 putSymKey (baseSymbols, makeKey ('CMPLX'), cmplxN) ;
18374 putSymKey (baseSymbols, makeKey ('RE'), reN) ;
18375 putSymKey (baseSymbols, makeKey ('IM'), imN) ;
18377 addDone (booleanN) ;
18378 addDone (charN) ;
18379 addDone (cardinalN) ;
18380 addDone (longcardN) ;
18381 addDone (shortcardN) ;
18382 addDone (integerN) ;
18383 addDone (longintN) ;
18384 addDone (shortintN) ;
18385 addDone (bitsetN) ;
18386 addDone (bitnumN) ;
18387 addDone (ztypeN) ;
18388 addDone (rtypeN) ;
18389 addDone (realN) ;
18390 addDone (longrealN) ;
18391 addDone (shortrealN) ;
18392 addDone (complexN) ;
18393 addDone (longcomplexN) ;
18394 addDone (shortcomplexN) ;
18395 addDone (procN) ;
18396 addDone (nilN) ;
18397 addDone (trueN) ;
18398 addDone (falseN)
18400 END makeBaseSymbols ;
18404 makeBuiltins -
18407 PROCEDURE makeBuiltins ;
18408 BEGIN
18409 bitsperunitN := makeLiteralInt (makeKey ('8')) ;
18410 bitsperwordN := makeLiteralInt (makeKey ('32')) ;
18411 bitspercharN := makeLiteralInt (makeKey ('8')) ;
18412 unitsperwordN := makeLiteralInt (makeKey ('4')) ;
18414 addDone (bitsperunitN) ;
18415 addDone (bitsperwordN) ;
18416 addDone (bitspercharN) ;
18417 addDone (unitsperwordN)
18418 END makeBuiltins ;
18422 makeCDataTypes - assign the charStarN and constCharStarN to NIL.
18425 PROCEDURE makeCDataTypes ;
18427 CdatatypesN: node ;
18428 BEGIN
18429 CdatatypesN := lookupDef (makeKey ('CDataTypes')) ;
18430 enterScope (CdatatypesN) ;
18431 charStarN := makePointer (charN) ;
18432 constCharStarN := makePointer (charN) ;
18433 leaveScope
18434 END makeCDataTypes ;
18438 init -
18441 PROCEDURE init ;
18442 BEGIN
18443 lang := ansiC ;
18444 outputFile := StdOut ;
18445 doP := initPretty (write, writeln) ;
18446 freeGroup := NIL ;
18447 globalGroup := initGroup () ;
18448 modUniverse := initTree () ;
18449 defUniverse := initTree () ;
18450 modUniverseI := InitIndex (1) ;
18451 defUniverseI := InitIndex (1) ;
18452 scopeStack := InitIndex (1) ;
18453 makeBaseSymbols ;
18454 makeSystem ;
18455 makeBuiltins ;
18456 makeM2rts ;
18457 outputState := punct ;
18458 tempCount := 0 ;
18459 mustVisitScope := FALSE ;
18460 makeCDataTypes
18461 END init ;
18464 BEGIN
18465 init
18466 END decl.