FoxBinarySymbolFile.Mod 87 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484
  1. MODULE FoxBinarySymbolFile; (** AUTHOR "fof"; PURPOSE "Symbol File - Binary Format"; *)
  2. IMPORT
  3. Basic := FoxBasic, Scanner := FoxScanner, SyntaxTree := FoxSyntaxTree, Global := FoxGlobal,
  4. Files,Streams, Kernel, SYSTEM, D := Debugging, Diagnostics, Options, Formats := FoxFormats, InterfaceComparison := FoxInterfaceComparison
  5. ,Commands, Printout := FoxPrintout, SemanticChecker := FoxSemanticChecker,
  6. Machine
  7. ;
  8. (** Symbol File Format
  9. SymbolFile = codeOptions:RawSet
  10. Imports
  11. [sfSysFlag sysFlags:RawNum]
  12. [sfConst {Symbol Value}]
  13. [sfVar {Symbol}]
  14. [sfXProcedure {Symbol ParameterList}]
  15. [sfOperator {Symbol ParameterList [sfInline Inline]}]
  16. [sfCProcedure {Symbol ParameterList Inline}]
  17. [sfAlias {Type name:RawString}]
  18. [sfType {Type}]
  19. sfEnd.
  20. Imports = {moduleName:RawString} 0X
  21. Symbol = [sfObjFlag flag:RawNum] [sfReadOnly]
  22. Type name:RawString
  23. Value = [ RawNum | RawHInt | RawReal | RawLReal | RawString ]
  24. Type = TypeReference
  25. | BasicType
  26. | ImportedType
  27. | UserType.
  28. TypeReference = number<0:RawNum
  29. BasicType = sfTypeBoolean | .. | sfLastType.
  30. ImportedType = ModuleNumber (structName:RawString | 0X typeIndex:RawNum)
  31. ModuleNumber = sfMod1 | .. | sfModOther-1 | sfModOther moduleNumber:RawNum
  32. UserType = [sfInvisible] [sfSysFlag sysFlag:RawNum] UserType2
  33. UserType2 = sfTypeOpenArray baseType:Type name:RawString
  34. | sfTypeStaticArray baseType:Type name:RawString length:RawNum
  35. | sfTypePointer baseType:Type name:RawString
  36. | sfTypeRecord baseType:Type name:RawString Record
  37. | sfTypeProcedure baseType:Type name:RawString flags:RawNum
  38. ParameterList
  39. Record = mode:RawNum priority:Char {variable:Symbol}
  40. [sfTProcedure {Symbol [name:RawString] ParameterList [sfInline Inline]} ]
  41. sfEnd.
  42. ParameterList = {
  43. [sfObjflag ( sfCParam | sfDarwinCParam | sfWinAPIParam )]
  44. [sfVar] [sfReadOnly] Type name:RawString
  45. } sfEnd.
  46. Inline = {len:Char {c:Char}} 0X.
  47. *)
  48. CONST
  49. TraceImport=0;
  50. TraceExport=1;
  51. Trace = {} ;
  52. (* FoxProgTools.Enum --start=1 sfTypeBoolean sfTypeChar8 sfTypeChar16 sfTypeChar32
  53. sfTypeShortint sfTypeInteger sfTypeLongint sfTypeHugeint sfTypeReal sfTypeLongreal sfTypeSet
  54. sfTypeString sfTypeNoType sfTypeNilType sfTypeByte sfTypeSptr sfMod1 ~
  55. FoxProgTools.Enum --start=2DH --hex sfModOther sfTypeOpenArray sfTypeStaticArray sfTypePointer sfTypeRecord sfTypeProcedure
  56. sfSysFlag sfInvisible sfReadOnly sfObjFlag sfConst sfVar sfLProcedure sfXProcedure sfOperator sfTProcedure sfCProcedure sfAlias sfType sfEnd ~
  57. *)
  58. sfTypeBoolean= 1;
  59. sfTypeChar8= 2;
  60. sfTypeChar16= 3;
  61. sfTypeChar32= 4;
  62. sfTypeShortint= 5;
  63. sfTypeInteger= 6;
  64. sfTypeLongint= 7;
  65. sfTypeHugeint = 8;
  66. sfTypeReal = 9;
  67. sfTypeLongreal = 10;
  68. sfTypeSet = 11;
  69. sfTypeString = 12;
  70. sfTypeNoType = 13;
  71. sfTypeNilType = 14;
  72. sfTypeByte = 15;
  73. sfTypeAny = 16;
  74. sfTypeObject = 17;
  75. sfTypeAddress= 18;
  76. sfTypeSize = 19;
  77. sfTypeUnsigned8=20;
  78. sfTypeUnsigned16=21;
  79. sfTypeUnsigned32=22;
  80. sfTypeUnsigned64=23;
  81. sfLastType = 23;
  82. sfMod1 = sfLastType+1;
  83. sfModOther=2DH;
  84. sfTypeOpenArray=2EH;
  85. (*
  86. sfTypeDynamicArray=2FH;
  87. *)
  88. sfTypeStaticArray=30H;
  89. sfTypePointer=31H;
  90. sfTypeRecord=32H;
  91. sfTypeProcedure=33H;
  92. sfSysFlag=34H;
  93. sfInvisible=35H;
  94. sfHidden = 0ACH;
  95. sfReadOnly=36H;
  96. sfObjFlag = 37H; (* fof: very (!) bad idea to have same number for two type flags *)
  97. sfConst=37H;
  98. sfVar=38H;
  99. sfTypeEnumeration=39H;
  100. (*
  101. sfLProcedure=39H;
  102. *)
  103. sfXProcedure=3AH;
  104. sfOperator=3BH;
  105. sfTProcedure=3CH;
  106. sfCProcedure = sfTProcedure;
  107. sfAlias=3DH;
  108. sfType=3EH;
  109. sfEnd= 3FH;
  110. sfTypeOpenMathArray = 40H;
  111. sfTypeTensor=42H;
  112. sfTypeStaticMathArray = 43H;
  113. sfTypeAll = 44H;
  114. sfTypeRange = 45H;
  115. sfTypeComplex = 46H;
  116. sfTypeLongcomplex = 47H;
  117. (* workaround: handle inlined operators *)
  118. sfInline = 0ABH;
  119. sfProtected = 0;
  120. sfActive=1;
  121. sfSafe=2;
  122. sfClass=16;
  123. sfDelegate = 5;
  124. sfUntraced = 4;
  125. sfWinAPIParam = 13; (* ejz *)
  126. sfCParam= 14; (* fof for linux *)
  127. sfDarwinCParam= 15; (* fld for darwin *)
  128. sfRealtime= 21;
  129. sfDynamic = 22;
  130. sfUnsafe= 23;
  131. sfDisposable= 24;
  132. sfFictive = 25;
  133. Undef=MIN(LONGINT);
  134. CONST
  135. FileTag = 0BBX; (* same constants are defined in Linker and AosLoader *)
  136. NoZeroCompress = 0ADX; (* do. *)
  137. FileVersion* = 0B1X; (* do. *)
  138. FileVersionOC*=0B2X;
  139. FileVersionCurrent*=0B4X;
  140. TYPE
  141. (* TypeReference provides a link between a type and a number for the purpose of late fixes while importing.
  142. When a type number is encountered while importing, a type reference will be used as a placeholder for the final type.
  143. After the import process has collected all types, the references are replaced by the referenced types (cf. Resolver Object) *)
  144. TypeReference = OBJECT (SyntaxTree.Type)
  145. VAR nr: LONGINT;
  146. PROCEDURE & InitTypeReference(nr: LONGINT);
  147. BEGIN
  148. InitType(Basic.invalidPosition); SELF.nr := nr;
  149. END InitTypeReference;
  150. END TypeReference;
  151. (* IndexToType provides a link between numbers and a type. Lists like this are typically filled while importing and provide the base
  152. for the type resolving, cf. Resolver below
  153. *)
  154. IndexToType= OBJECT(Basic.List)
  155. PROCEDURE PutType(nr: LONGINT; type: SyntaxTree.Type);
  156. BEGIN GrowAndSet(nr,type);
  157. END PutType;
  158. PROCEDURE GetType(nr: LONGINT): SyntaxTree.Type;
  159. VAR node: ANY;
  160. BEGIN node := Get(nr); IF node = NIL THEN RETURN NIL ELSE RETURN node(SyntaxTree.Type) END;
  161. END GetType;
  162. END IndexToType;
  163. LateFix= POINTER TO RECORD (* contains a late fix to be resolved in a later step: type fixes and implementations *)
  164. p: ANY; (*scope: SyntaxTree.Scope;*)
  165. next: LateFix;
  166. END;
  167. LateFixList = OBJECT (* fifo queue for items to be resolved later on - deferred fixes *)
  168. VAR first,last: LateFix;
  169. PROCEDURE & Init;
  170. BEGIN first := NIL; last := NIL;
  171. END Init;
  172. (* get and remove element from list *)
  173. PROCEDURE Get((*VAR scope: SyntaxTree.Scope*)): ANY;
  174. VAR p: ANY;
  175. BEGIN
  176. IF first # NIL THEN p := first.p; (*scope := first.scope;*) first := first.next ELSE p := NIL; END;
  177. IF first = NIL THEN last := NIL END;
  178. RETURN p;
  179. END Get;
  180. (* add unresolved type to list *)
  181. PROCEDURE Add(p: ANY (*; scope: SyntaxTree.Scope*));
  182. VAR next: LateFix;
  183. BEGIN
  184. (*ASSERT(scope # NIL);*)
  185. NEW(next); next.p := p; (* next.scope := scope;*)
  186. next.next := NIL;
  187. IF first = NIL THEN first := next; last := next;
  188. ELSE last.next := next; last := next
  189. END;
  190. END Add;
  191. END LateFixList;
  192. (*
  193. The resolver object is used to replace type references in a SyntaxTree.Module tree with the respective types from a given type list.
  194. To do so, the resolver traverses the module tree partially with direct procedural recursion and partially using the visitor pattern.
  195. *)
  196. Resolver=OBJECT (SyntaxTree.Visitor)
  197. VAR typeList: IndexToType; system: Global.System; typeFixes: LateFixList;
  198. checker: SemanticChecker.Checker;
  199. PROCEDURE & Init(system: Global.System; symbolFile: BinarySymbolFile; importCache: SyntaxTree.ModuleScope);
  200. VAR streamDiagnostics: Diagnostics.StreamDiagnostics;
  201. BEGIN
  202. typeList := NIL; SELF.system := system; NEW(typeFixes);
  203. NEW(streamDiagnostics, D.Log);
  204. checker := SemanticChecker.NewChecker(streamDiagnostics,FALSE,FALSE,TRUE,system,symbolFile,importCache,"");
  205. END Init;
  206. (* types that do not refer to other types *)
  207. PROCEDURE VisitType*(x: SyntaxTree.Type);
  208. BEGIN END VisitType;
  209. PROCEDURE VisitBasicType*(x: SyntaxTree.BasicType);
  210. BEGIN END VisitBasicType;
  211. PROCEDURE VisitByteType*(x: SyntaxTree.ByteType);
  212. BEGIN END VisitByteType;
  213. PROCEDURE VisitBooleanType*(x: SyntaxTree.BooleanType);
  214. BEGIN END VisitBooleanType;
  215. PROCEDURE VisitSetType*(x: SyntaxTree.SetType);
  216. BEGIN END VisitSetType;
  217. PROCEDURE VisitAddressType*(x: SyntaxTree.AddressType);
  218. BEGIN END VisitAddressType;
  219. PROCEDURE VisitSizeType*(x: SyntaxTree.SizeType);
  220. BEGIN END VisitSizeType;
  221. PROCEDURE VisitAnyType*(x: SyntaxTree.AnyType);
  222. BEGIN END VisitAnyType;
  223. PROCEDURE VisitObjectType*(x: SyntaxTree.ObjectType);
  224. BEGIN END VisitObjectType;
  225. PROCEDURE VisitNilType*(x: SyntaxTree.NilType);
  226. BEGIN END VisitNilType;
  227. PROCEDURE VisitCharacterType*(x: SyntaxTree.CharacterType);
  228. BEGIN END VisitCharacterType;
  229. PROCEDURE VisitIntegerType*(x: SyntaxTree.IntegerType);
  230. BEGIN END VisitIntegerType;
  231. PROCEDURE VisitFloatType*(x: SyntaxTree.FloatType);
  232. BEGIN END VisitFloatType;
  233. PROCEDURE VisitComplexType*(x: SyntaxTree.ComplexType);
  234. BEGIN END VisitComplexType;
  235. PROCEDURE VisitQualifiedType*(x: SyntaxTree.QualifiedType);
  236. BEGIN
  237. x.SetResolved(ResolveType(x.resolved))
  238. END VisitQualifiedType;
  239. PROCEDURE VisitStringType*(x: SyntaxTree.StringType);
  240. BEGIN END VisitStringType;
  241. PROCEDURE VisitRangeType*(x: SyntaxTree.RangeType);
  242. BEGIN END VisitRangeType;
  243. (* types containing links to other types *)
  244. (**
  245. check enumeration scope: enter symbols and check for duplicate names
  246. **)
  247. PROCEDURE CheckEnumerationScope(x: SyntaxTree.EnumerationScope);
  248. VAR e: SyntaxTree.Constant; lowest, highest,value: Basic.Integer;
  249. BEGIN
  250. lowest := 0; highest := 0;
  251. e := x.firstConstant;
  252. WHILE (e # NIL) DO
  253. e.SetType(x.ownerEnumeration);
  254. e.SetState(SyntaxTree.Resolved);
  255. value := e.value(SyntaxTree.EnumerationValue).value;
  256. IF value < lowest THEN lowest := value END;
  257. IF value > highest THEN highest := value END;
  258. e := e.nextConstant;
  259. END;
  260. x.ownerEnumeration.SetRange(lowest,highest);
  261. END CheckEnumerationScope;
  262. (**
  263. resolve enumeration type: check enumeration scope
  264. **)
  265. PROCEDURE VisitEnumerationType*(x: SyntaxTree.EnumerationType);
  266. VAR baseScope: SyntaxTree.EnumerationScope; resolved: SyntaxTree.Type; enumerationBase: SyntaxTree.EnumerationType;
  267. BEGIN
  268. x.SetEnumerationBase(ResolveType(x.enumerationBase));
  269. IF x.enumerationBase # NIL THEN
  270. resolved := x.enumerationBase.resolved;
  271. enumerationBase := resolved(SyntaxTree.EnumerationType);
  272. baseScope := enumerationBase.enumerationScope;
  273. END;
  274. CheckEnumerationScope(x.enumerationScope);
  275. x.SetState(SyntaxTree.Resolved);
  276. END VisitEnumerationType;
  277. PROCEDURE VisitArrayType*(arrayType: SyntaxTree.ArrayType);
  278. BEGIN
  279. ASSERT(arrayType.arrayBase # NIL);
  280. arrayType.SetArrayBase(ResolveType(arrayType.arrayBase));
  281. arrayType.SetHasPointers(arrayType.arrayBase.resolved.hasPointers);
  282. arrayType.SetState(SyntaxTree.Resolved);
  283. END VisitArrayType;
  284. PROCEDURE VisitMathArrayType*(arrayType: SyntaxTree.MathArrayType);
  285. BEGIN
  286. arrayType.SetArrayBase(ResolveType(arrayType.arrayBase));
  287. IF arrayType.form = SyntaxTree.Static THEN
  288. arrayType.SetIncrement(system.SizeOf(arrayType.arrayBase));
  289. arrayType.SetHasPointers(arrayType.arrayBase.resolved.hasPointers);
  290. ELSE
  291. arrayType.SetHasPointers(TRUE)
  292. END;
  293. arrayType.SetState(SyntaxTree.Resolved);
  294. END VisitMathArrayType;
  295. PROCEDURE VisitPointerType*(pointerType: SyntaxTree.PointerType);
  296. VAR recordType: SyntaxTree.RecordType;
  297. BEGIN
  298. IF ~(SyntaxTree.Resolved IN pointerType.state) THEN
  299. typeFixes.Add(pointerType);
  300. pointerType.SetState(SyntaxTree.Resolved);
  301. END;
  302. (*
  303. pointerType.SetPointerBase(ResolveType(pointerType.pointerBase));
  304. IF pointerType.pointerBase.resolved IS SyntaxTree.RecordType THEN
  305. recordType := pointerType.pointerBase.resolved(SyntaxTree.RecordType);
  306. IF (recordType.typeDeclaration = NIL) THEN
  307. recordType.SetPointerType(pointerType);
  308. recordType.SetTypeDeclaration(pointerType.typeDeclaration)
  309. END;
  310. END;
  311. pointerType.SetState(SyntaxTree.Resolved);
  312. *)
  313. END VisitPointerType;
  314. PROCEDURE FixPointerType(pointerType: SyntaxTree.PointerType);
  315. VAR recordType: SyntaxTree.RecordType;
  316. BEGIN
  317. pointerType.SetPointerBase(ResolveType(pointerType.pointerBase));
  318. IF pointerType.pointerBase.resolved IS SyntaxTree.RecordType THEN
  319. recordType := pointerType.pointerBase.resolved(SyntaxTree.RecordType);
  320. IF (recordType.typeDeclaration = NIL) THEN
  321. recordType.SetPointerType(pointerType);
  322. recordType.SetTypeDeclaration(pointerType.typeDeclaration)
  323. END;
  324. END;
  325. END FixPointerType;
  326. PROCEDURE VisitRecordType*(recordType: SyntaxTree.RecordType);
  327. VAR recordBase: SyntaxTree.RecordType; numberMethods: LONGINT; procedure,super,testsuper: SyntaxTree.Procedure; recordScope: SyntaxTree.RecordScope;
  328. pointerType: SyntaxTree.Type; typeDeclaration: SyntaxTree.TypeDeclaration; symbol: SyntaxTree.Symbol; size: HUGEINT; hasPointer: BOOLEAN;
  329. var: SyntaxTree.Variable;
  330. BEGIN
  331. recordType.SetBaseType(ResolveType(recordType.baseType));
  332. recordScope := recordType.recordScope;
  333. recordBase := recordType.GetBaseRecord();
  334. hasPointer := FALSE;
  335. IF recordBase = NIL THEN numberMethods := 0;
  336. ELSE
  337. recordBase.Accept(SELF); numberMethods := recordBase.recordScope.numberMethods;
  338. END;
  339. symbol := recordScope.firstSymbol; (* must use the sorted list here, important! *)
  340. WHILE symbol # NIL DO
  341. IF (symbol IS SyntaxTree.Procedure) THEN
  342. procedure := symbol(SyntaxTree.Procedure);
  343. IF procedure IS SyntaxTree.Operator THEN FixProcedureType(procedure.type(SyntaxTree.ProcedureType)) END;
  344. super := SemanticChecker.FindSuperProcedure(recordScope, procedure);
  345. procedure.SetSuper(super);
  346. IF super # NIL THEN
  347. procedure.SetAccess(procedure.access+super.access);
  348. END;
  349. IF procedure.super # NIL THEN
  350. procedure.SetMethodNumber(procedure.super.methodNumber)
  351. ELSE
  352. procedure.SetMethodNumber(numberMethods);
  353. INC(numberMethods);
  354. END;
  355. END;
  356. symbol := symbol.nextSymbol;
  357. END;
  358. recordScope.SetNumberMethods(numberMethods);
  359. IF (recordScope.firstProcedure # NIL) OR (recordBase # NIL) & (recordBase.isObject) THEN
  360. recordType.IsObject(TRUE)
  361. END;
  362. IF (recordBase # NIL) & recordBase.hasPointers THEN hasPointer := TRUE END;
  363. Scope(recordType.recordScope);
  364. var := recordType.recordScope.firstVariable;
  365. WHILE var # NIL DO
  366. hasPointer := hasPointer OR var.type.resolved.hasPointers & ~var.untraced;
  367. var := var.nextVariable;
  368. END;
  369. recordType.SetHasPointers(hasPointer);
  370. checker.SetCurrentScope(recordType.recordScope);
  371. checker.ResolveArrayStructure(recordType);
  372. recordType.SetState(SyntaxTree.Resolved);
  373. size := system.SizeOf(recordType); (* generate field offsets *)
  374. IF (recordType.typeDeclaration = NIL) & (recordType.pointerType # NIL) THEN
  375. pointerType := recordType.pointerType.resolved;
  376. typeDeclaration := pointerType.typeDeclaration;
  377. recordType.SetTypeDeclaration(typeDeclaration);
  378. END;
  379. END VisitRecordType;
  380. PROCEDURE VisitProcedureType*(procedureType: SyntaxTree.ProcedureType);
  381. VAR parameter: SyntaxTree.Parameter;
  382. BEGIN
  383. IF ~(SyntaxTree.Resolved IN procedureType.state) THEN
  384. typeFixes.Add(procedureType);
  385. IF procedureType.isDelegate THEN
  386. procedureType.SetHasPointers(TRUE);
  387. END;
  388. procedureType.SetState(SyntaxTree.Resolved);
  389. END;
  390. END VisitProcedureType;
  391. PROCEDURE FixProcedureType(procedureType: SyntaxTree.ProcedureType);
  392. VAR parameter: SyntaxTree.Parameter; returnType: SyntaxTree.Type;
  393. BEGIN
  394. (* parameter list *)
  395. parameter := procedureType.firstParameter;
  396. WHILE(parameter # NIL) DO
  397. parameter.SetType(ResolveType(parameter.type));
  398. parameter := parameter.nextParameter;
  399. END;
  400. (* return type *)
  401. returnType := ResolveType(procedureType.returnType);
  402. procedureType.SetReturnType(ResolveType(returnType));
  403. IF returnType# NIL THEN
  404. parameter := SyntaxTree.NewParameter(Basic.invalidPosition,procedureType,Global.ReturnParameterName,SyntaxTree.VarParameter);
  405. parameter.SetType(returnType);
  406. parameter.SetState(SyntaxTree.Resolved);
  407. procedureType.SetReturnParameter(parameter);
  408. END;
  409. END FixProcedureType;
  410. (* a type reference is resolved by replacing it with the respective element of the type list, all other types remain *)
  411. PROCEDURE ResolveType(type: SyntaxTree.Type): SyntaxTree.Type;
  412. BEGIN
  413. IF type = NIL THEN RETURN NIL
  414. ELSIF (type IS TypeReference) THEN
  415. type := typeList.GetType(type(TypeReference).nr);
  416. END;
  417. IF ~(SyntaxTree.Resolved IN type.state) THEN
  418. type.Accept(SELF);
  419. type.SetState(SyntaxTree.Resolved);
  420. END;
  421. RETURN type;
  422. END ResolveType;
  423. (** resolve all pending types (late resolving).
  424. - type fixes are resolved at the end of the declaration phase
  425. - type fixes may imply new type fixes that are also entered at the end of the list
  426. **)
  427. PROCEDURE FixTypes;
  428. VAR p: ANY; prevScope: SyntaxTree.Scope;
  429. BEGIN
  430. (*prevScope := currentScope;*)
  431. p := typeFixes.Get((*currentScope*));
  432. WHILE p # NIL DO
  433. ASSERT(p IS SyntaxTree.Type);
  434. IF p IS SyntaxTree.PointerType THEN
  435. FixPointerType(p(SyntaxTree.PointerType))
  436. ELSIF p IS SyntaxTree.ProcedureType THEN
  437. FixProcedureType(p(SyntaxTree.ProcedureType))
  438. ELSE
  439. HALT(100);
  440. END;
  441. p := typeFixes.Get((*currentScope*));
  442. END;
  443. (*currentScope :=prevScope;*)
  444. END FixTypes;
  445. (* scope traversal *)
  446. PROCEDURE Scope(scope: SyntaxTree.Scope);
  447. VAR typeDeclaration: SyntaxTree.TypeDeclaration; variable: SyntaxTree.Variable; procedure: SyntaxTree.Procedure;
  448. BEGIN
  449. (* type declarations *)
  450. typeDeclaration := scope.firstTypeDeclaration;
  451. WHILE(typeDeclaration # NIL) DO
  452. typeDeclaration.SetDeclaredType(ResolveType(typeDeclaration.declaredType));
  453. IF ~(typeDeclaration.declaredType IS SyntaxTree.BasicType) THEN
  454. typeDeclaration.declaredType.SetTypeDeclaration(typeDeclaration);
  455. END;
  456. typeDeclaration := typeDeclaration.nextTypeDeclaration;
  457. END;
  458. (* variables *)
  459. variable := scope.firstVariable;
  460. WHILE(variable # NIL) DO
  461. variable.SetType(ResolveType(variable.type));
  462. ASSERT (~(variable.type IS TypeReference));
  463. ASSERT(~(variable.type.resolved IS TypeReference));
  464. variable := variable.nextVariable;
  465. END;
  466. (* procedures *)
  467. procedure := scope.firstProcedure;
  468. WHILE(procedure # NIL) DO
  469. Scope(procedure.procedureScope);
  470. procedure.SetType(ResolveType(procedure.type));
  471. procedure := procedure.nextProcedure;
  472. END;
  473. END Scope;
  474. (* replace all TypeReferences in module by referenced types in typeList *)
  475. PROCEDURE Resolve(module: SyntaxTree.Module; typeList: IndexToType);
  476. BEGIN
  477. SELF.typeList := typeList;
  478. Scope(module.moduleScope);
  479. FixTypes;
  480. module.SetState(SyntaxTree.Resolved);
  481. END Resolve;
  482. END Resolver;
  483. (*
  484. An Index is the data structure containing a number to be mapped to types via the object TypeToIndex below.
  485. Used for type enumeration when exporting.
  486. *)
  487. Index =POINTER TO RECORD tag: LONGINT END;
  488. (*
  489. The TypeToIndex object provides the link between a type and a module and type number. It is the inverse of the IndexToType and is used
  490. for exporting. It is implemented using a hash table mapping a SyntaxTree.Type to a Index object.
  491. *)
  492. TypeToIndex= OBJECT (Basic.HashTable)
  493. PROCEDURE GetIndex(type: SyntaxTree.Type): LONGINT;
  494. VAR t:ANY;
  495. BEGIN
  496. t := Get(type);
  497. IF t # NIL THEN RETURN t(Index).tag ELSE RETURN Undef END;
  498. END GetIndex;
  499. PROCEDURE PutIndex(type:SyntaxTree.Type; nr: LONGINT);
  500. VAR t: Index;
  501. BEGIN
  502. ASSERT(nr # Undef);
  503. NEW(t); t.tag := nr; Put(type,t);
  504. END PutIndex;
  505. END TypeToIndex;
  506. Attribute = OBJECT
  507. VAR
  508. numberTypes: LONGINT;
  509. indexToType: IndexToType;
  510. typeToIndex: TypeToIndex;
  511. PROCEDURE &Init;
  512. BEGIN numberTypes := 0; NEW(indexToType,16); NEW(typeToIndex,100);
  513. END Init;
  514. END Attribute;
  515. IndexToAttribute= OBJECT(Basic.List)
  516. PROCEDURE PutAttribute(nr: LONGINT; attribute: Attribute);
  517. BEGIN GrowAndSet(nr,attribute);
  518. END PutAttribute;
  519. PROCEDURE GetAttribute(nr: LONGINT): Attribute;
  520. VAR node: ANY; attribute: Attribute;
  521. BEGIN
  522. IF Length() <= nr THEN node := NIL ELSE node := Get(nr) END;
  523. IF node # NIL THEN attribute := node(Attribute)
  524. ELSE NEW(attribute); PutAttribute(nr,attribute);
  525. END;
  526. RETURN attribute
  527. END GetAttribute;
  528. END IndexToAttribute;
  529. BinarySymbolFile*=OBJECT (Formats.SymbolFileFormat)
  530. VAR file-: Files.File; extension-: Basic.FileName;
  531. noRedefinition, noModification, noInterfaceCheck: BOOLEAN;
  532. version: CHAR;
  533. (** Import - Symbol Table Loader Plugin *)
  534. PROCEDURE Import*(CONST moduleName: ARRAY OF CHAR; importCache: SyntaxTree.ModuleScope): SyntaxTree.Module;
  535. VAR
  536. module: SyntaxTree.Module;
  537. moduleIdentifier,contextIdentifier: SyntaxTree.Identifier;
  538. moduleScope: SyntaxTree.ModuleScope;
  539. fileName: Files.FileName;
  540. R: Streams.Reader;
  541. tag, i: LONGINT;
  542. visibility: SET;
  543. type: SyntaxTree.Type;
  544. variable: SyntaxTree.Variable;
  545. constant: SyntaxTree.Constant;
  546. procedure: SyntaxTree.Procedure;
  547. procedureType: SyntaxTree.ProcedureType;
  548. procedureScope: SyntaxTree.ProcedureScope;
  549. typeDeclaration: SyntaxTree.TypeDeclaration;
  550. resolver: Resolver;
  551. allTypes: IndexToType; numberReimports, numberTypes : LONGINT;
  552. name: SyntaxTree.IdentifierString;
  553. value: SyntaxTree.Value;
  554. stamp: LONGINT;
  555. b: BOOLEAN;
  556. indexToAttribute: IndexToAttribute;
  557. predefType: ARRAY sfLastType+1 OF SyntaxTree.Type;
  558. PROCEDURE NewTypeReference(nr: LONGINT): SyntaxTree.Type;
  559. VAR typeReference: TypeReference;
  560. BEGIN
  561. NEW(typeReference,nr); RETURN typeReference;
  562. END NewTypeReference;
  563. (* Imports = {moduleName:RawString} 0X *)
  564. PROCEDURE Imports;
  565. VAR moduleName: SyntaxTree.IdentifierString; import: SyntaxTree.Import; importedModule: SyntaxTree.Module; moduleIdentifier,moduleContext: SyntaxTree.Identifier; b: BOOLEAN;
  566. BEGIN
  567. R.RawString(moduleName);
  568. WHILE moduleName # "" DO
  569. ASSERT(moduleName # "SYSTEM");
  570. IF TraceImport IN Trace THEN D.Str("import module: "); D.Str(moduleName); D.Ln; END;
  571. (* as the context is not encoded in the symbol file, we have to deduce it from the filename, this is ugly but necessary
  572. to keep consistency with old compiler
  573. *)
  574. Global.ContextFromName(moduleName,moduleIdentifier,moduleContext);
  575. import := importCache.ImportByModuleName(moduleIdentifier,moduleContext);
  576. IF import # NIL THEN
  577. IF import.module = NIL THEN (* has not yet been imported by parent module *)
  578. (* adjust import symbol in parent *)
  579. importedModule := Import(moduleName,importCache);
  580. import.SetModule(importedModule);
  581. ELSE
  582. (* take module from parent *)
  583. importedModule := import.module;
  584. END
  585. ELSE
  586. importedModule := Import(moduleName,importCache);
  587. IF importedModule # NIL THEN
  588. import := SyntaxTree.NewImport(Basic.invalidPosition,importedModule.name,importedModule.name,FALSE);
  589. import.SetContext(importedModule.context);
  590. import.SetModule(importedModule);
  591. import.SetState(SyntaxTree.Resolved);
  592. importCache.AddImport(import);
  593. END;
  594. END;
  595. (* create new import symbol for this module scope *)
  596. IF importedModule # NIL THEN
  597. import := SyntaxTree.NewImport(Basic.invalidPosition,moduleIdentifier,moduleIdentifier,TRUE);
  598. import.SetModule(importedModule);
  599. import.SetContext(moduleContext);
  600. import.SetState(SyntaxTree.Resolved);
  601. module.moduleScope.AddImport(import);
  602. module.moduleScope.EnterSymbol(import,b);
  603. END;
  604. R.RawString(moduleName);
  605. END
  606. END Imports;
  607. (* Value = [ RawNum | RawHInt | RawReal | RawLReal | RawString ] *)
  608. PROCEDURE Value(type: SyntaxTree.Type): SyntaxTree.Value;
  609. VAR i: LONGINT; huge: HUGEINT; r: REAL; lr: LONGREAL; string: SyntaxTree.String; length: LONGINT; set: SET;
  610. value: SyntaxTree.Value; size: LONGINT;
  611. BEGIN
  612. size := type.sizeInBits;
  613. IF type IS SyntaxTree.BooleanType THEN R.RawNum(i);
  614. IF TraceImport IN Trace THEN D.Str("InConst / Bool / "); D.Int(i,1); D.Ln; END;
  615. IF i = 0 THEN value := Global.NewBooleanValue(system,Basic.invalidPosition,FALSE) ELSE value := Global.NewBooleanValue(system,Basic.invalidPosition,TRUE) END
  616. ELSIF (type IS SyntaxTree.CharacterType) THEN
  617. IF (size=8) OR (size=16) OR (size=32) THEN
  618. R.RawNum(i);
  619. IF TraceImport IN Trace THEN D.Str("InConst / Char / "); D.Int(i,1); D.Ln; END;
  620. value := SyntaxTree.NewCharacterValue(Basic.invalidPosition,CHR(i));
  621. END;
  622. ELSIF type IS SyntaxTree.IntegerType THEN
  623. IF (size = 32) & ~type(SyntaxTree.IntegerType).signed THEN
  624. R.RawHInt(huge);
  625. IF TraceImport IN Trace THEN D.Str("InConst / Unsigned32 / "); D.Ln END;
  626. value := SyntaxTree.NewIntegerValue (Basic.invalidPosition,huge);
  627. ELSIF size <=32 THEN
  628. R.RawNum(i);
  629. IF TraceImport IN Trace THEN D.Str("InConst / Int"); D.Int(size,1); D.String(" "); D.Int(i,1); D.Ln END;
  630. value := SyntaxTree.NewIntegerValue(Basic.invalidPosition,i);
  631. ELSIF size=64 THEN
  632. R.RawHInt(huge);
  633. IF TraceImport IN Trace THEN D.Str("InConst / HInt / "); D.Ln END;
  634. value := SyntaxTree.NewIntegerValue (Basic.invalidPosition,huge);
  635. END;
  636. ELSIF type IS SyntaxTree.SetType THEN R.RawNum(SYSTEM.VAL(LONGINT, set));
  637. IF TraceImport IN Trace THEN D.Str("InConst / Set / "); D.Hex(SYSTEM.VAL(LONGINT, set),1); D.Ln END;
  638. value := SyntaxTree.NewSetValue(Basic.invalidPosition,set);
  639. ELSIF type IS SyntaxTree.FloatType THEN
  640. IF size = 32 THEN
  641. R.RawReal(r);
  642. IF TraceImport IN Trace THEN D.Str("InConst / Real / "); D.Ln END;
  643. value := SyntaxTree.NewRealValue(Basic.invalidPosition,r);
  644. ELSIF size = 64 THEN
  645. R.RawLReal(lr);
  646. IF TraceImport IN Trace THEN D.Str("InConst / LongReal / "); D.Ln END;
  647. value := SyntaxTree.NewRealValue(Basic.invalidPosition,lr);
  648. END;
  649. ELSIF type IS SyntaxTree.StringType THEN
  650. IF version <= FileVersionOC THEN NEW(string, 256)
  651. ELSE R.RawLInt(length); NEW(string, length)
  652. END;
  653. R.RawString(string^);
  654. IF TraceImport IN Trace THEN D.Str("InConst / String / "); D.Str(string^); D.Ln END;
  655. value := SyntaxTree.NewStringValue(Basic.invalidPosition,string);
  656. type(SyntaxTree.StringType).SetLength(value(SyntaxTree.StringValue).length);
  657. type.SetState(SyntaxTree.Resolved);
  658. ELSIF type IS SyntaxTree.EnumerationType THEN R.RawNum(i);
  659. IF TraceImport IN Trace THEN D.Str("InConst / LInt / "); D.Int(i,1); D.Ln END;
  660. value := SyntaxTree.NewEnumerationValue(Basic.invalidPosition,i);
  661. ELSIF type IS SyntaxTree.NilType THEN
  662. IF TraceImport IN Trace THEN D.Str("InConst / Nil"); D.Ln END;
  663. value := SyntaxTree.NewNilValue(Basic.invalidPosition);
  664. END;
  665. value.SetType(type);
  666. value.SetState(SyntaxTree.Resolved);
  667. RETURN value
  668. END Value;
  669. (* EnumerationList = {name:RawString} sfEnd *)
  670. PROCEDURE EnumerationList(enumerationScope: SyntaxTree.EnumerationScope);
  671. VAR enumerator: SyntaxTree.Constant; visibility,flags: SET; b: BOOLEAN;
  672. type: SyntaxTree.Type; name: SyntaxTree.IdentifierString; identifier: SyntaxTree.Identifier;
  673. BEGIN
  674. R.RawString(name);
  675. WHILE name # "" DO
  676. identifier := SyntaxTree.NewIdentifier(name);
  677. enumerator := SyntaxTree.NewConstant(Basic.invalidPosition,identifier);
  678. enumerationScope.AddConstant(enumerator);
  679. enumerationScope.EnterSymbol(enumerator,b);
  680. IF name # "@" THEN enumerationScope.lastConstant.SetAccess(SyntaxTree.Public+SyntaxTree.Internal+SyntaxTree.Protected)
  681. ELSE enumerationScope.lastConstant.SetAccess(SyntaxTree.Internal)
  682. END;
  683. value := Value(enumerationScope.ownerEnumeration);
  684. enumerator.SetValue(value);
  685. enumerator.SetType(enumerationScope.ownerEnumeration);
  686. R.RawString(name);
  687. END;
  688. END EnumerationList;
  689. (* ParameterList = { [sfObjflag ( sfCParam | sfDarwinCParam | sfWinAPIParam )] [sfVar] [sfReadOnly] Type name:RawString } sfEnd *)
  690. PROCEDURE ParameterList(VAR callingConvention: LONGINT; parentScope: SyntaxTree.Scope; procedureType: SyntaxTree.ProcedureType);
  691. VAR name: SyntaxTree.IdentifierString; type: SyntaxTree.Type; f: LONGINT;
  692. kind: LONGINT;
  693. parameter: SyntaxTree.Parameter;
  694. BEGIN
  695. IF TraceImport IN Trace THEN
  696. D.Str("ParameterList "); D.Ln
  697. END;
  698. callingConvention := SyntaxTree.OberonCallingConvention;
  699. R.RawNum(tag);
  700. WHILE tag#sfEnd DO
  701. IF tag = sfObjFlag THEN (*! the calling convention should not be expressed via the parameters (compatiblity with old compiler) *)
  702. R.RawNum(f);
  703. IF f = sfCParam THEN (* fof for Linux *)
  704. callingConvention := SyntaxTree.CCallingConvention
  705. ELSIF f = sfDarwinCParam THEN (* fld for darwin *)
  706. callingConvention := SyntaxTree.DarwinCCallingConvention
  707. ELSIF f=sfWinAPIParam THEN
  708. callingConvention := SyntaxTree.WinAPICallingConvention
  709. ELSE HALT(100)
  710. END;
  711. R.RawNum(tag);
  712. END;
  713. IF tag=sfVar THEN
  714. R.RawNum(tag);
  715. kind := SyntaxTree.VarParameter;
  716. ELSE
  717. kind := SyntaxTree.ValueParameter;
  718. END;
  719. IF tag = sfReadOnly THEN (* var const *)
  720. R.RawNum(tag);
  721. kind := SyntaxTree.ConstParameter;
  722. END;
  723. type := Type();
  724. R.RawString(name);
  725. parameter := SyntaxTree.NewParameter(Basic.invalidPosition,procedureType,SyntaxTree.NewIdentifier(name),kind);
  726. parameter.SetType(type);
  727. parameter.SetState(SyntaxTree.Resolved);
  728. (*! remove this after a rebuild of the release - for compatibility only *)
  729. IF (parameter.name=Global.SelfParameterName)
  730. OR (parameter.name=Global.ReturnParameterName)
  731. OR (parameter.name=Global.PointerReturnName)
  732. OR (parameter.name=Global.ResultName) THEN (* ignore *)
  733. ELSE
  734. procedureType.AddParameter(parameter);
  735. END;
  736. R.RawNum(tag)
  737. END;
  738. IF callingConvention # SyntaxTree.OberonCallingConvention THEN
  739. procedureType.RevertParameters;
  740. END;
  741. END ParameterList;
  742. (* returns the index of module importedModule in the list of module module *)
  743. PROCEDURE ModuleByIndex(module: SyntaxTree.Module; index: LONGINT): SyntaxTree.Module;
  744. VAR import: SyntaxTree.Import;
  745. BEGIN import := module.moduleScope.firstImport;
  746. WHILE (import # NIL) & (index > 0) DO
  747. IF (* (import.direct) & *) ~Global.IsSystemModule(import.module) THEN DEC(index) END;
  748. import := import.nextImport;
  749. END;
  750. ASSERT(import # NIL);
  751. (* ASSERT(import.direct); *)
  752. RETURN import.module;
  753. END ModuleByIndex;
  754. (*
  755. Record =
  756. mode:RawNum priority:Char {variable:Symbol}
  757. [sfTProcedure {Symbol [name:RawString] ParameterList [sfInline Inline]} ]
  758. sfEnd
  759. *)
  760. PROCEDURE Record(recordType: SyntaxTree.RecordType; baseType: SyntaxTree.Type);
  761. VAR
  762. mode: SET;
  763. priority: LONGINT;
  764. visibility: SET;
  765. active, safe, isOperator, isDynamic, isFictive: BOOLEAN;
  766. untraced, realtime, constructor: BOOLEAN;
  767. fOffset: LONGINT;
  768. variable: SyntaxTree.Variable;
  769. procedure: SyntaxTree.Procedure;
  770. operator: SyntaxTree.Operator;
  771. procedureType: SyntaxTree.ProcedureType;
  772. recordScope: SyntaxTree.RecordScope;
  773. recordBody: SyntaxTree.Body;
  774. name: SyntaxTree.IdentifierString;
  775. ch: CHAR;
  776. callingConvention: LONGINT;
  777. BEGIN
  778. recordScope := recordType.recordScope;
  779. R.RawNum(SYSTEM.VAL(LONGINT, mode));
  780. IF sfActive IN mode THEN active := TRUE ELSE active := FALSE END;
  781. IF sfProtected IN mode THEN recordType.SetProtected(TRUE) END;
  782. IF sfSafe IN mode THEN safe := TRUE ELSE safe := FALSE END;
  783. R.Char(ch);
  784. priority := ORD(ch); (* body priority, if active object *)
  785. IF TraceImport IN Trace THEN
  786. D.Str("Rec / Mode / "); D.Hex(SYSTEM.VAL(LONGINT, mode),1); D.Ln;
  787. D.Str("Rec / Prio / "); D.Int(priority,1); D.Ln
  788. END;
  789. R.RawNum(tag);
  790. WHILE (tag < sfTProcedure) OR (tag > sfEnd) DO (*read fields*)
  791. isOperator := FALSE;
  792. Symbol(recordScope,type,name,visibility,untraced, realtime, constructor, isOperator, isDynamic, isFictive, fOffset);
  793. ASSERT(type # NIL);
  794. IF name = "" THEN visibility := SyntaxTree.Internal END;
  795. variable := SyntaxTree.NewVariable(Basic.invalidPosition,SyntaxTree.NewIdentifier(name));
  796. variable.SetType(type);
  797. variable.SetUntraced(untraced);
  798. variable.SetAccess(visibility);
  799. IF isFictive THEN
  800. TRACE(fOffset);
  801. variable.SetFictive(fOffset);
  802. variable.SetUntraced(TRUE);
  803. END;
  804. variable.SetState(SyntaxTree.Resolved);
  805. recordScope.AddVariable(variable);
  806. recordScope.EnterSymbol(variable,b);
  807. R.RawNum(tag);
  808. END;
  809. IF tag=sfTProcedure THEN
  810. R.RawNum(tag);
  811. WHILE tag#sfEnd DO
  812. isOperator := FALSE;
  813. Symbol(recordScope,type,name, visibility,untraced, realtime, constructor, isOperator, isDynamic, isFictive, fOffset);
  814. IF name = "" THEN R.RawString(name) END;
  815. procedureScope := SyntaxTree.NewProcedureScope(recordScope);
  816. IF isOperator THEN
  817. operator := SyntaxTree.NewOperator(Basic.invalidPosition,SyntaxTree.NewIdentifier(name),procedureScope);
  818. procedure := operator
  819. ELSE
  820. procedure := SyntaxTree.NewProcedure(Basic.invalidPosition,SyntaxTree.NewIdentifier(name),procedureScope);
  821. END;
  822. procedureType := SyntaxTree.NewProcedureType(Basic.invalidPosition,recordScope);
  823. procedureType.SetReturnType(type);
  824. procedureType.SetRealtime(realtime);
  825. procedure.SetConstructor(constructor);
  826. procedureType.SetDelegate(TRUE);
  827. procedure.SetType(procedureType);
  828. procedure.SetAccess(visibility);
  829. procedure.SetState(SyntaxTree.Resolved);
  830. IF constructor THEN
  831. recordScope.SetConstructor(procedure); (*! redundant *)
  832. END;
  833. ParameterList(callingConvention,procedureScope,procedureType);
  834. recordScope.AddProcedure(procedure);
  835. IF isOperator THEN
  836. recordScope.AddOperator(operator);
  837. END;
  838. recordScope.EnterSymbol(procedure,b);
  839. (* This identifies a inlined Indexer *)
  840. R.RawNum(tag);
  841. IF tag = sfInline THEN
  842. Inline(procedureScope);
  843. (*
  844. INCL(flag, SyntaxTree.Inline);
  845. INCL(flag, SyntaxTree.Indexer);
  846. INCL(flag, SyntaxTree.Operator);
  847. mscope.code := Inline();
  848. *)
  849. R.RawNum(tag)
  850. END;
  851. IF (procedure.name=Global.RecordBodyName) THEN
  852. recordScope.SetBodyProcedure(procedure);
  853. recordBody := SyntaxTree.NewBody(Basic.invalidPosition,procedureScope);
  854. recordBody.SetSafe(safe);
  855. recordBody.SetActive(active);
  856. procedureScope.SetBody(recordBody);
  857. END;
  858. END
  859. ELSE ASSERT(tag = sfEnd);
  860. END;
  861. (*
  862. ASSERT((bodyFlags = {}) OR (recordScope.bodyProcedure # NIL));
  863. *)
  864. recordType.SetBaseType(baseType);
  865. END Record;
  866. (*
  867. Type =
  868. TypeReference
  869. |BasicType
  870. |ImportedType
  871. |UserType.
  872. TypeReference = number:RawNum(<0)
  873. BasicType = sfTypeBoolean | .. | sfLastType.
  874. ImportedType = ModuleNumber (structName:RawString | 0X typeIndex:RawNum)
  875. ModuleNumber = sfMod1 | .. | sfModOther-1 | sfModOther moduleNumber:RawNum
  876. UserType = [sfInvisible] [sfSysFlag sysFlag:RawNum] UserType2
  877. UserType2=
  878. sfTypeOpenArray baseType:Type name:RawString flags:RawNum
  879. |sfTypeStaticArray baseType:Type name:RawString flags:RawNum length:RawNum
  880. |sfOpenMathArray baseType:Type name:RawString
  881. |sfStaticMathArray baseType:Type name:RawString length:RawNum
  882. |sfTypeTensor baseType:Type name:RawString
  883. |sfTypePointer baseType:Type name:RawString flags:RawNum
  884. |sfTypeRecord baseType:Type name:RawString flags:RawNum Record
  885. |sfTypeProcedure baseType:Type name:RawString flags:RawNum ParameterList
  886. |sfTypeEnumeration enumerationBase:Type name:RawString
  887. *)
  888. PROCEDURE Type(): SyntaxTree.Type;
  889. VAR
  890. typtag,len: LONGINT;
  891. name: SyntaxTree.IdentifierString;
  892. type, baseType: SyntaxTree.Type;
  893. typeDeclaration: SyntaxTree.TypeDeclaration;
  894. arrayType: SyntaxTree.ArrayType;
  895. mathArrayType: SyntaxTree.MathArrayType;
  896. pointerType: SyntaxTree.PointerType;
  897. procedureType: SyntaxTree.ProcedureType;
  898. recordType: SyntaxTree.RecordType;
  899. recordScope: SyntaxTree.RecordScope;
  900. qualifiedType: SyntaxTree.QualifiedType;
  901. enumerationScope: SyntaxTree.EnumerationScope;
  902. enumerationType: SyntaxTree.EnumerationType;
  903. (*import: SyntaxTree.Import;*)
  904. importedModule: SyntaxTree.Module;
  905. identifier: SyntaxTree.Identifier;
  906. thisIndex : LONGINT;
  907. typeAdr: LONGINT;
  908. size: SyntaxTree.Value;
  909. visibility: SET;
  910. typeName: SyntaxTree.IdentifierString;
  911. sysflag: LONGINT; flags: SET;
  912. attribute: Attribute;
  913. callingConvention: LONGINT;
  914. BEGIN
  915. visibility := SyntaxTree.Public + SyntaxTree.Protected + SyntaxTree.Internal; flags := {};
  916. IF tag <= 0 THEN (* TypeReference = number:RawNum(<0) *)
  917. type := NewTypeReference(-tag);
  918. IF TraceImport IN Trace THEN
  919. D.Str("Type / OldStr "); D.Int(-tag,1); D.Ln
  920. END
  921. ELSIF tag = sfTypeString THEN
  922. type := SyntaxTree.NewStringType(Basic.invalidPosition,system.characterType,0);
  923. IF TraceImport IN Trace THEN
  924. D.Str("Type / String "); D.Int(tag,1); D.Ln
  925. END
  926. ELSIF tag <= sfLastType THEN (* BasicType = sfTypeBoolean | .. | sfLastType. *)
  927. type := predefType[tag];
  928. ASSERT((tag = sfTypeNoType) OR (type # NIL));
  929. IF TraceImport IN Trace THEN
  930. D.Str("Type / Basic "); D.Int(tag,1); D.Ln
  931. END
  932. ELSIF tag = sfTypeRange THEN
  933. type := system.rangeType;
  934. ELSIF tag = sfTypeComplex THEN
  935. type := system.complexType;
  936. ELSIF tag = sfTypeLongcomplex THEN
  937. type := system.longcomplexType;
  938. ELSIF tag <= sfModOther THEN
  939. (* ImportedType = ModuleNumber (structName:RawString | 0X typeIndex:RawNum) *)
  940. (* ModuleNumber = sfMod1 | .. | sfModOther-1 | sfModOther moduleNumber:RawNum *)
  941. IF tag = sfModOther THEN
  942. R.RawNum(tag);
  943. ASSERT(tag >= 0);
  944. ELSE
  945. tag := tag-sfMod1
  946. END; (*tag = [0 .. +oo[ *)
  947. importedModule := ModuleByIndex(module,tag);
  948. ASSERT(importedModule # NIL);
  949. R.RawString(typeName);
  950. type := NIL;
  951. attribute := indexToAttribute.GetAttribute(tag);
  952. IF typeName # "" THEN (* first import of struct *)
  953. identifier := SyntaxTree.NewIdentifier(typeName);
  954. typeDeclaration := importedModule.moduleScope.FindTypeDeclaration(identifier); (* find type in module *)
  955. IF (typeDeclaration # NIL) THEN
  956. qualifiedType := SyntaxTree.NewQualifiedType(Basic.invalidPosition,moduleScope,SyntaxTree.NewQualifiedIdentifier(Basic.invalidPosition,importedModule.name,identifier));
  957. qualifiedType.SetResolved(typeDeclaration.declaredType);
  958. qualifiedType.SetTypeDeclaration(typeDeclaration);
  959. type := qualifiedType;
  960. END;
  961. (* add reimport *)
  962. attribute.indexToType.PutType(attribute.numberTypes,type);
  963. INC(attribute.numberTypes);
  964. IF TraceImport IN Trace THEN
  965. D.Str("Type / Reimport "); D.Str(typeName); D.Str(" in "); D.Str0(importedModule.name); D.Str(":"); D.Int(tag,1-sfMod1); D.Ln;
  966. END;
  967. ELSE
  968. R.RawNum(typeAdr);
  969. type := attribute.indexToType.GetType(typeAdr);
  970. IF TraceImport IN Trace THEN
  971. D.Str("Type / Reimport "); D.Int(typeAdr,1); D.Str(" in "); D.Str0(importedModule.name); D.Str(":"); D.Int(tag,1-sfMod1); D.Ln;
  972. END;
  973. END;
  974. ELSE (* UserType = [sfInvisible] [sfSysFlag flag] UserType2 *)
  975. IF TraceImport IN Trace THEN
  976. D.Str("Type / User "); D.Str(name); D.Ln
  977. END;
  978. thisIndex := numberTypes; INC(numberTypes);
  979. IF tag = sfInvisible THEN visibility := SyntaxTree.Internal; R.RawNum(tag) END;
  980. IF tag = sfHidden THEN visibility := SyntaxTree.Hidden; R.RawNum(tag) END;
  981. IF tag = sfSysFlag THEN R.RawNum(sysflag); R.RawNum(tag) END;
  982. (* UserType2 *)
  983. typtag := tag;
  984. R.RawNum(tag);
  985. baseType := Type();
  986. R.RawString(name);
  987. CASE typtag OF
  988. | sfTypeOpenArray:
  989. IF TraceImport IN Trace THEN
  990. D.Str("Type / User / OpenArr "); D.Str(name); D.Ln
  991. END;
  992. ASSERT(baseType # NIL);
  993. arrayType := SyntaxTree.NewArrayType(Basic.invalidPosition,moduleScope,SyntaxTree.Open);
  994. arrayType.SetArrayBase(baseType);
  995. type := arrayType;
  996. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  997. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  998. | sfTypeStaticArray:
  999. IF TraceImport IN Trace THEN
  1000. D.Str("Type / User / Array ");
  1001. D.Int(len,1); D.Str(name); D.Ln
  1002. END;
  1003. ASSERT(baseType # NIL);
  1004. arrayType :=SyntaxTree.NewArrayType(Basic.invalidPosition,moduleScope,SyntaxTree.Static);
  1005. arrayType.SetArrayBase(baseType);
  1006. type := arrayType;
  1007. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1008. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1009. R.RawNum(len);
  1010. size := SyntaxTree.NewIntegerValue(Basic.invalidPosition,len);
  1011. size.SetType(system.longintType);
  1012. arrayType.SetLength(size);
  1013. | sfTypeOpenMathArray:
  1014. IF TraceImport IN Trace THEN
  1015. D.Str("Type / User / MathArray (open) "); D.Str(name); D.Ln
  1016. END;
  1017. ASSERT(baseType # NIL);
  1018. mathArrayType := SyntaxTree.NewMathArrayType(Basic.invalidPosition,moduleScope,SyntaxTree.Open);
  1019. mathArrayType.SetArrayBase(baseType);
  1020. type := mathArrayType;
  1021. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1022. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1023. | sfTypeTensor:
  1024. IF TraceImport IN Trace THEN
  1025. D.Str("Type / User / Tensor "); D.Str(name); D.Ln
  1026. END;
  1027. mathArrayType := SyntaxTree.NewMathArrayType(Basic.invalidPosition,moduleScope,SyntaxTree.Tensor);
  1028. mathArrayType.SetArrayBase(baseType);
  1029. type := mathArrayType;
  1030. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1031. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1032. | sfTypeStaticMathArray:
  1033. IF TraceImport IN Trace THEN
  1034. D.Str("Type / User / MathArray (Static) ");
  1035. D.Int(len,1); D.Str(name); D.Ln
  1036. END;
  1037. ASSERT(baseType # NIL);
  1038. mathArrayType :=SyntaxTree.NewMathArrayType(Basic.invalidPosition,moduleScope,SyntaxTree.Static);
  1039. mathArrayType.SetArrayBase(baseType);
  1040. type := mathArrayType;
  1041. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1042. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1043. R.RawNum(len);
  1044. size := SyntaxTree.NewIntegerValue(Basic.invalidPosition,len);
  1045. size.SetType(system.longintType);
  1046. mathArrayType.SetLength(size);
  1047. | sfTypePointer:
  1048. IF TraceImport IN Trace THEN
  1049. D.Str("Type / User / Pointer "); D.Str(name); D.Ln
  1050. END;
  1051. pointerType := SyntaxTree.NewPointerType(Basic.invalidPosition,moduleScope);
  1052. type := pointerType;
  1053. pointerType.SetPointerBase(baseType);
  1054. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1055. WITH type: SyntaxTree.PointerType DO
  1056. IF sfUnsafe IN flags THEN type.SetUnsafe(TRUE) END;
  1057. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1058. IF sfDisposable IN flags THEN type.SetDisposable(TRUE) END;
  1059. END;
  1060. | sfTypeRecord:
  1061. IF TraceImport IN Trace THEN
  1062. D.Str("Type / User / Record "); D.Str(name); D.Ln
  1063. END;
  1064. recordScope := SyntaxTree.NewRecordScope(moduleScope);
  1065. recordType := SyntaxTree.NewRecordType(Basic.invalidPosition,moduleScope,recordScope);
  1066. type := recordType;
  1067. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1068. IF sfRealtime IN flags THEN type.SetRealtime(TRUE) END;
  1069. Record(recordType,baseType);
  1070. | sfTypeProcedure:
  1071. IF TraceImport IN Trace THEN
  1072. D.Str("Type / User / Proc "); D.Str(name); D.Ln
  1073. END;
  1074. procedureScope := SyntaxTree.NewProcedureScope(NIL);
  1075. procedureType := SyntaxTree.NewProcedureType(Basic.invalidPosition,moduleScope);
  1076. procedureType.SetReturnType(baseType);
  1077. type := procedureType;
  1078. IF sysflag = sfDelegate THEN procedureType.SetDelegate(TRUE) END;
  1079. R.RawNum(SYSTEM.VAL(LONGINT,flags));
  1080. IF sfWinAPIParam IN flags THEN procedureType.SetCallingConvention(SyntaxTree.WinAPICallingConvention)
  1081. ELSIF sfCParam IN flags THEN procedureType.SetCallingConvention(SyntaxTree.CCallingConvention)
  1082. ELSIF sfDarwinCParam IN flags THEN procedureType.SetCallingConvention(SyntaxTree.DarwinCCallingConvention)
  1083. END;
  1084. IF sfRealtime IN flags THEN procedureType.SetRealtime(TRUE) END;
  1085. ParameterList(callingConvention,procedureScope,procedureType);
  1086. | sfTypeEnumeration:
  1087. IF TraceImport IN Trace THEN
  1088. D.Str("Type / User / Enumerator "); D.Str(name); D.Ln
  1089. END;
  1090. enumerationScope := SyntaxTree.NewEnumerationScope(moduleScope);
  1091. enumerationType := SyntaxTree.NewEnumerationType(Basic.invalidPosition,moduleScope,enumerationScope);
  1092. type := enumerationType;
  1093. enumerationType.SetEnumerationBase(baseType);
  1094. EnumerationList(enumerationScope);
  1095. END;
  1096. IF name # "" THEN
  1097. typeDeclaration := SyntaxTree.NewTypeDeclaration(Basic.invalidPosition,SyntaxTree.NewIdentifier(name));
  1098. typeDeclaration.SetDeclaredType(type);
  1099. type.SetTypeDeclaration(typeDeclaration);
  1100. typeDeclaration.SetAccess(visibility);
  1101. typeDeclaration.SetState(SyntaxTree.Resolved);
  1102. qualifiedType := SyntaxTree.NewQualifiedType(Basic.invalidPosition,moduleScope, SyntaxTree.NewQualifiedIdentifier(Basic.invalidPosition,SyntaxTree.invalidIdentifier,typeDeclaration.name));
  1103. qualifiedType.SetResolved(type);
  1104. type := qualifiedType;
  1105. type.SetTypeDeclaration(typeDeclaration);
  1106. module.moduleScope.AddTypeDeclaration(typeDeclaration); (* do not replace module.moduleScope by parentScope ! *)
  1107. module.moduleScope.EnterSymbol(typeDeclaration,b);
  1108. END;
  1109. allTypes.PutType(thisIndex,type);
  1110. IF TraceImport IN Trace THEN
  1111. D.Str("resolver.AddType "); D.Str(name); D.Str(" "); D.Int(thisIndex,1); D.Str("");
  1112. D.Ln
  1113. END;
  1114. END;
  1115. RETURN type;
  1116. END Type;
  1117. (*
  1118. Inline = {len:Char {c:Char}} 0X
  1119. *)
  1120. PROCEDURE Inline(scope: SyntaxTree.ProcedureScope);
  1121. VAR ch: CHAR; pos, len: LONGINT; array: SyntaxTree.BinaryCode; newcode: SyntaxTree.Code;
  1122. body: SyntaxTree.Body;
  1123. PROCEDURE Append(ch: CHAR);
  1124. BEGIN
  1125. array.Resize(pos+8);
  1126. array.SetBits(pos,8,ORD(ch));
  1127. INC(pos,8);
  1128. END Append;
  1129. BEGIN
  1130. NEW(array,128*8);
  1131. R.Char(ch);pos := 0;
  1132. REPEAT
  1133. len := ORD(ch);
  1134. WHILE len > 0 DO R.Char(ch); Append(ch); DEC(len) END;
  1135. R.Char(ch);
  1136. UNTIL ch = 0X;
  1137. body := SyntaxTree.NewBody(Basic.invalidPosition,scope);
  1138. newcode := SyntaxTree.NewCode(Basic.invalidPosition,body);
  1139. body.SetCode(newcode);
  1140. scope.SetBody(body);
  1141. newcode.SetBinaryCode(array);
  1142. END Inline;
  1143. (* Symbol = [sfObjFlag flag:RawNum] [sfReadOnly] Type name:RawString *)
  1144. PROCEDURE Symbol(parentScope: SyntaxTree.Scope; VAR type: SyntaxTree.Type; VAR name: SyntaxTree.IdentifierString; VAR visibility: SET; VAR untraced, realtime, constructor, operator, isDynamic, isFictive: BOOLEAN; VAR fictiveOffset: LONGINT);
  1145. VAR f,i: LONGINT;
  1146. BEGIN
  1147. IF TraceImport IN Trace THEN
  1148. D.Str("Symbol: --> "); D.Ln
  1149. END;
  1150. untraced := FALSE; realtime := FALSE; constructor := FALSE; isDynamic := FALSE; isFictive := FALSE;
  1151. visibility:=SyntaxTree.Public+SyntaxTree.Protected+SyntaxTree.Internal;
  1152. WHILE tag=sfObjFlag DO
  1153. R.RawNum(f);
  1154. IF f = sfFictive THEN isFictive := TRUE; untraced := TRUE; TRACE(fictiveOffset); R.RawNum(fictiveOffset);
  1155. ELSIF f = sfUntraced THEN untraced := TRUE
  1156. ELSIF f = sfRealtime THEN realtime := TRUE
  1157. ELSIF f = sfOperator THEN operator := TRUE;
  1158. ELSIF f = sfDynamic THEN isDynamic := TRUE;
  1159. ELSE D.Str("Object: unknown objflag"); D.Ln
  1160. END;
  1161. R.RawNum(tag);
  1162. END;
  1163. IF tag=sfReadOnly THEN visibility := visibility * SyntaxTree.ReadOnly; R.RawNum(tag) END;
  1164. type := Type();
  1165. R.RawString(name);
  1166. IF ~operator & (name[0] = "&") THEN
  1167. constructor := TRUE;
  1168. i := 0; REPEAT name[i] := name[i+1]; INC(i) UNTIL name[i] = 0X;
  1169. END;
  1170. IF name = "" THEN
  1171. visibility := visibility * SyntaxTree.Internal;
  1172. END;
  1173. IF TraceImport IN Trace THEN
  1174. D.Str("<-- "); D.Str(name); D.Ln
  1175. END;
  1176. END Symbol;
  1177. (*
  1178. SymbolFile =
  1179. coeOptions:RawSet
  1180. Imports
  1181. [sfSysFlag sysFlags:Number]
  1182. [sfConst {Symbol Value}]
  1183. [sfVar {Symbol}]
  1184. [sfXProcedure {Symbol ParameterList}]
  1185. [sfOperator {Symbol ParameterList [sfInline Inline]}]
  1186. [sfCProcedure {Symbol ParameterList Inline}]
  1187. [sfAlias {Type name:RawString}]
  1188. [sfType {Type}]
  1189. sfEnd
  1190. *)
  1191. PROCEDURE Module;
  1192. VAR flags: SET; untraced, realtime, constructor,operator, isDynamic, isFictive: BOOLEAN; callingConvention: LONGINT; fOffset: LONGINT;
  1193. BEGIN
  1194. R.RawSet(flags);
  1195. Imports;
  1196. R.RawNum(tag);
  1197. flags := {};
  1198. IF tag = sfSysFlag THEN
  1199. R.RawNum(SYSTEM.VAL(LONGINT, flags));
  1200. R.RawNum(tag);
  1201. END;
  1202. IF TraceImport IN Trace THEN D.Str("importing constants"); D.Ln; END;
  1203. IF tag=sfConst THEN R.RawNum(tag);
  1204. WHILE (tag < sfVar) OR (tag > sfEnd) DO
  1205. operator := FALSE;
  1206. Symbol(moduleScope,type,name, visibility,untraced,realtime,constructor,operator, isDynamic, isFictive, fOffset);
  1207. ASSERT(type # NIL);
  1208. value := Value(type);
  1209. constant := SyntaxTree.NewConstant(Basic.invalidPosition,SyntaxTree.NewIdentifier(name));
  1210. constant.SetValue(value);
  1211. constant.SetType(value.type);
  1212. constant.SetAccess(visibility);
  1213. constant.SetState(SyntaxTree.Resolved);
  1214. moduleScope.AddConstant(constant);
  1215. moduleScope.EnterSymbol(constant,b);
  1216. R.RawNum(tag)
  1217. END
  1218. END;
  1219. IF TraceImport IN Trace THEN D.Str("importing variables"); D.Ln; END;
  1220. IF tag=sfVar THEN R.RawNum(tag);
  1221. WHILE (tag < sfXProcedure) OR (tag > sfEnd) DO
  1222. operator := FALSE;
  1223. Symbol(moduleScope,type,name, visibility,untraced,realtime,constructor,operator, isDynamic,isFictive, fOffset);
  1224. ASSERT(type # NIL);
  1225. variable := SyntaxTree.NewVariable(Basic.invalidPosition,SyntaxTree.NewIdentifier(name));
  1226. variable.SetType(type);
  1227. variable.SetAccess(visibility);
  1228. variable.SetState(SyntaxTree.Resolved);
  1229. IF isFictive THEN
  1230. TRACE(fOffset);
  1231. variable.SetFictive(fOffset);
  1232. variable.SetUntraced(TRUE);
  1233. END;
  1234. moduleScope.AddVariable(variable);
  1235. moduleScope.EnterSymbol(variable,b);
  1236. R.RawNum(tag)
  1237. END
  1238. END;
  1239. IF TraceImport IN Trace THEN D.Str("importing procedures"); D.Ln; END;
  1240. IF tag=sfXProcedure THEN R.RawNum(tag);
  1241. WHILE (tag < sfOperator) OR (tag > sfEnd) DO
  1242. operator := FALSE;
  1243. Symbol(moduleScope,type,name, visibility,untraced,realtime,constructor,operator, isDynamic, isFictive, fOffset);
  1244. ASSERT(~(constructor));
  1245. procedureScope := SyntaxTree.NewProcedureScope(moduleScope);
  1246. procedureType := SyntaxTree.NewProcedureType(Basic.invalidPosition,moduleScope);
  1247. procedureType.SetReturnType(type);
  1248. procedure := SyntaxTree.NewProcedure(Basic.invalidPosition,SyntaxTree.NewIdentifier(name),procedureScope);
  1249. procedure.SetType(procedureType);
  1250. procedure.SetAccess(visibility);
  1251. ParameterList(callingConvention,procedureScope,procedureType);
  1252. procedureType.SetRealtime(realtime);
  1253. procedure.SetState(SyntaxTree.Resolved);
  1254. procedure.SetConstructor(constructor);
  1255. moduleScope.AddProcedure(procedure);
  1256. moduleScope.EnterSymbol(procedure,b);
  1257. R.RawNum(tag)
  1258. END
  1259. END;
  1260. IF TraceImport IN Trace THEN D.Str("importing operators"); D.Ln; END;
  1261. IF tag=sfOperator THEN R.RawNum(tag);
  1262. WHILE (tag < sfCProcedure) OR (tag > sfEnd) DO
  1263. operator := TRUE;
  1264. Symbol(moduleScope,type,name, visibility,untraced,realtime,constructor,operator, isDynamic, isFictive, fOffset);
  1265. ASSERT(~(constructor));
  1266. procedureScope := SyntaxTree.NewProcedureScope(moduleScope);
  1267. procedureType := SyntaxTree.NewProcedureType(Basic.invalidPosition,moduleScope);
  1268. procedureType.SetReturnType(type);
  1269. procedureType.SetRealtime(realtime);
  1270. procedure := SyntaxTree.NewOperator(Basic.invalidPosition,SyntaxTree.NewIdentifier(name),procedureScope);
  1271. procedure.SetType(procedureType);
  1272. procedure.SetAccess(visibility);
  1273. procedure(SyntaxTree.Operator).SetDynamic(isDynamic);
  1274. ParameterList(callingConvention,procedureScope,procedureType);
  1275. procedureType.SetCallingConvention(callingConvention);
  1276. procedure.SetState(SyntaxTree.Resolved);
  1277. module.moduleScope.AddProcedure(procedure);
  1278. module.moduleScope.AddOperator(procedure(SyntaxTree.Operator));
  1279. module.moduleScope.EnterSymbol(procedure,b);
  1280. R.RawNum(tag);
  1281. IF tag = sfInline THEN
  1282. Inline(procedureScope);
  1283. procedure.SetInline(TRUE);
  1284. R.RawNum(tag);
  1285. END;
  1286. END
  1287. END;
  1288. IF TraceImport IN Trace THEN D.Str("importing inline procedures"); D.Ln; END;
  1289. IF tag = sfCProcedure THEN R.RawNum(tag);
  1290. WHILE (tag < sfAlias) OR (tag > sfEnd) DO
  1291. operator := FALSE;
  1292. Symbol(moduleScope,type,name, visibility,untraced, realtime, constructor,operator, isDynamic, isFictive, fOffset);
  1293. ASSERT(~(constructor));
  1294. procedureScope := SyntaxTree.NewProcedureScope(moduleScope);
  1295. procedureType := SyntaxTree.NewProcedureType(Basic.invalidPosition,moduleScope);
  1296. procedure := SyntaxTree.NewProcedure(Basic.invalidPosition,SyntaxTree.NewIdentifier(name),procedureScope);
  1297. procedureType.SetReturnType(type);
  1298. procedure.SetInline(TRUE);
  1299. procedure.SetType(procedureType);
  1300. procedure.SetAccess(visibility);
  1301. ParameterList(callingConvention,procedureScope,procedureType);
  1302. procedure.SetState(SyntaxTree.Resolved);
  1303. module.moduleScope.AddProcedure(procedure);
  1304. module.moduleScope.EnterSymbol(procedure,b);
  1305. Inline(procedureScope);
  1306. R.RawNum(tag);
  1307. END
  1308. END;
  1309. IF TraceImport IN Trace THEN D.Str("importing type declaration aliases"); D.Ln; END;
  1310. IF tag=sfAlias THEN R.RawNum(tag);
  1311. WHILE (tag < sfType) OR (tag > sfEnd) DO
  1312. type := Type();
  1313. R.RawString(name);
  1314. IF TraceImport IN Trace THEN D.Str("alias:"); D.Str(name); D.Ln END;
  1315. typeDeclaration := SyntaxTree.NewTypeDeclaration(Basic.invalidPosition,SyntaxTree.NewIdentifier(name));
  1316. typeDeclaration.SetDeclaredType(type);
  1317. visibility := SyntaxTree.Public+SyntaxTree.Protected+SyntaxTree.Internal;
  1318. typeDeclaration.SetAccess(visibility);
  1319. typeDeclaration.SetState(SyntaxTree.Resolved);
  1320. IF ~(type IS SyntaxTree.BasicType) THEN
  1321. type.SetTypeDeclaration(typeDeclaration);
  1322. END;
  1323. module.moduleScope.AddTypeDeclaration(typeDeclaration);
  1324. module.moduleScope.EnterSymbol(typeDeclaration,b);
  1325. R.RawNum(tag)
  1326. END
  1327. END;
  1328. IF TraceImport IN Trace THEN D.Str("importing type declaration"); D.Ln; END;
  1329. IF tag=sfType THEN
  1330. R.RawNum(tag);
  1331. WHILE tag # sfEnd DO
  1332. type := Type();
  1333. R.RawNum(tag)
  1334. END
  1335. END;
  1336. END Module;
  1337. PROCEDURE InitBasic(type: SyntaxTree.Type; tag: LONGINT);
  1338. BEGIN
  1339. predefType[tag] := type;
  1340. END InitBasic;
  1341. PROCEDURE Init;
  1342. BEGIN
  1343. (*Built-In types*)
  1344. InitBasic(system.booleanType,sfTypeBoolean);
  1345. InitBasic(system.characterType,sfTypeChar8);
  1346. InitBasic(Global.Character16,sfTypeChar16);
  1347. InitBasic(Global.Character32,sfTypeChar32);
  1348. InitBasic(system.shortintType, sfTypeShortint);
  1349. InitBasic(system.integerType, sfTypeInteger);
  1350. InitBasic(system.longintType, sfTypeLongint);
  1351. InitBasic(system.hugeintType, sfTypeHugeint);
  1352. InitBasic(Global.Unsigned8, sfTypeUnsigned8);
  1353. InitBasic(Global.Unsigned16, sfTypeUnsigned16);
  1354. InitBasic(Global.Unsigned32, sfTypeUnsigned32);
  1355. InitBasic(Global.Unsigned64, sfTypeUnsigned64);
  1356. InitBasic(Global.Float32, sfTypeReal);
  1357. InitBasic(Global.Float64, sfTypeLongreal);
  1358. InitBasic(system.setType, sfTypeSet);
  1359. InitBasic(system.anyType, sfTypeAny);
  1360. InitBasic(system.objectType, sfTypeObject);
  1361. InitBasic(system.nilType, sfTypeNilType);
  1362. InitBasic(NIL, sfTypeNoType);
  1363. InitBasic(system.byteType, sfTypeByte);
  1364. InitBasic(system.sizeType, sfTypeSize);
  1365. InitBasic(system.addressType, sfTypeAddress);
  1366. END Init;
  1367. BEGIN
  1368. Init;
  1369. i := 0; numberTypes := 0; numberReimports := 0;
  1370. COPY(moduleName,fileName);
  1371. NEW(allTypes,32); NEW(indexToAttribute,32);
  1372. ASSERT(fileName # "SYSTEM");
  1373. IF ~OpenSymFile(fileName, path, extension, R, version) THEN (*! reintroduce flexible extension *)
  1374. RETURN NIL
  1375. END;
  1376. IF TraceImport IN Trace THEN
  1377. D.Str("BINARY SYMBOL FILE IMPORT "); D.Str(moduleName); D.Ln;
  1378. END;
  1379. (* as the context is not encoded in the symbol file, we have to deduce it from the filename, this is ugly but necessary
  1380. to keep consistency with old compiler
  1381. *)
  1382. Global.ContextFromName(moduleName,moduleIdentifier,contextIdentifier);
  1383. moduleScope := SyntaxTree.NewModuleScope();
  1384. module:= SyntaxTree.NewModule(fileName,Basic.invalidPosition,moduleIdentifier,moduleScope,Scanner.Uppercase);
  1385. module.SetContext(contextIdentifier);
  1386. IF importCache = NIL THEN importCache := SyntaxTree.NewModuleScope(); END;
  1387. Module;
  1388. stamp := Kernel.GetTicks();
  1389. NEW(resolver,system,SELF,importCache);
  1390. resolver.Resolve(module,allTypes);
  1391. module.SetState(SyntaxTree.Resolved);
  1392. IF TraceImport IN Trace THEN
  1393. D.Str("BINARY SYMBOL FILE IMPORT DONE "); D.Str(moduleName); D.Ln;
  1394. END;
  1395. (* if import error then module := NIL *)
  1396. RETURN module
  1397. END Import;
  1398. PROCEDURE Export*(module: SyntaxTree.Module; importCache: SyntaxTree.ModuleScope): BOOLEAN;
  1399. VAR w: Files.Writer; lookup: TypeToIndex; indexToAttribute: IndexToAttribute; numberType: LONGINT; flags: SET;
  1400. (* Imports = {moduleName:RawString} 0X *)
  1401. PROCEDURE Imports(import: SyntaxTree.Import);
  1402. VAR name: SyntaxTree.IdentifierString;
  1403. BEGIN
  1404. WHILE import # NIL DO
  1405. IF ~Global.IsSystemModule(import.module) THEN
  1406. Global.ModuleFileName(import.module.name,import.module.context,name);
  1407. (*! maybe the context and module name should be stored as different names ? *)
  1408. IF TraceExport IN Trace THEN
  1409. D.Str("import: "); D.Str(name); D.Ln;
  1410. END;
  1411. w.RawString(name);
  1412. END;
  1413. import := import.nextImport;
  1414. END;
  1415. w.RawNum(0); (* end of imports *)
  1416. END Imports;
  1417. (* Value = [RawNum | RawHInt | RawReal | RawLReal | RawString] *)
  1418. PROCEDURE Value(v: SyntaxTree.Value);
  1419. VAR type: SyntaxTree.Type;
  1420. BEGIN
  1421. type := v.type.resolved;
  1422. IF type IS SyntaxTree.BooleanType THEN w.RawNum(SYSTEM.VAL(SHORTINT,v(SyntaxTree.BooleanValue).value))
  1423. ELSIF type IS SyntaxTree.CharacterType THEN w.RawNum(ORD(v(SyntaxTree.CharacterValue).value));
  1424. (*
  1425. ELSIF type = Global.Char16 THEN w.RawNum(ORD(v(SyntaxTree.CharacterValue).value));
  1426. ELSIF type = Global.Char32 THEN w.RawNum(ORD(v(SyntaxTree.CharacterValue).value));
  1427. *)
  1428. ELSIF type IS SyntaxTree.IntegerType THEN w.RawHInt(v(SyntaxTree.IntegerValue).value);
  1429. ELSIF type IS SyntaxTree.SetType THEN w.RawNum(SYSTEM.VAL(LONGINT,v(SyntaxTree.SetValue).value));
  1430. ELSIF type IS SyntaxTree.FloatType THEN
  1431. IF type.sizeInBits = 32 THEN w.RawReal(SHORT(v(SyntaxTree.RealValue).value));
  1432. ELSE w.RawLReal(v(SyntaxTree.RealValue).value);
  1433. END;
  1434. ELSIF type IS SyntaxTree.StringType THEN w.RawLInt(v(SyntaxTree.StringValue).length); w.RawString(v(SyntaxTree.StringValue).value^);
  1435. ELSIF type IS SyntaxTree.NilType THEN
  1436. ELSIF type IS SyntaxTree.ByteType THEN HALT(100)
  1437. ELSIF type IS SyntaxTree.EnumerationType THEN w.RawHInt(v(SyntaxTree.EnumerationValue).value);
  1438. ELSE HALT(200);
  1439. END;
  1440. END Value;
  1441. (*
  1442. Record =
  1443. mode:RawNum priority:Char {variable:Symbol}
  1444. [sfTProcedure {Symbol [name:RawString] ParameterList [sfInline Inline]} ]
  1445. sfEnd
  1446. *)
  1447. PROCEDURE Record(record: SyntaxTree.RecordType);
  1448. VAR scope: SyntaxTree.RecordScope; variable: SyntaxTree.Variable; procedure: SyntaxTree.Procedure; name: SyntaxTree.IdentifierString; flags,mode: SET;
  1449. procedureType: SyntaxTree.ProcedureType; body: SyntaxTree.Body; first: BOOLEAN;
  1450. BEGIN
  1451. scope := record.recordScope;
  1452. IF record.recordScope.bodyProcedure # NIL THEN
  1453. body := record.recordScope.bodyProcedure.procedureScope.body;
  1454. IF body.isActive THEN INCL(mode,sfActive) END;
  1455. IF body.isSafe THEN INCL(mode,sfSafe) END;
  1456. END;
  1457. IF record.IsProtected() THEN INCL(mode,sfProtected) END;
  1458. IF record.pointerType # NIL THEN INCL(mode,sfClass) END;
  1459. w.RawNum(SYSTEM.VAL(LONGINT,mode));
  1460. w.Char(0X); (*! record priority *)
  1461. variable := scope.firstVariable;
  1462. WHILE variable # NIL DO
  1463. ASSERT(variable.type # NIL);
  1464. Symbol(variable.type,variable.name,variable.access,variable.untraced,FALSE, FALSE, FALSE, FALSE, variable.fictive, variable.fictiveOffset);
  1465. variable := variable.nextVariable;
  1466. END;
  1467. procedure := scope.firstProcedure;
  1468. IF procedure # NIL THEN
  1469. w.RawNum(sfTProcedure);
  1470. WHILE procedure # NIL DO
  1471. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1472. IF (procedure.access * SyntaxTree.Internal = procedure.access) THEN (* not exported method *)
  1473. Symbol(procedureType.returnType,procedure.name,procedure.access,FALSE, procedureType.isRealtime,procedure.isConstructor,procedure IS SyntaxTree.Operator, FALSE, FALSE, 0);
  1474. procedure.GetName(name);
  1475. w.RawString(name);
  1476. ELSE (* exported method *)
  1477. Symbol(procedureType.returnType,procedure.name,SyntaxTree.Public (*! for compatiblity should be procedure.access *),
  1478. FALSE, procedureType.isRealtime,procedure.isConstructor, procedure IS SyntaxTree.Operator, FALSE, FALSE, 0
  1479. );
  1480. END;
  1481. ParameterList(procedure.type(SyntaxTree.ProcedureType));
  1482. (*! inline *)
  1483. procedure := procedure.nextProcedure;
  1484. END;
  1485. END;
  1486. w.RawNum(sfEnd);
  1487. END Record;
  1488. (* returns the index of module importedModule in the list of module module *)
  1489. PROCEDURE ModuleIndex(module: SyntaxTree.Module; importedModule: SyntaxTree.Module): LONGINT;
  1490. VAR import: SyntaxTree.Import; index: LONGINT;
  1491. BEGIN import := module.moduleScope.firstImport;
  1492. index := 0;
  1493. WHILE (import # NIL) & (import.module # importedModule) DO
  1494. IF (* (import.direct) & *) ~Global.IsSystemModule(import.module) THEN INC(index) END;
  1495. import := import.nextImport;
  1496. END;
  1497. ASSERT(import # NIL);
  1498. RETURN index;
  1499. END ModuleIndex;
  1500. (*
  1501. Type =
  1502. TypeReference
  1503. |BasicType
  1504. |ImportedType
  1505. |UserType.
  1506. TypeReference = number:RawNum(<0)
  1507. BasicType = sfTypeBoolean | .. | sfLastType.
  1508. ImportedType = ModuleNumber (structName:RawString | 0X typeIndex:RawNum)
  1509. ModuleNumber = sfMod1 | .. | sfModOther-1 | sfModOther moduleNumber:RawNum
  1510. UserType = [sfInvisible] [sfSysFlag sysFlag:RawNum] UserType2
  1511. UserType2=
  1512. sfTypeOpenArray baseType:Type name:RawString flags:RawNum
  1513. |sfTypeStaticArray baseType:Type name:RawString flags:RawNum length:RawNum
  1514. |sfOpenMathArray baseType:Type name:RawString
  1515. |sfStaticMathArray baseType:Type name:RawString length:RawNum
  1516. |sfTypeTensor baseType:Type name:RawString
  1517. |sfTypePointer baseType:Type name:RawString flags:RawNum
  1518. |sfTypeRecord baseType:Type name:RawString flags:RawNum Record
  1519. |sfTypeProcedure baseType:Type name:RawString flags:RawNum ParameterList
  1520. |sfTypeEnumeration enumerationBase:Type name:RawString
  1521. *)
  1522. PROCEDURE Type(type: SyntaxTree.Type);
  1523. VAR typeIndex,moduleIndex: LONGINT; name:SyntaxTree.IdentifierString; importedModule: SyntaxTree.Module; attribute: Attribute;
  1524. baseType: SyntaxTree.Type; typeDeclaration : SyntaxTree.TypeDeclaration; flags: SET; size: LONGINT;
  1525. BEGIN
  1526. IF type = NIL THEN
  1527. IF TraceExport IN Trace THEN
  1528. D.Str("Type / Basic / NIL "); D.Ln
  1529. END;
  1530. w.RawNum(sfTypeNoType); RETURN
  1531. END;
  1532. type := type.resolved;
  1533. typeDeclaration := type.typeDeclaration;
  1534. IF (typeDeclaration # NIL) & (typeDeclaration.declaredType.resolved # type) THEN typeDeclaration := NIL END;
  1535. size := type.sizeInBits;
  1536. IF type IS SyntaxTree.BasicType THEN (* BasicType *)
  1537. IF type IS SyntaxTree.BooleanType THEN w.RawNum(sfTypeBoolean);
  1538. IF TraceExport IN Trace THEN
  1539. D.Str("Type / Basic / Boolean "); D.Ln
  1540. END;
  1541. ELSIF type IS SyntaxTree.CharacterType THEN
  1542. IF size = 8 THEN
  1543. w.RawNum(sfTypeChar8);
  1544. IF TraceExport IN Trace THEN
  1545. D.Str("Type / Basic / Char8"); D.Ln
  1546. END;
  1547. ELSIF size = 16 THEN
  1548. w.RawNum(sfTypeChar16);
  1549. IF TraceExport IN Trace THEN
  1550. D.Str("Type / Basic / Char16"); D.Ln
  1551. END;
  1552. ELSIF size = 32 THEN
  1553. w.RawNum(sfTypeChar32);
  1554. IF TraceExport IN Trace THEN
  1555. D.Str("Type / Basic / Char32"); D.Ln
  1556. END;
  1557. END
  1558. ELSIF type IS SyntaxTree.IntegerType THEN
  1559. IF type(SyntaxTree.IntegerType).signed THEN
  1560. IF size = 8 THEN
  1561. w.RawNum(sfTypeShortint);
  1562. IF TraceExport IN Trace THEN
  1563. D.Str("Type / Basic / Shortint"); D.Ln
  1564. END;
  1565. ELSIF size = 16 THEN
  1566. w.RawNum(sfTypeInteger);
  1567. IF TraceExport IN Trace THEN
  1568. D.Str("Type / Basic / Integer"); D.Ln
  1569. END;
  1570. ELSIF size = 32 THEN
  1571. w.RawNum(sfTypeLongint);
  1572. IF TraceExport IN Trace THEN
  1573. D.Str("Type / Basic / Longint"); D.Ln
  1574. END;
  1575. ELSIF size = 64 THEN w.RawNum(sfTypeHugeint);
  1576. IF TraceExport IN Trace THEN
  1577. D.Str("Type / Basic / Hugeint"); D.Ln
  1578. END;
  1579. END;
  1580. ELSE
  1581. IF size = 8 THEN
  1582. w.RawNum(sfTypeUnsigned8);
  1583. IF TraceExport IN Trace THEN
  1584. D.Str("Type / Basic / Unsigned8"); D.Ln
  1585. END;
  1586. ELSIF size = 16 THEN
  1587. w.RawNum(sfTypeUnsigned16);
  1588. IF TraceExport IN Trace THEN
  1589. D.Str("Type / Basic / Unsigned16"); D.Ln
  1590. END;
  1591. ELSIF size = 32 THEN
  1592. w.RawNum(sfTypeUnsigned32);
  1593. IF TraceExport IN Trace THEN
  1594. D.Str("Type / Basic / Unsigned32"); D.Ln
  1595. END;
  1596. ELSIF size = 64 THEN w.RawNum(sfTypeUnsigned64);
  1597. IF TraceExport IN Trace THEN
  1598. D.Str("Type / Basic / Unsigned64"); D.Ln
  1599. END;
  1600. END;
  1601. END;
  1602. ELSIF type IS SyntaxTree.FloatType THEN
  1603. IF size = 32 THEN
  1604. w.RawNum(sfTypeReal);
  1605. IF TraceExport IN Trace THEN
  1606. D.Str("Type / Basic / Real"); D.Ln
  1607. END;
  1608. ELSIF size = 64 THEN
  1609. w.RawNum(sfTypeLongreal);
  1610. IF TraceExport IN Trace THEN
  1611. D.Str("Type / Basic / Longreal"); D.Ln
  1612. END;
  1613. END;
  1614. ELSIF type IS SyntaxTree.ComplexType THEN
  1615. IF size = 64 THEN
  1616. w.RawNum(sfTypeComplex);
  1617. IF TraceExport IN Trace THEN
  1618. D.Str("Type / Basic / Complex"); D.Ln
  1619. END;
  1620. ELSIF size = 128 THEN
  1621. w.RawNum(sfTypeLongcomplex);
  1622. IF TraceExport IN Trace THEN
  1623. D.Str("Type / Basic / Longcomplex"); D.Ln
  1624. END;
  1625. END;
  1626. ELSIF type IS SyntaxTree.SetType THEN
  1627. w.RawNum(sfTypeSet);
  1628. IF TraceExport IN Trace THEN
  1629. D.Str("Type / Basic / Set"); D.Ln
  1630. END;
  1631. ELSIF type IS SyntaxTree.NilType THEN w.RawNum(sfTypeNilType);
  1632. IF TraceExport IN Trace THEN
  1633. D.Str("Type / Basic / NilType"); D.Ln
  1634. END;
  1635. ELSIF type IS SyntaxTree.AnyType THEN w.RawNum(sfTypeAny);
  1636. IF TraceExport IN Trace THEN
  1637. D.Str("Type / Basic / Any"); D.Ln
  1638. END;
  1639. ELSIF type IS SyntaxTree.ObjectType THEN
  1640. w.RawNum(sfTypeObject);
  1641. IF TraceExport IN Trace THEN
  1642. D.Str("Type / Basic / Object"); D.Ln
  1643. END;
  1644. ELSIF type IS SyntaxTree.ByteType THEN
  1645. w.RawNum(sfTypeByte);
  1646. IF TraceExport IN Trace THEN
  1647. D.Str("Type / Basic / Byte"); D.Ln
  1648. END;
  1649. ELSIF type IS SyntaxTree.RangeType THEN w.RawNum(sfTypeRange);
  1650. IF TraceExport IN Trace THEN
  1651. D.Str("Type / Basic / Range"); D.Ln
  1652. END;
  1653. ELSIF type IS SyntaxTree.AddressType THEN w.RawNum(sfTypeAddress) (*! compatibility with PACO *)
  1654. ELSIF type IS SyntaxTree.SizeType THEN w.RawNum(sfTypeSize)
  1655. ELSE HALT(100)
  1656. END;
  1657. ELSIF type IS SyntaxTree.StringType THEN (* special case BasicType : StringType *)
  1658. IF TraceExport IN Trace THEN
  1659. D.Str("Type / String "); D.Ln
  1660. END;
  1661. w.RawNum(sfTypeString); (*! string length should be written here also *)
  1662. ELSIF (typeDeclaration # NIL) & (typeDeclaration.scope # NIL) & (typeDeclaration.scope.ownerModule # module) THEN (* ImportedType *)
  1663. (* imported, reexport:
  1664. ImportedType = ModuleNumber (structName:RawString | 0X typeIndex:RawNum)
  1665. ModuleNumber = sfMod1 | .. | sfModOther-1 | sfModOther moduleNumber:RawNum
  1666. *)
  1667. typeDeclaration.GetName(name);
  1668. importedModule := typeDeclaration.scope.ownerModule;
  1669. moduleIndex := ModuleIndex(module,importedModule);
  1670. ASSERT(moduleIndex >= 0);
  1671. IF moduleIndex >= sfModOther - sfMod1 THEN w.RawNum(sfModOther); w.RawNum(moduleIndex)
  1672. ELSE w.RawNum(sfMod1 + moduleIndex)
  1673. END;
  1674. attribute := indexToAttribute.GetAttribute(moduleIndex);
  1675. typeIndex := attribute.typeToIndex.GetIndex(type);
  1676. IF TraceExport IN Trace THEN
  1677. D.Str("Type / Reexport "); D.Str(name); D.Str(":"); D.Int(typeIndex,1); D.String(" in "); D.Str0(importedModule.name); D.String(":"); D.Int(moduleIndex,1);D.Ln
  1678. END;
  1679. IF typeIndex = Undef THEN (* not yet written import: structName:RawString *)
  1680. type.typeDeclaration.GetName(name);
  1681. w.RawString(name);
  1682. attribute.typeToIndex.PutIndex(type,attribute.numberTypes); INC(attribute.numberTypes);
  1683. ELSE (* previously written import: 0X typeIndex:RawNum *)
  1684. w.Char(0X); w.RawNum(typeIndex);
  1685. END;
  1686. ELSE
  1687. IF TraceExport IN Trace THEN
  1688. D.Str("Type / User "); D.Ln
  1689. END;
  1690. typeIndex := lookup.GetIndex(type);
  1691. IF typeIndex # Undef THEN (* already written: TypeReference = number:RawNum (<0)*)
  1692. IF TraceExport IN Trace THEN
  1693. D.Str("Type / User / AlreadyWritten "); D.Ln
  1694. END;
  1695. w.RawNum(-typeIndex)
  1696. ELSE (* UserType *)
  1697. IF TraceExport IN Trace THEN D.Str("Type / UserType "); D.Ln END;
  1698. lookup.PutIndex(type,numberType); INC(numberType);
  1699. name:="";
  1700. IF typeDeclaration#NIL THEN typeDeclaration.GetName(name);
  1701. IF typeDeclaration.access = SyntaxTree.Hidden THEN
  1702. w.RawNum(sfHidden);
  1703. ELSIF typeDeclaration.access* SyntaxTree.Public={} THEN
  1704. w.RawNum(sfInvisible);
  1705. END;
  1706. END;
  1707. flags := {};
  1708. IF type IS SyntaxTree.RecordType THEN
  1709. IF TraceExport IN Trace THEN D.Str("Type / UserType / RecordType "); D.Str(name); D.Ln END;
  1710. WITH type: SyntaxTree.RecordType DO
  1711. w.RawNum(sfTypeRecord);
  1712. baseType := type.baseType;
  1713. Type(baseType);
  1714. w.RawString(name);
  1715. IF type.isRealtime THEN INCL(flags,sfRealtime) END;
  1716. w.RawNum(SYSTEM.VAL(LONGINT,flags));
  1717. Record(type)
  1718. END
  1719. ELSIF type IS SyntaxTree.PointerType THEN
  1720. IF TraceExport IN Trace THEN D.Str("Type / UserType / PointerType "); D.Str(name); D.Ln END;
  1721. w.RawNum(sfTypePointer);
  1722. Type(type(SyntaxTree.PointerType).pointerBase);
  1723. w.RawString(name);
  1724. WITH type: SyntaxTree.PointerType DO
  1725. IF type.isUnsafe THEN INCL(flags,sfUnsafe) END;
  1726. IF type.isRealtime THEN INCL(flags,sfRealtime) END;
  1727. IF type.isDisposable THEN INCL(flags,sfDisposable) END;
  1728. END;
  1729. w.RawNum(SYSTEM.VAL(LONGINT,flags));
  1730. ELSIF type IS SyntaxTree.ArrayType THEN
  1731. IF TraceExport IN Trace THEN D.Str("Type / UserType / ArrayType "); D.Str(name); D.Ln END;
  1732. WITH type: SyntaxTree.ArrayType DO
  1733. IF type.form = SyntaxTree.Open THEN
  1734. w.RawNum(sfTypeOpenArray)
  1735. ELSIF type.form = SyntaxTree.Static THEN
  1736. w.RawNum(sfTypeStaticArray)
  1737. ELSE HALT(100)
  1738. END;
  1739. Type(type.arrayBase);
  1740. w.RawString(name);
  1741. IF type.isRealtime THEN INCL(flags,sfRealtime) END;
  1742. w.RawNum(SYSTEM.VAL(LONGINT,flags));
  1743. IF type.form = SyntaxTree.Static THEN
  1744. w.RawNum(type.staticLength);
  1745. END;
  1746. END;
  1747. ELSIF type IS SyntaxTree.MathArrayType THEN
  1748. IF TraceExport IN Trace THEN D.Str("Type / UserType / MathArrayType "); D.Str(name); D.Ln END;
  1749. WITH type: SyntaxTree.MathArrayType DO
  1750. IF type.form = SyntaxTree.Open THEN
  1751. w.RawNum(sfTypeOpenMathArray)
  1752. ELSIF type.form = SyntaxTree.Static THEN
  1753. w.RawNum(sfTypeStaticMathArray)
  1754. ELSIF type.form = SyntaxTree.Tensor THEN
  1755. w.RawNum(sfTypeTensor)
  1756. ELSE HALT(100)
  1757. END;
  1758. Type(type.arrayBase);
  1759. w.RawString(name);
  1760. IF type.isRealtime THEN INCL(flags,sfRealtime) END;
  1761. w.RawNum(SYSTEM.VAL(LONGINT,flags));
  1762. IF type.form = SyntaxTree.Static THEN
  1763. w.RawNum(type.staticLength);
  1764. END;
  1765. END;
  1766. ELSIF type IS SyntaxTree.ProcedureType THEN
  1767. IF TraceExport IN Trace THEN D.Str("Type / UserType / ProcedureType"); D.Str(name); D.Ln END;
  1768. WITH type: SyntaxTree.ProcedureType DO
  1769. IF type.isDelegate THEN
  1770. w.RawNum(sfSysFlag); w.RawNum(sfDelegate);
  1771. END;
  1772. w.RawNum(sfTypeProcedure);
  1773. Type(type.returnType);
  1774. w.RawString(name);
  1775. IF type.callingConvention = SyntaxTree.WinAPICallingConvention THEN
  1776. INCL(flags,sfWinAPIParam);
  1777. ELSIF type.callingConvention = SyntaxTree.CCallingConvention THEN
  1778. INCL(flags,sfCParam);
  1779. ELSIF type.callingConvention = SyntaxTree.DarwinCCallingConvention THEN
  1780. INCL(flags,sfDarwinCParam);
  1781. END;
  1782. IF type.isRealtime THEN
  1783. INCL(flags,sfRealtime)
  1784. END;
  1785. w.RawNum(SYSTEM.VAL(LONGINT,flags));
  1786. ParameterList(type);
  1787. END;
  1788. ELSIF type IS SyntaxTree.EnumerationType THEN
  1789. IF TraceExport IN Trace THEN D.Str("Type / UserType / EnumerationType"); D.Str(name); D.Ln END;
  1790. WITH type: SyntaxTree.EnumerationType DO
  1791. w.RawNum(sfTypeEnumeration);
  1792. Type(type.enumerationBase);
  1793. w.RawString(name);
  1794. EnumerationList(type.enumerationScope);
  1795. END;
  1796. ELSE HALT(200)
  1797. END;
  1798. END;
  1799. END;
  1800. END Type;
  1801. (*
  1802. EnumerationList = {name:RawString} 0X;
  1803. *)
  1804. PROCEDURE EnumerationList(enumerationScope: SyntaxTree.EnumerationScope);
  1805. VAR name: SyntaxTree.IdentifierString; enumerator: SyntaxTree.Constant;
  1806. BEGIN
  1807. enumerator := enumerationScope.firstConstant;
  1808. WHILE enumerator # NIL DO
  1809. enumerator.GetName(name);
  1810. IF enumerator.access * SyntaxTree.Public = {} THEN
  1811. w.RawString("@");
  1812. ELSE
  1813. w.RawString(name);
  1814. END;
  1815. Value(enumerator.value.resolved);
  1816. enumerator := enumerator.nextConstant;
  1817. END;
  1818. w.RawString("");
  1819. END EnumerationList;
  1820. (* ParameterList =
  1821. { [sfObjFlag sfWinAPIParam | sfObjFlag sfCParam | sfObjFlag sfDarwinCParam] [sfVar] [sfReadOnly] Type name:RawString } sfEnd
  1822. *)
  1823. PROCEDURE ParameterList(procedureType: SyntaxTree.ProcedureType);
  1824. VAR flags: SET; name: SyntaxTree.IdentifierString;
  1825. PROCEDURE Parameters(parameter: SyntaxTree.Parameter; reverse: BOOLEAN);
  1826. VAR procedureType: SyntaxTree.ProcedureType;
  1827. BEGIN
  1828. WHILE parameter # NIL DO
  1829. (*! the calling convention should not be expressed via the parameters (compatiblity with old compiler) *)
  1830. procedureType := parameter.ownerType(SyntaxTree.ProcedureType);
  1831. IF procedureType.callingConvention = SyntaxTree.WinAPICallingConvention THEN
  1832. w.RawNum(sfObjFlag); w.RawNum(sfWinAPIParam);
  1833. ELSIF procedureType.callingConvention = SyntaxTree.CCallingConvention THEN
  1834. w.RawNum(sfObjFlag); w.RawNum(sfCParam);
  1835. ELSIF procedureType.callingConvention = SyntaxTree.DarwinCCallingConvention THEN
  1836. w.RawNum(sfObjFlag); w.RawNum(sfDarwinCParam);
  1837. END;
  1838. IF parameter.kind = SyntaxTree.VarParameter THEN
  1839. w.RawNum(sfVar)
  1840. ELSIF parameter.kind = SyntaxTree.ConstParameter THEN
  1841. IF (parameter.type.resolved IS SyntaxTree.ArrayType) OR (parameter.type.resolved IS SyntaxTree.RecordType) THEN
  1842. w.RawNum(sfVar);
  1843. END; (* cf. FingerPrint.FPSignature *)
  1844. w.RawNum(sfReadOnly);
  1845. END;
  1846. Type(parameter.type);
  1847. parameter.GetName(name);
  1848. w.RawString(name);
  1849. IF reverse THEN
  1850. parameter := parameter.prevParameter
  1851. ELSE
  1852. parameter := parameter.nextParameter
  1853. END;
  1854. END;
  1855. END Parameters;
  1856. BEGIN
  1857. IF procedureType.callingConvention # SyntaxTree.OberonCallingConvention THEN
  1858. (*! if a procedure has a return type, then it has a return parameter (new)
  1859. ASSERT(procedureType.returnParameter = NIL);
  1860. *)
  1861. Parameters(procedureType.lastParameter,TRUE);
  1862. ELSE
  1863. Parameters(procedureType.firstParameter,FALSE);
  1864. END;
  1865. w.RawNum(sfEnd);
  1866. END ParameterList;
  1867. PROCEDURE Inline(procedureScope: SyntaxTree.ProcedureScope);
  1868. VAR len,count,pos: LONGINT; code: SyntaxTree.Code; ch: CHAR;
  1869. BEGIN
  1870. code := procedureScope.body.code;
  1871. IF code.inlineCode # NIL THEN
  1872. len := code.inlineCode.GetSize() DIV 8;
  1873. ELSE
  1874. len := 0
  1875. END;
  1876. count := 0; pos := 0;
  1877. IF len = 0 THEN
  1878. w.Char(0X);
  1879. ELSE
  1880. WHILE pos < len DO
  1881. IF count = 0 THEN
  1882. count := 255;
  1883. IF len < 255 THEN count := len END;
  1884. w.Char(CHR(count))
  1885. END;
  1886. ch := CHR(code.inlineCode.GetBits(pos*8,8));
  1887. w.Char(ch);
  1888. INC(pos); DEC(count)
  1889. END;
  1890. END;
  1891. w.Char(0X);
  1892. END Inline;
  1893. (* Symbol =
  1894. [sfObjFlag flag:RawNum] [sfReadOnly] Type Name
  1895. *)
  1896. PROCEDURE Symbol(type: SyntaxTree.Type; name: SyntaxTree.Identifier; visibility: SET;untraced, realtime, constructor, operator, isDynamic, isFictive: BOOLEAN; fOffset: LONGINT);
  1897. VAR string,string2: SyntaxTree.IdentifierString;
  1898. BEGIN
  1899. IF TraceExport IN Trace THEN
  1900. Basic.GetString(name,string);
  1901. D.Str("Symbol "); D.Str(string); D.Ln;
  1902. END;
  1903. IF isFictive THEN w.RawNum(sfObjFlag); w.RawNum(sfFictive); TRACE(fOffset); w.RawNum(fOffset);
  1904. ELSIF untraced THEN w.RawNum(sfObjFlag); w.RawNum(sfUntraced)
  1905. ELSIF realtime THEN w.RawNum(sfObjFlag); w.RawNum(sfRealtime)
  1906. END;
  1907. IF operator THEN w.RawNum(sfObjFlag); w.RawNum(sfOperator) END;
  1908. IF isDynamic THEN w.RawNum(sfObjFlag); w.RawNum(sfDynamic) END;
  1909. IF (SyntaxTree.PublicRead IN visibility) & ~(SyntaxTree.PublicWrite IN visibility) THEN
  1910. w.RawNum(sfReadOnly);
  1911. END;
  1912. Type(type);
  1913. IF visibility * SyntaxTree.Internal = visibility THEN
  1914. string2 := "";
  1915. IF constructor THEN string2 := "&" END;
  1916. ELSE Basic.GetString(name,string);
  1917. IF constructor THEN
  1918. Basic.Concat(string2,"&",string,"");
  1919. ELSE
  1920. string2 := string
  1921. END;
  1922. END;
  1923. w.RawString(string2);
  1924. END Symbol;
  1925. (*
  1926. SymbolFile =
  1927. flags:RawSet
  1928. Imports
  1929. [sfSysFlag flags:Number]
  1930. [sfConst {Symbol Value}]
  1931. [sfVar {Symbol}]
  1932. [sfXProcedure {Symbol ParameterList}]
  1933. [sfOperator {Symbol ParameterList [sfInline Inline]}]
  1934. [sfCProcedure {Symbol ParameterList Inline}]
  1935. [sfAlias {declaredType:Type Name}]
  1936. [sfType {declaredType:Type}]
  1937. sfEnd
  1938. *)
  1939. PROCEDURE Module(module: SyntaxTree.Module);
  1940. VAR constant: SyntaxTree.Constant; name: SyntaxTree.IdentifierString; first: BOOLEAN;
  1941. variable: SyntaxTree.Variable; typeDeclaration: SyntaxTree.TypeDeclaration; procedure: SyntaxTree.Procedure;
  1942. procedureType: SyntaxTree.ProcedureType;
  1943. BEGIN
  1944. IF TraceExport IN Trace THEN
  1945. module.GetName(name);
  1946. D.Str("BINARY SYMBOL FILE EXPORT "); D.Str(name); D.Ln;
  1947. END;
  1948. w.RawSet({}); (* compilation flags *)
  1949. (* overloading flags omitted *)
  1950. (* import section: write names of imported modules *)
  1951. Imports(module.moduleScope.firstImport);
  1952. (* constants *)
  1953. IF TraceExport IN Trace THEN
  1954. D.Str("exporting constants "); D.Ln;
  1955. END;
  1956. first :=TRUE;
  1957. constant := module.moduleScope.firstConstant;
  1958. WHILE constant # NIL DO
  1959. IF constant.access * SyntaxTree.Public # {} THEN
  1960. IF first THEN w.RawNum(sfConst); first := FALSE END;
  1961. Symbol(constant.type,constant.name,SyntaxTree.Public (*! for compatiblity should be constant.access *) ,FALSE,FALSE,FALSE,FALSE, FALSE, FALSE, 0);
  1962. constant.GetName(name);
  1963. Value(constant.value.resolved(SyntaxTree.Value))
  1964. END;
  1965. constant := constant.nextConstant;
  1966. END;
  1967. (* variables *)
  1968. IF TraceExport IN Trace THEN
  1969. D.Str("exporting variables "); D.Ln;
  1970. END;
  1971. first := TRUE;
  1972. variable := module.moduleScope.firstVariable;
  1973. WHILE variable # NIL DO
  1974. IF variable.access * SyntaxTree.Public # {} THEN
  1975. IF first THEN w.RawNum(sfVar); first := FALSE END;
  1976. Symbol(variable.type,variable.name,variable.access,variable.untraced, FALSE, FALSE, FALSE, FALSE, variable.fictive, variable.fictiveOffset);
  1977. END;
  1978. variable := variable.nextVariable;
  1979. END;
  1980. (* procedures: normal *)
  1981. IF TraceExport IN Trace THEN
  1982. D.Str("exporting procedures "); D.Ln;
  1983. END;
  1984. first := TRUE;
  1985. procedure := module.moduleScope.firstProcedure;
  1986. WHILE procedure # NIL DO
  1987. IF (procedure.access * SyntaxTree.Public # {}) & ~(procedure IS SyntaxTree.Operator) THEN
  1988. procedureType := procedure.type(SyntaxTree.ProcedureType);
  1989. IF ~procedure.isInline THEN
  1990. IF first THEN w.RawNum(sfXProcedure); first := FALSE END;
  1991. Symbol(procedureType.returnType,procedure.name,SyntaxTree.Public (*! for compatiblity should be procedure.access *),
  1992. FALSE, procedureType.isRealtime, procedure.isConstructor, FALSE, FALSE, FALSE, 0);
  1993. ParameterList(procedureType);
  1994. END;
  1995. END;
  1996. procedure := procedure.nextProcedure;
  1997. END;
  1998. (* procedures: operators *)
  1999. IF TraceExport IN Trace THEN
  2000. D.Str("exporting operators"); D.Ln;
  2001. END;
  2002. first := TRUE;
  2003. procedure := module.moduleScope.firstProcedure;
  2004. WHILE procedure # NIL DO
  2005. IF (procedure.access * SyntaxTree.Public # {}) & (procedure IS SyntaxTree.Operator) THEN
  2006. procedureType := procedure.type(SyntaxTree.ProcedureType);
  2007. IF first THEN w.RawNum(sfOperator); first := FALSE END;
  2008. Symbol(procedureType.returnType,procedure.name,SyntaxTree.Public (*! for compatiblity should be procedure.access *),
  2009. FALSE, procedure.isInline, procedure.isConstructor, FALSE, procedure(SyntaxTree.Operator).isDynamic, FALSE, 0);
  2010. ParameterList(procedureType);
  2011. IF procedure.isInline THEN
  2012. w.RawNum(sfInline); Inline(procedure.procedureScope);
  2013. END;
  2014. END;
  2015. procedure := procedure.nextProcedure;
  2016. END;
  2017. (* procedures: inline *)
  2018. IF TraceExport IN Trace THEN
  2019. D.Str("exporting inline procedures"); D.Ln;
  2020. END;
  2021. first := TRUE;
  2022. procedure := module.moduleScope.firstProcedure;
  2023. WHILE procedure # NIL DO
  2024. IF (procedure.access * SyntaxTree.Public # {}) & ~(procedure IS SyntaxTree.Operator) THEN
  2025. procedureType := procedure.type(SyntaxTree.ProcedureType);
  2026. IF procedure.isInline THEN
  2027. IF first THEN w.RawNum(sfCProcedure); first := FALSE END;
  2028. Symbol(procedureType.returnType,procedure.name,SyntaxTree.Public (*! for compatiblity should be procedure.access *),
  2029. FALSE, procedure.isInline, procedure.isConstructor, FALSE, FALSE, FALSE, 0);
  2030. ParameterList(procedureType);
  2031. Inline(procedure.procedureScope);
  2032. END;
  2033. END;
  2034. procedure := procedure.nextProcedure;
  2035. END;
  2036. (* type declarations: aliases *)
  2037. IF TraceExport IN Trace THEN
  2038. D.Str("exporting type declarations aliases"); D.Ln;
  2039. END;
  2040. first := TRUE;
  2041. typeDeclaration := module.moduleScope.firstTypeDeclaration;
  2042. WHILE typeDeclaration # NIL DO
  2043. IF typeDeclaration.access * SyntaxTree.Public # {} THEN
  2044. IF typeDeclaration.declaredType IS SyntaxTree.QualifiedType THEN
  2045. IF first THEN w.RawNum(sfAlias); first := FALSE END;
  2046. Type(typeDeclaration.declaredType);
  2047. typeDeclaration.GetName(name);
  2048. w.RawString(name);
  2049. END;
  2050. END;
  2051. typeDeclaration := typeDeclaration.nextTypeDeclaration;
  2052. END;
  2053. (* type declarations: declarations *)
  2054. IF TraceExport IN Trace THEN
  2055. D.Str("exporting type declarations"); D.Ln;
  2056. END;
  2057. first := TRUE;
  2058. typeDeclaration := module.moduleScope.firstTypeDeclaration;
  2059. WHILE typeDeclaration # NIL DO
  2060. IF typeDeclaration.access * SyntaxTree.Public # {} THEN
  2061. IF ~(typeDeclaration.declaredType IS SyntaxTree.QualifiedType) THEN
  2062. IF first THEN w.RawNum(sfType); first := FALSE END;
  2063. Type(typeDeclaration.declaredType);
  2064. END;
  2065. END;
  2066. typeDeclaration := typeDeclaration.nextTypeDeclaration;
  2067. END;
  2068. IF TraceExport IN Trace THEN
  2069. module.GetName(name);
  2070. D.Str("BINARY SYMBOL FILE EXPORT DONE "); D.Str(name); D.Ln;
  2071. END;
  2072. w.RawNum(sfEnd);
  2073. END Module;
  2074. BEGIN
  2075. file := Files.New("");
  2076. IF ~noInterfaceCheck THEN
  2077. InterfaceComparison.CompareThis(module,SELF,diagnostics,importCache,flags);
  2078. IF noRedefinition OR noModification THEN
  2079. IF (InterfaceComparison.Redefined IN flags) THEN
  2080. Basic.Error(diagnostics, module.sourceName, Basic.invalidPosition, " no redefinition of symbol file allowed");
  2081. RETURN FALSE;
  2082. END;
  2083. END;
  2084. IF noModification THEN
  2085. IF (InterfaceComparison.Extended IN flags) THEN
  2086. Basic.Error(diagnostics, module.sourceName,Basic.invalidPosition, " no extension of symbol file allowed");
  2087. RETURN FALSE;
  2088. END;
  2089. END;
  2090. END;
  2091. NEW(w,file,0);
  2092. NEW(lookup,100); NEW(indexToAttribute,16);
  2093. numberType := 0;
  2094. Module(module);
  2095. w.Update();
  2096. Files.Register(file);
  2097. RETURN TRUE
  2098. END Export;
  2099. PROCEDURE DefineOptions*(options: Options.Options);
  2100. BEGIN
  2101. options.Add(0X,"symbolFileExtension",Options.String);
  2102. options.Add(0X,"noRedefinition",Options.Flag);
  2103. options.Add(0X,"noModification",Options.Flag);
  2104. options.Add(0X,"noInterfaceCheck",Options.Flag);
  2105. END DefineOptions;
  2106. PROCEDURE GetOptions*(options: Options.Options);
  2107. BEGIN
  2108. IF ~options.GetString("symbolFileExtension",extension) THEN
  2109. extension := Machine.DefaultObjectFileExtension
  2110. END;
  2111. noRedefinition := options.GetFlag("noRedefinition");
  2112. noModification := options.GetFlag("noModification");
  2113. noInterfaceCheck := options.GetFlag("noInterfaceCheck");
  2114. END GetOptions;
  2115. END BinarySymbolFile;
  2116. VAR
  2117. (* move to basic *)
  2118. PROCEDURE MakeFileName(VAR file: ARRAY OF CHAR; CONST name, prefix, suffix: ARRAY OF CHAR);
  2119. VAR i, j: LONGINT;
  2120. BEGIN
  2121. i := 0; WHILE prefix[i] # 0X DO file[i] := prefix[i]; INC(i) END;
  2122. j := 0; WHILE name[j] # 0X DO file[i+j] := name[j]; INC(j) END;
  2123. INC(i, j);
  2124. j := 0; WHILE suffix[j] # 0X DO file[i+j] := suffix[j]; INC(j) END;
  2125. file[i+j] := 0X;
  2126. END MakeFileName;
  2127. (** OpenSymFile - Open a symfile for reading *)
  2128. PROCEDURE OpenSymFile(CONST name,prefix,suffix: ARRAY OF CHAR; VAR r: Streams.Reader; VAR version: CHAR): BOOLEAN;
  2129. VAR res: BOOLEAN; file: Files.FileName; f: Files.File; R: Files.Reader; dummy: LONGINT; ch: CHAR;
  2130. BEGIN
  2131. res := FALSE;
  2132. MakeFileName(file, name, prefix, suffix);
  2133. f := Files.Old(file);
  2134. IF f # NIL THEN
  2135. NEW(R,f,0);
  2136. r := R;
  2137. r.Char(ch);
  2138. IF ch = FileTag THEN
  2139. r.Char(version);
  2140. ASSERT(version = NoZeroCompress); r.Char(version);
  2141. IF version = FileVersion THEN
  2142. r.RawNum(dummy); (*skip symfile size*)
  2143. ELSIF (version >= FileVersionOC) & (version <= FileVersionCurrent) THEN
  2144. r.RawLInt(dummy); (* new in OC: symbol file size uncompressed *)
  2145. ELSE
  2146. HALT(100)
  2147. END;
  2148. res := TRUE
  2149. END
  2150. END;
  2151. RETURN res
  2152. END OpenSymFile;
  2153. PROCEDURE Get*(): Formats.SymbolFileFormat;
  2154. VAR symbolFileFormat: BinarySymbolFile;
  2155. BEGIN
  2156. NEW(symbolFileFormat); symbolFileFormat.file := Files.New(""); RETURN symbolFileFormat
  2157. END Get;
  2158. PROCEDURE Test*(context: Commands.Context);
  2159. VAR moduleName: SyntaxTree.IdentifierString; module: SyntaxTree.Module;
  2160. log2: Basic.Writer; time: LONGINT;
  2161. p: Printout.Printer;
  2162. symbolFileFormat: BinarySymbolFile;
  2163. options: Options.Options;
  2164. extension: Basic.FileName;
  2165. BEGIN
  2166. NEW(options);
  2167. NEW(symbolFileFormat);
  2168. symbolFileFormat.DefineOptions(options);
  2169. IF options.Parse(context.arg,context.error) THEN
  2170. symbolFileFormat.GetOptions(options);
  2171. context.arg.SkipWhitespace; context.arg.String(moduleName);
  2172. time := Kernel.GetTicks();
  2173. symbolFileFormat.Initialize(NIL,Global.DefaultSystem(),"");
  2174. module := symbolFileFormat.Import(moduleName,NIL);
  2175. time := Kernel.GetTicks()-time;
  2176. D.Str("importer elapsed ms: "); D.Int(time,10); D.Ln;
  2177. D.Update;
  2178. log2 := Basic.GetWriter(Basic.GetDebugWriter("SymbolFile"));
  2179. p := Printout.NewPrinter(log2,Printout.SymbolFile,FALSE);
  2180. log2.String("Interface of "); log2.String(moduleName); log2.Ln;
  2181. log2.Ln;
  2182. p.Module(module);
  2183. log2.Ln;
  2184. log2.Ln;
  2185. log2.String(" -------------------------------------------------------------- "); log2.Ln;
  2186. log2.Ln;
  2187. log2.Ln;
  2188. p := Printout.NewPrinter(log2,Printout.All,TRUE);
  2189. p.Module(module);
  2190. log2.Update;
  2191. END;
  2192. END Test;
  2193. END FoxBinarySymbolFile.
  2194. SystemTools.Free FoxBinarySymbolFile ~
  2195. FoxBinarySymbolFile.Test Visualizer ~
  2196. Compiler.Compile -PCtp Visualizer.Sym ~
  2197. FoxBinarySymbolFile.Test Oberon.Oberon ~
  2198. FoxBinarySymbolFile.Test --symbolFileExtension=".Obw" Dump ~