NewSymFileRW.cp 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209
  1. (* ==================================================================== *)
  2. (* *)
  3. (* SymFileRW: Symbol-file reading and writing for GPCP. *)
  4. (* Copyright (c) John Gough 1999 -- 2018. *)
  5. (* *)
  6. (* ==================================================================== *)
  7. MODULE NewSymFileRW;
  8. IMPORT
  9. GPCPcopyright,
  10. RTS,
  11. Error,
  12. Console,
  13. GF := GPFiles,
  14. BF := GPBinFiles,
  15. Id := IdDesc,
  16. D := Symbols,
  17. Lt := LitValue,
  18. Visitor,
  19. ExprDesc,
  20. Ty := TypeDesc,
  21. B := Builtin,
  22. S := CPascalS,
  23. CSt:= CompState,
  24. Nh := NameHash,
  25. FileNames;
  26. (* ========================================================================= *
  27. // Collected syntax ---
  28. //
  29. // SymFile = Header [String (falSy | truSy | <other attribute>)]
  30. // [ VersionName ]
  31. // {Import | Constant | Variable | Type | Procedure}
  32. // TypeList Key.
  33. // -- optional String is external name.
  34. // -- falSy ==> Java class
  35. // -- truSy ==> Java interface
  36. // -- others ...
  37. // Header = magic modSy Name.
  38. // VersionName= numSy longint numSy longint numSy longint.
  39. // -- mj# mn# bld rv# 8xbyte extract
  40. // Import = impSy Name [String] Key.
  41. // -- optional string is explicit external name of class
  42. // Constant = conSy Name Literal.
  43. // Variable = varSy Name TypeOrd.
  44. // Type = typSy Name TypeOrd.
  45. // Procedure = prcSy Name [String] FormalType.
  46. // -- optional string is explicit external name of procedure
  47. // Method = mthSy Name byte byte TypeOrd [String] [Name] FormalType.
  48. // -- optional string is explicit external name of method
  49. // FormalType = [retSy TypeOrd] frmSy {parSy byte TypeOrd [String]} endFm.
  50. // -- optional phrase is return type for proper procedures
  51. // TypeOrd = ordinal.
  52. // TypeHeader = tDefS Ord [fromS Ord Name].
  53. // -- optional phrase occurs if:
  54. // -- type not from this module, i.e. indirect export
  55. // TypeList = start { Array | Record | Pointer | ProcType |
  56. // Enum | Vector | NamedType } close.
  57. // Array = TypeHeader arrSy TypeOrd (Byte | Number | <empty>) endAr.
  58. // -- nullable phrase is array length for fixed length arrays
  59. // Vector = TypeHeader vecSy TypeOrd endAr.
  60. // Pointer = TypeHeader ptrSy TypeOrd.
  61. // Event = TypeHeader evtSy FormalType.
  62. // ProcType = TypeHeader pTpSy FormalType.
  63. // Record = TypeHeader recSy recAtt [truSy | falSy]
  64. // [basSy TypeOrd] [iFcSy {basSy TypeOrd}]
  65. // {Name TypeOrd} {Method} {Statics} endRc.
  66. // -- truSy ==> is an extension of external interface
  67. // -- falSy ==> is an extension of external class
  68. // -- basSy option defines base type, if not ANY / j.l.Object
  69. // Statics = ( Constant | Variable | Procedure ).
  70. // Enum = TypeHeader eTpSy { Constant } endRc.
  71. // NamedType = TypeHeader.
  72. // Name = namSy byte UTFstring.
  73. // Literal = Number | String | Set | Char | Real | falSy | truSy.
  74. // Byte = bytSy byte.
  75. // String = strSy UTFstring.
  76. // Number = numSy longint.
  77. // Real = fltSy ieee-double.
  78. // Set = setSy integer.
  79. // Key = keySy integer..
  80. // Char = chrSy unicode character.
  81. //
  82. // Notes on the syntax:
  83. // All record types must have a Name field, even though this is often
  84. // redundant. The issue is that every record type (including those that
  85. // are anonymous in CP) corresponds to a IR class, and the definer
  86. // and the user of the class _must_ agree on the IR name of the class.
  87. // The same reasoning applies to procedure types, which must have equal
  88. // interface names in all modules.
  89. //
  90. // Notes on the fine print about UTFstring --- November 2011 clarification.
  91. // The character sequence in the symbol file is modified UTF-8, that is
  92. // it may represent CHR(0), U+0000, by the bytes 0xC0, 0x80. String
  93. // constants may thus contain embedded nulls.
  94. //
  95. // ======================================================================== *)
  96. CONST
  97. modSy = ORD('H'); namSy = ORD('$'); bytSy = ORD('\');
  98. numSy = ORD('#'); chrSy = ORD('c'); strSy = ORD('s');
  99. fltSy = ORD('r'); falSy = ORD('0'); truSy = ORD('1');
  100. impSy = ORD('I'); setSy = ORD('S'); keySy = ORD('K');
  101. conSy = ORD('C'); typSy = ORD('T'); tDefS = ORD('t');
  102. prcSy = ORD('P'); retSy = ORD('R'); mthSy = ORD('M');
  103. varSy = ORD('V'); parSy = ORD('p'); start = ORD('&');
  104. close = ORD('!'); recSy = ORD('{'); endRc = ORD('}');
  105. frmSy = ORD('('); fromS = ORD('@'); endFm = ORD(')');
  106. arrSy = ORD('['); endAr = ORD(']'); pTpSy = ORD('%');
  107. ptrSy = ORD('^'); basSy = ORD('+'); eTpSy = ORD('e');
  108. iFcSy = ORD('~'); evtSy = ORD('v'); vecSy = ORD('*');
  109. eofSy = -1;
  110. CONST
  111. magic = 0DEADD0D0H;
  112. syMag = 0D0D0DEADH;
  113. dumped* = -1;
  114. buffDefault = 1024;
  115. logPrefix = "Rlog ";
  116. (* ============================================================ *)
  117. TYPE
  118. SymFile = POINTER TO RECORD
  119. file : BF.FILE;
  120. cSum : INTEGER;
  121. modS : Id.BlkId;
  122. iNxt : INTEGER;
  123. oNxt : INTEGER;
  124. work : D.TypeSeq;
  125. (* Recycled scratch area *)
  126. buff : POINTER TO ARRAY OF UBYTE;
  127. END;
  128. TYPE
  129. SymFileReader* = POINTER TO RECORD
  130. file : BF.FILE;
  131. modS : Id.BlkId;
  132. impS : Id.BlkId;
  133. sSym : INTEGER;
  134. cAtt : CHAR;
  135. iAtt : INTEGER;
  136. lAtt : LONGINT;
  137. rAtt : REAL;
  138. rScp : ImpResScope;
  139. strLen : INTEGER;
  140. strAtt : Lt.CharOpen;
  141. oArray : D.IdSeq;
  142. sArray : D.ScpSeq; (* These two sequences *)
  143. tArray : D.TypeSeq; (* must be private as *)
  144. END; (* file parses overlap. *)
  145. (* ============================================================ *)
  146. TYPE ImpResScope = POINTER TO RECORD
  147. work : D.ScpSeq; (* Direct and ind imps. *)
  148. host : Id.BlkId; (* Compilation module. *)
  149. END;
  150. (* ============================================================ *)
  151. TYPE TypeLinker* = POINTER TO RECORD (D.SymForAll) sym : SymFileReader END;
  152. TYPE SymFileSFA* = POINTER TO RECORD (D.SymForAll) sym : SymFile END;
  153. TYPE ResolveAll* = POINTER TO RECORD (D.SymForAll) END;
  154. (* ============================================================ *)
  155. VAR lastKey : INTEGER; (* private state for CPMake *)
  156. fSepArr : ARRAY 2 OF CHAR;
  157. PROCEDURE^ (f : SymFile)EmitType(type : D.Type),NEW;
  158. (* ============================================================ *)
  159. PROCEDURE GetLastKeyVal*() : INTEGER;
  160. BEGIN
  161. RETURN lastKey;
  162. END GetLastKeyVal;
  163. (* ============================================================ *)
  164. (* ======== Various writing utility procedures ======= *)
  165. (* ============================================================ *)
  166. PROCEDURE newSymFile(mod : Id.BlkId) : SymFile;
  167. VAR new : SymFile;
  168. BEGIN
  169. NEW(new);
  170. NEW(new.buff, buffDefault);
  171. (*
  172. * Initialization: cSum starts at zero. Since impOrd of
  173. * the module is zero, impOrd of the imports starts at 1.
  174. *)
  175. new.cSum := 0;
  176. new.iNxt := 1;
  177. new.oNxt := D.tOffset;
  178. new.modS := mod;
  179. D.InitTypeSeq(new.work, 32);
  180. RETURN new;
  181. END newSymFile;
  182. (* ======================================= *)
  183. PROCEDURE (f : SymFile)Write(chr : INTEGER),NEW;
  184. VAR tmp : INTEGER;
  185. BEGIN [UNCHECKED_ARITHMETIC]
  186. (* need to turn off overflow checking here *)
  187. tmp := f.cSum * 2 + chr;
  188. IF f.cSum < 0 THEN INC(tmp) END;
  189. f.cSum := tmp;
  190. BF.WriteByte(f.file, chr);
  191. END Write;
  192. (* ======================================= *
  193. * This method writes a UTF-8 byte sequence that
  194. * represents the input string up to but not
  195. * including the terminating null character.
  196. *)
  197. PROCEDURE (f : SymFile)WriteNameUTF(IN nam : ARRAY OF CHAR),NEW;
  198. VAR num : INTEGER;
  199. idx : INTEGER;
  200. chr : INTEGER;
  201. BEGIN
  202. IF LEN(nam) * 3 > LEN(f.buff) THEN
  203. NEW(f.buff, LEN(nam) * 3);
  204. END;
  205. num := 0;
  206. idx := 0;
  207. chr := ORD(nam[0]);
  208. WHILE chr # 0H DO
  209. IF chr <= 7FH THEN (* [0xxxxxxx] *)
  210. f.buff[num] := USHORT(chr); INC(num);
  211. ELSIF chr <= 7FFH THEN (* [110xxxxx,10xxxxxx] *)
  212. f.buff[num+1] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  213. f.buff[num ] := USHORT(0C0H + chr); INC(num, 2);
  214. ELSE (* [1110xxxx,10xxxxxx,10xxxxxxx] *)
  215. f.buff[num+2] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  216. f.buff[num+1] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  217. f.buff[num ] := USHORT(0E0H + chr); INC(num, 3);
  218. END;
  219. INC(idx); chr := ORD(nam[idx]);
  220. END;
  221. f.Write(num DIV 256);
  222. f.Write(num MOD 256);
  223. FOR idx := 0 TO num-1 DO f.Write(f.buff[idx]) END;
  224. END WriteNameUTF;
  225. (* ======================================= *
  226. * This method writes a UTF-8 byte sequence that
  227. * represents the input string up to but not
  228. * including the final null character. The
  229. * string may include embedded null characters.
  230. * Thus if the last meaningfull character is null
  231. * there will be two nulls at the end.
  232. *)
  233. PROCEDURE (f : SymFile)WriteStringUTF(chOp : Lt.CharOpen),NEW;
  234. VAR num : INTEGER;
  235. len : INTEGER;
  236. idx : INTEGER;
  237. chr : INTEGER;
  238. BEGIN
  239. len := LEN(chOp) - 1; (* Discard "terminating" null *)
  240. IF len * 3 > LEN(f.buff) THEN
  241. NEW(f.buff, len * 3);
  242. END;
  243. num := 0;
  244. FOR idx := 0 TO len - 1 DO
  245. chr := ORD(chOp[idx]);
  246. IF chr = 0 THEN (* [11000000, 10000000] *)
  247. f.buff[num+1] := 080H;
  248. f.buff[num ] := 0C0H; INC(num, 2);
  249. ELSIF chr <= 7FH THEN (* [0xxxxxxx] *)
  250. f.buff[num ] := USHORT(chr); INC(num);
  251. ELSIF chr <= 7FFH THEN (* [110xxxxx,10xxxxxx] *)
  252. f.buff[num+1] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  253. f.buff[num ] := USHORT(0C0H + chr); INC(num, 2);
  254. ELSE (* [1110xxxx,10xxxxxx,10xxxxxxx] *)
  255. f.buff[num+2] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  256. f.buff[num+1] := USHORT(080H + chr MOD 64); chr := chr DIV 64;
  257. f.buff[num ] := USHORT(0E0H + chr); INC(num, 3);
  258. END;
  259. END;
  260. f.Write(num DIV 256);
  261. f.Write(num MOD 256);
  262. FOR idx := 0 TO num-1 DO f.Write(f.buff[idx]) END;
  263. END WriteStringUTF;
  264. (* ======================================= *)
  265. PROCEDURE (f : SymFile)WriteStringForName(nam : Lt.CharOpen),NEW;
  266. BEGIN
  267. f.Write(strSy);
  268. f.WriteNameUTF(nam);
  269. END WriteStringForName;
  270. (* ======================================= *)
  271. PROCEDURE (f : SymFile)WriteStringForLit(str : Lt.CharOpen),NEW;
  272. BEGIN
  273. f.Write(strSy);
  274. f.WriteStringUTF(str);
  275. END WriteStringForLit;
  276. (* ======================================= *)
  277. PROCEDURE (f : SymFile)WriteNameForId(idD : D.Idnt),NEW;
  278. VAR name : Lt.CharOpen;
  279. BEGIN
  280. name := Nh.charOpenOfHash(idD.hash);
  281. f.Write(namSy);
  282. f.Write(idD.vMod);
  283. f.WriteNameUTF(name);
  284. END WriteNameForId;
  285. (* ======================================= *)
  286. PROCEDURE (f : SymFile)WriteChar(chr : CHAR),NEW;
  287. CONST mask = {0 .. 7};
  288. VAR a,b,int : INTEGER;
  289. BEGIN
  290. f.Write(chrSy);
  291. int := ORD(chr);
  292. b := ORD(BITS(int) * mask); int := ASH(int, -8);
  293. a := ORD(BITS(int) * mask);
  294. f.Write(a);
  295. f.Write(b);
  296. END WriteChar;
  297. (* ======================================= *)
  298. PROCEDURE (f : SymFile)Write4B(int : INTEGER),NEW;
  299. CONST mask = {0 .. 7};
  300. VAR a,b,c,d : INTEGER;
  301. BEGIN
  302. d := ORD(BITS(int) * mask); int := ASH(int, -8);
  303. c := ORD(BITS(int) * mask); int := ASH(int, -8);
  304. b := ORD(BITS(int) * mask); int := ASH(int, -8);
  305. a := ORD(BITS(int) * mask);
  306. f.Write(a);
  307. f.Write(b);
  308. f.Write(c);
  309. f.Write(d);
  310. END Write4B;
  311. (* ======================================= *)
  312. PROCEDURE (f : SymFile)Write8B(val : LONGINT),NEW;
  313. BEGIN
  314. f.Write4B(RTS.hiInt(val));
  315. f.Write4B(RTS.loInt(val));
  316. END Write8B;
  317. (* ======================================= *)
  318. PROCEDURE (f : SymFile)WriteNum(val : LONGINT),NEW;
  319. BEGIN
  320. f.Write(numSy);
  321. f.Write8B(val);
  322. END WriteNum;
  323. (* ======================================= *)
  324. PROCEDURE (f : SymFile)WriteReal(flt : REAL),NEW;
  325. VAR rslt : LONGINT;
  326. BEGIN
  327. f.Write(fltSy);
  328. rslt := RTS.realToLongBits(flt);
  329. f.Write8B(rslt);
  330. END WriteReal;
  331. (* ======================================= *)
  332. PROCEDURE (f : SymFile)WriteOrd(ord : INTEGER),NEW;
  333. BEGIN
  334. IF ord <= 7FH THEN
  335. f.Write(ord);
  336. ELSIF ord <= 7FFFH THEN
  337. f.Write(128 + ord MOD 128); (* LS7-bits first *)
  338. f.Write(ord DIV 128); (* MS8-bits next *)
  339. ELSE
  340. ASSERT(FALSE);
  341. END;
  342. END WriteOrd;
  343. (* ======================================= *)
  344. PROCEDURE (f : SymFile)EmitTypeOrd(t : D.Type),NEW;
  345. (*
  346. * This proceedure facilitates the naming rules
  347. * for records and (runtime) classes: -
  348. *
  349. * (1) Classes derived from named record types have
  350. * names synthesized from the record typename.
  351. * (2) If a named pointer is bound to an anon record
  352. * the class takes its name from the pointer name.
  353. * (3) If both the pointer and the record types have
  354. * names, the class is named from the record.
  355. *)
  356. VAR recT : Ty.Record;
  357. (* ------------------------------------ *)
  358. PROCEDURE AddToWorklist(syF :SymFile; tyD : D.Type);
  359. BEGIN
  360. tyD.dump := syF.oNxt; INC(syF.oNxt);
  361. D.AppendType(syF.work, tyD);
  362. IF tyD.idnt = NIL THEN
  363. tyD.idnt := Id.newSfAnonId(tyD.dump);
  364. tyD.idnt.type := tyD;
  365. END;
  366. END AddToWorklist;
  367. (* ------------------------------------ *)
  368. BEGIN
  369. IF t.dump = 0 THEN (* type is not dumped yet *)
  370. WITH t : Ty.Record DO
  371. (*
  372. * We wish to ensure that anonymous records are
  373. * never emitted before their binding pointer
  374. * types. This ensures that we do not need to
  375. * merge types when reading the files.
  376. *)
  377. IF (t.bindTp # NIL) &
  378. (t.bindTp.dump = 0) THEN
  379. AddToWorklist(f, t.bindTp); (* First the pointer... *)
  380. END;
  381. AddToWorklist(f, t); (* Then this record type *)
  382. | t : Ty.Pointer DO
  383. (*
  384. * If a pointer to record is being emitted, and
  385. * the pointer is NOT anonymous, then the class
  386. * is known by the name of the record. Thus the
  387. * record name must be emitted, at least opaquely.
  388. * Furthermore, we must indicate the binding
  389. * relationship between the pointer and record.
  390. * (It is possible that DCode need record size.)
  391. *)
  392. AddToWorklist(f, t); (* First this pointer... *)
  393. IF (t.boundTp # NIL) &
  394. (t.boundTp.dump = 0) &
  395. (t.boundTp IS Ty.Record) THEN
  396. recT := t.boundTp(Ty.Record);
  397. IF recT.bindTp = NIL THEN
  398. AddToWorklist(f, t.boundTp); (* Then the record type *)
  399. END;
  400. END;
  401. ELSE (* All others *)
  402. AddToWorklist(f, t); (* Just add the type. *)
  403. END;
  404. END;
  405. f.WriteOrd(t.dump);
  406. END EmitTypeOrd;
  407. (* ============================================================ *)
  408. (* ======== Various writing procedures ======= *)
  409. (* ============================================================ *)
  410. PROCEDURE (f : SymFile)FormalType(t : Ty.Procedure),NEW;
  411. (*
  412. ** FormalType = [retSy TypeOrd] frmSy {parSy Byte TypeOrd [String]} endFm.
  413. *)
  414. VAR indx : INTEGER;
  415. parI : Id.ParId;
  416. BEGIN
  417. IF t.retType # NIL THEN
  418. f.Write(retSy);
  419. f.EmitTypeOrd(t.retType);
  420. END;
  421. f.Write(frmSy);
  422. FOR indx := 0 TO t.formals.tide-1 DO
  423. parI := t.formals.a[indx];
  424. f.Write(parSy);
  425. f.Write(parI.parMod);
  426. f.EmitTypeOrd(parI.type);
  427. (*
  428. * Emit Optional Parameter name
  429. *)
  430. IF (parI.hash # 0) THEN
  431. f.WriteStringForName(Nh.charOpenOfHash(parI.hash));
  432. END;
  433. END;
  434. f.Write(endFm);
  435. END FormalType;
  436. (* ======================================= *)
  437. PROCEDURE (f : SymFile)EmitConstId(id : Id.ConId),NEW;
  438. VAR conX : ExprDesc.LeafX;
  439. cVal : Lt.Value;
  440. sVal : INTEGER;
  441. (*
  442. ** Constant = conSy Name Literal.
  443. ** Literal = Number | String | Set | Char | Real | falSy | truSy.
  444. *)
  445. BEGIN
  446. conX := id.conExp(ExprDesc.LeafX);
  447. cVal := conX.value;
  448. f.Write(conSy);
  449. f.WriteNameForId(id);
  450. CASE conX.kind OF
  451. | ExprDesc.tBool : f.Write(truSy);
  452. | ExprDesc.fBool : f.Write(falSy);
  453. | ExprDesc.numLt : f.WriteNum(cVal.long());
  454. | ExprDesc.charLt : f.WriteChar(cVal.char());
  455. | ExprDesc.realLt : f.WriteReal(cVal.real());
  456. | ExprDesc.strLt : f.WriteStringForLit(cVal.chOpen());
  457. | ExprDesc.setLt :
  458. f.Write(setSy);
  459. IF cVal # NIL THEN sVal := cVal.int() ELSE sVal := 0 END;
  460. f.Write4B(sVal);
  461. END;
  462. END EmitConstId;
  463. (* ======================================= *)
  464. PROCEDURE (f : SymFile)EmitTypeId(id : Id.TypId),NEW;
  465. (*
  466. ** Type = TypeSy Name TypeOrd.
  467. *)
  468. BEGIN
  469. f.Write(typSy);
  470. f.WriteNameForId(id);
  471. f.EmitTypeOrd(id.type);
  472. END EmitTypeId;
  473. (* ======================================= *)
  474. PROCEDURE (f : SymFile)EmitVariableId(id : Id.VarId),NEW;
  475. (*
  476. ** Variable = varSy Name TypeOrd.
  477. *)
  478. BEGIN
  479. f.Write(varSy);
  480. f.WriteNameForId(id);
  481. f.EmitTypeOrd(id.type);
  482. END EmitVariableId;
  483. (* ======================================= *)
  484. PROCEDURE (f : SymFile)EmitImportId(id : Id.BlkId),NEW;
  485. (*
  486. ** Import = impSy Name.
  487. *)
  488. BEGIN
  489. IF id.namStr = NIL THEN id.SetNameFromHash(id.hash) END;
  490. IF D.need IN id.xAttr THEN
  491. f.Write(impSy);
  492. f.WriteNameForId(id);
  493. IF id.scopeNm # NIL THEN f.WriteStringForName(id.scopeNm) END;
  494. f.Write(keySy);
  495. f.Write4B(id.modKey);
  496. id.impOrd := f.iNxt; INC(f.iNxt);
  497. END;
  498. END EmitImportId;
  499. (* ======================================= *)
  500. PROCEDURE (f : SymFile)EmitProcedureId(id : Id.PrcId),NEW;
  501. (*
  502. ** Procedure = prcSy Name FormalType.
  503. *)
  504. BEGIN
  505. f.Write(prcSy);
  506. f.WriteNameForId(id);
  507. IF id.prcNm # NIL THEN f.WriteStringForName(id.prcNm) END;
  508. IF id.kind = Id.ctorP THEN f.Write(truSy) END;
  509. f.FormalType(id.type(Ty.Procedure));
  510. END EmitProcedureId;
  511. (* ======================================= *)
  512. PROCEDURE (f : SymFile)EmitMethodId(id : Id.MthId),NEW;
  513. (*
  514. ** Method = mthSy Name Byte Byte TypeOrd [strSy ] FormalType.
  515. *)
  516. BEGIN
  517. IF id.kind = Id.fwdMth THEN id := id.resolve(Id.MthId) END;
  518. f.Write(mthSy);
  519. f.WriteNameForId(id);
  520. f.Write(ORD(id.mthAtt));
  521. f.Write(id.rcvFrm.parMod);
  522. f.EmitTypeOrd(id.rcvFrm.type);
  523. IF id.prcNm # NIL THEN f.WriteStringForName(id.prcNm) END;
  524. IF (id.rcvFrm.hash # 0) THEN f.WriteNameForId(id.rcvFrm) END;
  525. f.FormalType(id.type(Ty.Procedure));
  526. END EmitMethodId;
  527. (* ======================================= *)
  528. PROCEDURE moduleOrd(tpId : D.Idnt) : INTEGER;
  529. VAR impM : Id.BlkId;
  530. BEGIN
  531. IF (tpId = NIL) OR
  532. (tpId.dfScp = NIL) OR
  533. (tpId.dfScp.kind = Id.modId) THEN
  534. RETURN 0;
  535. ELSE
  536. impM := tpId.dfScp(Id.BlkId);
  537. IF impM.impOrd = 0 THEN RETURN -1 ELSE RETURN impM.impOrd END;
  538. END;
  539. END moduleOrd;
  540. (* ======================================= *)
  541. PROCEDURE (f : SymFile)isImportedPointer(ptr : Ty.Pointer) : BOOLEAN,NEW;
  542. BEGIN
  543. RETURN (ptr.idnt # NIL) &
  544. (ptr.idnt.dfScp # NIL) &
  545. (ptr.idnt.dfScp # f.modS);
  546. END isImportedPointer;
  547. PROCEDURE (f : SymFile)isImportedRecord(rec : Ty.Record) : BOOLEAN,NEW;
  548. BEGIN
  549. IF rec.bindTp # NIL THEN (* bindTp takes precedence *)
  550. RETURN f.isImportedPointer(rec.bindTp(Ty.Pointer));
  551. ELSIF rec.idnt # NIL THEN
  552. RETURN (rec.idnt.dfScp # NIL) & (rec.idnt.dfScp # f.modS);
  553. ELSE
  554. RETURN FALSE;
  555. END;
  556. END isImportedRecord;
  557. PROCEDURE (f : SymFile)isImportedArray(arr : Ty.Array) : BOOLEAN,NEW;
  558. BEGIN
  559. RETURN (arr.idnt # NIL) &
  560. (arr.idnt.dfScp # NIL) &
  561. (arr.idnt.dfScp # f.modS);
  562. END isImportedArray;
  563. (* ======================================= *)
  564. PROCEDURE (f : SymFile)EmitTypeHeader(t : D.Type),NEW;
  565. (*
  566. ** TypeHeader = typSy Ord [fromS Ord Name].
  567. *)
  568. VAR mod : INTEGER;
  569. idt : D.Idnt;
  570. (* =================================== *)
  571. PROCEDURE warp(id : D.Idnt) : D.Idnt;
  572. BEGIN
  573. IF id.type = CSt.ntvObj THEN RETURN CSt.objId;
  574. ELSIF id.type = CSt.ntvStr THEN RETURN CSt.strId;
  575. ELSIF id.type = CSt.ntvExc THEN RETURN CSt.excId;
  576. ELSIF id.type = CSt.ntvTyp THEN RETURN CSt.clsId;
  577. ELSE RETURN NIL;
  578. END;
  579. END warp;
  580. (* =================================== *)
  581. BEGIN
  582. WITH t : Ty.Record DO
  583. IF t.bindTp = NIL THEN
  584. idt := t.idnt;
  585. ELSIF t.bindTp.dump = 0 THEN
  586. ASSERT(FALSE);
  587. idt := NIL;
  588. ELSE
  589. idt := t.bindTp.idnt;
  590. END;
  591. ELSE
  592. idt := t.idnt;
  593. END;
  594. (*
  595. * mod := moduleOrd(t.idnt);
  596. *)
  597. mod := moduleOrd(idt);
  598. f.Write(tDefS);
  599. f.WriteOrd(t.dump);
  600. (*
  601. * Convert native types back to RTS.nativeXXX, if necessary.
  602. * That is ... if the native module is not explicitly imported.
  603. *)
  604. IF mod = -1 THEN idt := warp(idt); mod := moduleOrd(idt) END;
  605. IF mod # 0 THEN
  606. f.Write(fromS);
  607. f.WriteOrd(mod);
  608. f.WriteNameForId(idt);
  609. IF (mod > (f.iNxt - 1)) OR (mod < 0) THEN
  610. Console.WriteString(idt.dfScp.namStr);
  611. Console.Write(".");
  612. Console.WriteString(idt.namStr);
  613. Console.WriteLn;
  614. END;
  615. END;
  616. END EmitTypeHeader;
  617. (* ======================================= *)
  618. PROCEDURE (f : SymFile)EmitArrOrVecType(t : Ty.Array),NEW;
  619. BEGIN
  620. f.EmitTypeHeader(t);
  621. IF ~f.isImportedArray(t) THEN
  622. IF t.kind = Ty.vecTp THEN f.Write(vecSy) ELSE f.Write(arrSy) END;
  623. f.EmitTypeOrd(t.elemTp);
  624. IF t.length > 127 THEN
  625. f.Write(numSy);
  626. f.Write8B(t.length);
  627. ELSIF t.length > 0 THEN
  628. f.Write(bytSy);
  629. f.Write(t.length);
  630. END;
  631. f.Write(endAr);
  632. END;
  633. END EmitArrOrVecType;
  634. (* ======================================= *)
  635. PROCEDURE (f : SymFile)EmitRecordType(t : Ty.Record),NEW;
  636. VAR index : INTEGER;
  637. field : D.Idnt;
  638. method : D.Idnt;
  639. (*
  640. ** Record = TypeHeader recSy recAtt [truSy | falSy | <others>]
  641. ** [basSy TypeOrd] [iFcSy {basSy TypeOrd}]
  642. ** {Name TypeOrd} {Method} {Statics} endRc.
  643. *)
  644. BEGIN
  645. f.EmitTypeHeader(t);
  646. IF ~f.isImportedRecord(t) THEN
  647. f.Write(recSy);
  648. index := t.recAtt;
  649. IF D.valTp IN t.xAttr THEN INC(index, Ty.valRc) END;
  650. IF D.clsTp IN t.xAttr THEN INC(index, Ty.clsRc) END;
  651. f.Write(index);
  652. (* ########## *)
  653. IF t.recAtt = Ty.iFace THEN
  654. f.Write(truSy);
  655. ELSIF CSt.special OR (D.isFn IN t.xAttr) THEN
  656. f.Write(falSy);
  657. END;
  658. (* ########## *)
  659. IF t.baseTp # NIL THEN (* this is the parent type *)
  660. f.Write(basSy);
  661. f.EmitTypeOrd(t.baseTp);
  662. END;
  663. (* ########## *)
  664. IF t.interfaces.tide > 0 THEN
  665. f.Write(iFcSy);
  666. FOR index := 0 TO t.interfaces.tide-1 DO (* any interfaces *)
  667. f.Write(basSy);
  668. f.EmitTypeOrd(t.interfaces.a[index]);
  669. END;
  670. END;
  671. (* ########## *)
  672. FOR index := 0 TO t.fields.tide-1 DO
  673. field := t.fields.a[index];
  674. IF (field.vMod # D.prvMode) & (field.type # NIL) THEN
  675. f.WriteNameForId(field);
  676. f.EmitTypeOrd(field.type);
  677. END;
  678. END;
  679. FOR index := 0 TO t.methods.tide-1 DO
  680. method := t.methods.a[index];
  681. IF method.vMod # D.prvMode THEN
  682. f.EmitMethodId(method(Id.MthId));
  683. END;
  684. END;
  685. FOR index := 0 TO t.statics.tide-1 DO
  686. field := t.statics.a[index];
  687. IF field.vMod # D.prvMode THEN
  688. CASE field.kind OF
  689. | Id.conId : f.EmitConstId(field(Id.ConId));
  690. | Id.varId : f.EmitVariableId(field(Id.VarId));
  691. | Id.ctorP,
  692. Id.conPrc : f.EmitProcedureId(field(Id.PrcId));
  693. END;
  694. END;
  695. END;
  696. f.Write(endRc);
  697. END;
  698. D.AppendType(f.modS.expRecs, t);
  699. END EmitRecordType;
  700. (* ======================================= *)
  701. PROCEDURE (f : SymFile)EmitEnumType(t : Ty.Enum),NEW;
  702. VAR index : INTEGER;
  703. const : D.Idnt;
  704. (*
  705. ** Enum = TypeHeader eTpSy { constant } endRc.
  706. *)
  707. BEGIN
  708. f.EmitTypeHeader(t);
  709. f.Write(eTpSy);
  710. FOR index := 0 TO t.statics.tide-1 DO
  711. const := t.statics.a[index];
  712. IF const.vMod # D.prvMode THEN f.EmitConstId(const(Id.ConId)) END;
  713. END;
  714. f.Write(endRc);
  715. (* D.AppendType(f.modS.expRecs, t); *)
  716. END EmitEnumType;
  717. (* ======================================= *)
  718. PROCEDURE (f : SymFile)EmitOpaqueType(t : Ty.Opaque),NEW;
  719. BEGIN
  720. f.EmitTypeHeader(t);
  721. END EmitOpaqueType;
  722. (* ======================================= *)
  723. PROCEDURE (f : SymFile)EmitPointerType(t : Ty.Pointer),NEW;
  724. BEGIN
  725. f.EmitTypeHeader(t);
  726. IF ~f.isImportedPointer(t) THEN
  727. f.Write(ptrSy);
  728. f.EmitTypeOrd(t.boundTp);
  729. END;
  730. END EmitPointerType;
  731. (* ======================================= *)
  732. PROCEDURE (f : SymFile)EmitProcedureType(t : Ty.Procedure),NEW;
  733. BEGIN
  734. f.EmitTypeHeader(t);
  735. IF t.isEventType() THEN f.Write(evtSy) ELSE f.Write(pTpSy) END;
  736. f.FormalType(t);
  737. D.AppendType(f.modS.expRecs, t);
  738. END EmitProcedureType;
  739. (* ======================================= *)
  740. PROCEDURE (f : SymFile)EmitType(type : D.Type),NEW;
  741. BEGIN
  742. WITH type : Ty.Array DO f.EmitArrOrVecType(type);
  743. | type : Ty.Record DO f.EmitRecordType(type);
  744. | type : Ty.Opaque DO f.EmitOpaqueType(type);
  745. | type : Ty.Pointer DO f.EmitPointerType(type);
  746. | type : Ty.Procedure DO f.EmitProcedureType(type);
  747. | type : Ty.Enum DO f.EmitEnumType(type);
  748. END;
  749. END EmitType;
  750. PROCEDURE (f : SymFile)EmitTypeList(),NEW;
  751. VAR indx : INTEGER;
  752. type : D.Type;
  753. BEGIN
  754. (*
  755. * We cannot use a FOR loop here, as the tide changes
  756. * during evaluation, as a result of reaching new types.
  757. * (This comment may not be true for the Reflection reader)
  758. *)
  759. indx := 0;
  760. WHILE indx < f.work.tide DO
  761. f.EmitType(f.work.a[indx]);
  762. INC(indx);
  763. END;
  764. END EmitTypeList;
  765. (* ======================================= *)
  766. PROCEDURE EmitSymfileAndComment*(m : Id.BlkId; cmnt1, cmnt2 : Lt.CharOpen);
  767. VAR symVisit : SymFileSFA;
  768. symfile : SymFile;
  769. marker : INTEGER;
  770. fNamePtr : Lt.CharOpen;
  771. (* ----------------------------------- *)
  772. PROCEDURE mkPathName(m : D.Idnt) : Lt.CharOpen;
  773. VAR str : Lt.CharOpen;
  774. BEGIN
  775. str := BOX(CSt.symDir);
  776. IF str[LEN(str) - 2] = GF.fileSep THEN
  777. str := BOX(str^ + D.getName.ChPtr(m)^ + ".cps");
  778. ELSE
  779. str := BOX(str^ + fSepArr + D.getName.ChPtr(m)^ + ".cps");
  780. END;
  781. RETURN str;
  782. END mkPathName;
  783. (* ----------------------------------- *)
  784. (*
  785. ** SymFile = Header [String (falSy | truSy | <others>)]
  786. ** [ VersionName]
  787. ** {Import | Constant | Variable
  788. ** | Type | Procedure | Method} TypeList.
  789. ** Header = magic modSy Name.
  790. ** VersionName= numSy longint numSy longint numSy longint.
  791. ** -- mj# mn# bld rv# 8xbyte extract
  792. *)
  793. BEGIN
  794. (*
  795. * Create the SymFile structure, and open the output file.
  796. *)
  797. symfile := newSymFile(m);
  798. (* Start of alternative gpcp1.2 code *)
  799. IF CSt.symDir # "" THEN
  800. fNamePtr := mkPathName(m);
  801. symfile.file := BF.createPath(fNamePtr);
  802. ELSE
  803. fNamePtr := BOX(D.getName.ChPtr(m)^ + ".cps");
  804. symfile.file := BF.createFile(fNamePtr);
  805. END;
  806. IF symfile.file = NIL THEN
  807. S.SemError.Report(177, 0, 0);
  808. Error.WriteString("Cannot create file <" + fNamePtr^ + ">");
  809. Error.WriteLn;
  810. RETURN;
  811. ELSE
  812. (*
  813. * Emit the symbol file header
  814. *)
  815. IF CSt.verbose THEN CSt.Message("Created " + fNamePtr^) END;
  816. (* End of alternative gpcp1.2 code *)
  817. IF D.rtsMd IN m.xAttr THEN
  818. marker := RTS.loInt(syMag); (* ==> a system module *)
  819. ELSE
  820. marker := RTS.loInt(magic); (* ==> a normal module *)
  821. END;
  822. symfile.Write4B(RTS.loInt(marker));
  823. symfile.Write(modSy);
  824. symfile.WriteNameForId(m);
  825. IF m.scopeNm # NIL THEN (* explicit name *)
  826. symfile.WriteStringForName(m.scopeNm);
  827. symfile.Write(falSy);
  828. END;
  829. (*
  830. * Emit the optional TypeName, if required.
  831. *
  832. * VersionName= numSy longint numSy longint numSy longint.
  833. * -- mj# mn# bld rv# 8xbyte extract
  834. *)
  835. IF m.verNm # NIL THEN
  836. symfile.WriteNum(m.verNm[0] * 100000000L + m.verNm[1]);
  837. symfile.WriteNum(m.verNm[2] * 100000000L + m.verNm[3]);
  838. symfile.WriteNum(m.verNm[4] * 100000000L + m.verNm[5]);
  839. END;
  840. (*
  841. * Create the symbol table visitor, an extension of
  842. * Symbols.SymForAll type. Emit symbols from the scope.
  843. *)
  844. NEW(symVisit);
  845. symVisit.sym := symfile;
  846. symfile.modS.symTb.Apply(symVisit); (* Apply SymFileSFA to sym-tab *)
  847. (*
  848. * Now emit the types on the worklist.
  849. *)
  850. symfile.Write(start);
  851. symfile.EmitTypeList();
  852. symfile.Write(close);
  853. (*
  854. * Now emit the accumulated checksum key symbol.
  855. *)
  856. symfile.Write(keySy);
  857. lastKey := symfile.cSum;
  858. IF CSt.special THEN symfile.Write4B(0) ELSE symfile.Write4B(lastKey) END;
  859. IF cmnt1 # NIL THEN symfile.WriteStringForLit(cmnt1);
  860. IF cmnt2 # NIL THEN symfile.WriteStringForLit(cmnt2) END;
  861. END;
  862. BF.CloseFile(symfile.file);
  863. END;
  864. END EmitSymfileAndComment;
  865. PROCEDURE EmitSymfile*(m : Id.BlkId);
  866. BEGIN
  867. EmitSymfileAndComment(m, NIL, NIL);
  868. END EmitSymfile;
  869. (* ============================================================ *)
  870. (* ======== Various reading utility procedures ======= *)
  871. (* ============================================================ *)
  872. PROCEDURE read(f : BF.FILE) : INTEGER;
  873. BEGIN
  874. RETURN BF.readByte(f);
  875. END read;
  876. (* ======================================= *)
  877. PROCEDURE (rdr : SymFileReader)ReadUTF(), NEW;
  878. CONST
  879. bad = "Bad UTF-8 string";
  880. VAR num : INTEGER;
  881. bNm : INTEGER;
  882. len : INTEGER;
  883. idx : INTEGER;
  884. chr : INTEGER;
  885. fil : BF.FILE;
  886. BEGIN
  887. num := 0;
  888. fil := rdr.file;
  889. (*
  890. * len is the length in bytes of the UTF8 representation
  891. *)
  892. len := read(fil) * 256 + read(fil); (* max length 65k *)
  893. (*
  894. * Worst case the number of chars will equal byte-number.
  895. *)
  896. IF LEN(rdr.strAtt) <= len THEN
  897. NEW(rdr.strAtt, len + 1);
  898. END;
  899. idx := 0;
  900. WHILE idx < len DO
  901. chr := read(fil); INC(idx);
  902. IF chr <= 07FH THEN (* [0xxxxxxx] *)
  903. rdr.strAtt[num] := CHR(chr); INC(num);
  904. ELSIF chr DIV 32 = 06H THEN (* [110xxxxx,10xxxxxx] *)
  905. bNm := chr MOD 32 * 64;
  906. chr := read(fil); INC(idx);
  907. IF chr DIV 64 = 02H THEN
  908. rdr.strAtt[num] := CHR(bNm + chr MOD 64); INC(num);
  909. ELSE
  910. RTS.Throw(bad);
  911. END;
  912. ELSIF chr DIV 16 = 0EH THEN (* [1110xxxx,10xxxxxx,10xxxxxxx] *)
  913. bNm := chr MOD 16 * 64;
  914. chr := read(fil); INC(idx);
  915. IF chr DIV 64 = 02H THEN
  916. bNm := (bNm + chr MOD 64) * 64;
  917. chr := read(fil); INC(idx);
  918. IF chr DIV 64 = 02H THEN
  919. rdr.strAtt[num] := CHR(bNm + chr MOD 64); INC(num);
  920. ELSE
  921. RTS.Throw(bad);
  922. END;
  923. ELSE
  924. RTS.Throw(bad);
  925. END;
  926. ELSE
  927. RTS.Throw(bad);
  928. END;
  929. END;
  930. rdr.strAtt[num] := 0X;
  931. rdr.strLen := num;
  932. END ReadUTF;
  933. (* ======================================= *)
  934. PROCEDURE readChar(f : BF.FILE) : CHAR;
  935. BEGIN
  936. RETURN CHR(read(f) * 256 + read(f));
  937. END readChar;
  938. (* ======================================= *)
  939. PROCEDURE readInt(f : BF.FILE) : INTEGER;
  940. BEGIN [UNCHECKED_ARITHMETIC]
  941. (* overflow checking off here *)
  942. RETURN ((read(f) * 256 + read(f)) * 256 + read(f)) * 256 + read(f);
  943. END readInt;
  944. (* ======================================= *)
  945. PROCEDURE readLong(f : BF.FILE) : LONGINT;
  946. VAR result : LONGINT;
  947. index : INTEGER;
  948. BEGIN [UNCHECKED_ARITHMETIC]
  949. (* overflow checking off here *)
  950. result := read(f);
  951. FOR index := 1 TO 7 DO
  952. result := result * 256 + read(f);
  953. END;
  954. RETURN result;
  955. END readLong;
  956. (* ======================================= *)
  957. PROCEDURE readReal(f : BF.FILE) : REAL;
  958. VAR result : LONGINT;
  959. BEGIN
  960. result := readLong(f);
  961. RETURN RTS.longBitsToReal(result);
  962. END readReal;
  963. (* ======================================= *)
  964. PROCEDURE readOrd(f : BF.FILE) : INTEGER;
  965. VAR chr : INTEGER;
  966. BEGIN
  967. chr := read(f);
  968. IF chr <= 07FH THEN RETURN chr;
  969. ELSE
  970. DEC(chr, 128);
  971. RETURN chr + read(f) * 128;
  972. END;
  973. END readOrd;
  974. (* ============================================================ *)
  975. (* ======== Symbol File Reader ======= *)
  976. (* ============================================================ *)
  977. PROCEDURE newSymFileReader*(mod : Id.BlkId) : SymFileReader;
  978. VAR new : SymFileReader;
  979. BEGIN
  980. NEW(new);
  981. new.modS := mod;
  982. D.InitIdSeq(new.oArray, 4);
  983. D.InitTypeSeq(new.tArray, 8);
  984. D.InitScpSeq(new.sArray, 8);
  985. NEW(new.strAtt, buffDefault);
  986. RETURN new;
  987. END newSymFileReader;
  988. (* ======================================= *)
  989. PROCEDURE^ (f : SymFileReader)SymFile(IN nm : ARRAY OF CHAR),NEW;
  990. (* ======================================= *)
  991. PROCEDURE Abandon(f : SymFileReader);
  992. BEGIN
  993. RTS.Throw("Bad symbol file format" +
  994. Nh.charOpenOfHash(f.impS.hash)^);
  995. END Abandon;
  996. (* ======================================= *)
  997. PROCEDURE (f : SymFileReader)GetSym(),NEW;
  998. VAR file : BF.FILE;
  999. BEGIN
  1000. file := f.file;
  1001. f.sSym := read(file);
  1002. CASE f.sSym OF
  1003. | namSy :
  1004. f.iAtt := read(file); f.ReadUTF();
  1005. | strSy :
  1006. f.ReadUTF();
  1007. | retSy, fromS, tDefS, basSy :
  1008. f.iAtt := readOrd(file);
  1009. | bytSy :
  1010. f.iAtt := read(file);
  1011. | keySy, setSy :
  1012. f.iAtt := readInt(file);
  1013. | numSy :
  1014. f.lAtt := readLong(file);
  1015. | fltSy :
  1016. f.rAtt := readReal(file);
  1017. | chrSy :
  1018. f.cAtt := readChar(file);
  1019. ELSE (* nothing to do *)
  1020. END;
  1021. END GetSym;
  1022. (* ======================================= *)
  1023. PROCEDURE (f : SymFileReader)ReadPast(sym : INTEGER),NEW;
  1024. BEGIN
  1025. IF f.sSym # sym THEN Abandon(f) END;
  1026. f.GetSym();
  1027. END ReadPast;
  1028. (* ======================================= *)
  1029. PROCEDURE (f : SymFileReader)Parse*(scope : Id.BlkId),NEW;
  1030. VAR filNm : Lt.CharOpen;
  1031. fileName : Lt.CharOpen;
  1032. message : Lt.CharOpen;
  1033. marker : INTEGER;
  1034. token : S.Token;
  1035. index : INTEGER;
  1036. BEGIN
  1037. message := NIL;
  1038. token := scope.token;
  1039. IF token = NIL THEN token := S.prevTok END;
  1040. filNm := Nh.charOpenOfHash(scope.hash);
  1041. f.impS := scope;
  1042. D.AppendScope(f.sArray, scope);
  1043. fileName := BOX(filNm^ + ".cps");
  1044. f.file := BF.findOnPath(CSt.cpSymX$, fileName);
  1045. (* #### *)
  1046. IF f.file = NIL THEN
  1047. fileName := BOX("__" + fileName^);
  1048. f.file := BF.findOnPath(CSt.cpSymX$, fileName);
  1049. IF f.file # NIL THEN
  1050. S.SemError.RepSt2(309, filNm, fileName, token.lin, token.col);
  1051. filNm := BOX("__" + filNm^);
  1052. scope.clsNm := filNm;
  1053. END;
  1054. END;
  1055. (* #### *)
  1056. IF f.file = NIL THEN
  1057. (* S.SemError.Report(129, token.lin, token.col); *)
  1058. S.SemError.RepSt1(129, BOX(filNm^ + ".cps"), token.lin, token.col);
  1059. RETURN;
  1060. ELSE
  1061. IF D.weak IN scope.xAttr THEN
  1062. message := BOX("Implicit import " + filNm^);
  1063. ELSE
  1064. message := BOX("Explicit import " + filNm^);
  1065. END;
  1066. marker := readInt(f.file);
  1067. IF marker = RTS.loInt(magic) THEN
  1068. (* normal case, nothing to do *)
  1069. ELSIF marker = RTS.loInt(syMag) THEN
  1070. INCL(scope.xAttr, D.rtsMd);
  1071. ELSE
  1072. (* S.SemError.Report(130, token.lin, token.col); *)
  1073. S.SemError.RepSt1(130, BOX(filNm^ + ".cps"), token.lin, token.col);
  1074. RETURN;
  1075. END;
  1076. f.GetSym();
  1077. f.SymFile(filNm);
  1078. BF.CloseFile(f.file);
  1079. END;
  1080. END Parse;
  1081. (* ============================================ *)
  1082. PROCEDURE testInsert(id : D.Idnt; sc : D.Scope) : D.Idnt;
  1083. VAR ident : D.Idnt;
  1084. PROCEDURE Report(i,s : D.Idnt);
  1085. VAR iS, sS : FileNames.NameString;
  1086. BEGIN
  1087. D.getName.Of(i, iS);
  1088. D.getName.Of(s, sS);
  1089. S.SemError.RepSt2(172, iS, sS, S.line, S.col);
  1090. END Report;
  1091. BEGIN
  1092. IF sc.symTb.enter(id.hash, id) THEN
  1093. ident := id;
  1094. ELSE
  1095. ident := sc.symTb.lookup(id.hash); (* Warp the return Idnt *)
  1096. IF ident.kind # id.kind THEN Report(id, sc); ident := id END;
  1097. END;
  1098. RETURN ident;
  1099. END testInsert;
  1100. (* ============================================ *)
  1101. PROCEDURE Insert(id : D.Idnt; VAR tb : D.SymbolTable);
  1102. VAR ident : D.Idnt;
  1103. PROCEDURE Report(i : D.Idnt);
  1104. VAR iS : FileNames.NameString;
  1105. BEGIN
  1106. D.getName.Of(i, iS);
  1107. S.SemError.RepSt1(172, iS, 1, 1);
  1108. END Report;
  1109. BEGIN
  1110. IF ~tb.enter(id.hash, id) THEN
  1111. ident := tb.lookup(id.hash); (* and test isForeign? *)
  1112. IF ident.kind # id.kind THEN Report(id) END;
  1113. END;
  1114. END Insert;
  1115. (* ============================================ *)
  1116. PROCEDURE InsertInRec(id : D.Idnt; rec : Ty.Record; sfr : SymFileReader);
  1117. (* insert, taking into account possible overloaded methods. *)
  1118. VAR
  1119. ok : BOOLEAN;
  1120. oId : Id.OvlId;
  1121. PROCEDURE Report(i : D.Idnt; IN s : ARRAY OF CHAR);
  1122. VAR iS, sS : FileNames.NameString;
  1123. BEGIN
  1124. D.getName.Of(i, iS);
  1125. S.SemError.RepSt2(172, iS, s, S.line, S.col);
  1126. END Report;
  1127. BEGIN
  1128. Ty.InsertInRec(id,rec,TRUE,oId,ok);
  1129. IF oId # NIL THEN D.AppendIdnt(sfr.oArray,oId); END;
  1130. IF ~ok THEN Report(id, rec.name()) END;
  1131. END InsertInRec;
  1132. (* ============================================ *)
  1133. PROCEDURE (f : SymFileReader)getLiteral() : D.Expr,NEW;
  1134. VAR expr : D.Expr;
  1135. BEGIN
  1136. CASE f.sSym OF
  1137. | truSy : expr := ExprDesc.mkTrueX();
  1138. | falSy : expr := ExprDesc.mkFalseX();
  1139. | numSy : expr := ExprDesc.mkNumLt(f.lAtt);
  1140. | chrSy : expr := ExprDesc.mkCharLt(f.cAtt);
  1141. | fltSy : expr := ExprDesc.mkRealLt(f.rAtt);
  1142. | setSy : expr := ExprDesc.mkSetLt(BITS(f.iAtt));
  1143. | strSy : expr := ExprDesc.mkStrLenLt(f.strAtt, f.strLen);
  1144. END;
  1145. f.GetSym(); (* read past value *)
  1146. RETURN expr;
  1147. END getLiteral;
  1148. (* ============================================ *)
  1149. PROCEDURE (f : SymFileReader)typeOf(ord : INTEGER) : D.Type,NEW;
  1150. VAR newT : D.Type;
  1151. indx : INTEGER;
  1152. BEGIN
  1153. IF ord < D.tOffset THEN (* builtin type *)
  1154. RETURN B.baseTypeArray[ord];
  1155. ELSIF ord - D.tOffset < f.tArray.tide THEN
  1156. RETURN f.tArray.a[ord - D.tOffset];
  1157. ELSE
  1158. indx := f.tArray.tide + D.tOffset;
  1159. REPEAT
  1160. newT := Ty.newTmpTp(); (* a placeholder *)
  1161. newT.dump := indx; INC(indx);
  1162. D.AppendType(f.tArray, newT);
  1163. UNTIL indx > ord;
  1164. RETURN newT;
  1165. END;
  1166. END typeOf;
  1167. (* ============================================ *)
  1168. PROCEDURE (f : SymFileReader)getTypeFromOrd() : D.Type,NEW;
  1169. VAR ord : INTEGER;
  1170. BEGIN
  1171. ord := readOrd(f.file);
  1172. f.GetSym();
  1173. RETURN f.typeOf(ord);
  1174. END getTypeFromOrd;
  1175. (* ============================================ *)
  1176. PROCEDURE (f : SymFileReader)getFormalType(rslt : Ty.Procedure;
  1177. indx : INTEGER) : D.Type,NEW;
  1178. (*
  1179. ** FormalType = [retSy TypeOrd] frmSy {parSy Byte TypeOrd [String]} endFm.
  1180. // -- optional phrase is return type for proper procedures
  1181. *)
  1182. VAR parD : Id.ParId;
  1183. byte : INTEGER;
  1184. BEGIN
  1185. IF f.sSym = retSy THEN
  1186. rslt.retType := f.typeOf(f.iAtt);
  1187. f.GetSym();
  1188. END;
  1189. f.ReadPast(frmSy);
  1190. WHILE f.sSym = parSy DO
  1191. byte := read(f.file);
  1192. parD := Id.newParId();
  1193. parD.parMod := byte;
  1194. parD.varOrd := indx;
  1195. parD.type := f.getTypeFromOrd();
  1196. (* Skip over optional parameter name string *)
  1197. IF f.sSym = strSy THEN (* parD.hash := Nh.enterStr(f.strAtt); *)
  1198. f.GetSym;
  1199. END;
  1200. Id.AppendParam(rslt.formals, parD);
  1201. INC(indx);
  1202. END;
  1203. f.ReadPast(endFm);
  1204. RETURN rslt;
  1205. END getFormalType;
  1206. (* ============================================ *)
  1207. PROCEDURE (f : SymFileReader)pointerType(old : D.Type) : D.Type,NEW;
  1208. (* Assert: the current symbol ptrSy *)
  1209. (* Pointer = TypeHeader ptrSy TypeOrd. *)
  1210. VAR rslt : Ty.Pointer;
  1211. indx : INTEGER;
  1212. junk : D.Type;
  1213. isEvt: BOOLEAN;
  1214. BEGIN
  1215. isEvt := (f.sSym = evtSy);
  1216. indx := readOrd(f.file);
  1217. WITH old : Ty.Pointer DO
  1218. rslt := old;
  1219. (*
  1220. * Check if there is space in the tArray for this
  1221. * element, otherwise expand using typeOf().
  1222. *)
  1223. IF indx - D.tOffset >= f.tArray.tide THEN
  1224. junk := f.typeOf(indx);
  1225. END;
  1226. f.tArray.a[indx - D.tOffset] := rslt.boundTp;
  1227. ELSE
  1228. rslt := Ty.newPtrTp();
  1229. rslt.boundTp := f.typeOf(indx);
  1230. IF isEvt THEN rslt.SetKind(Ty.evtTp) END;
  1231. END;
  1232. f.GetSym();
  1233. RETURN rslt;
  1234. END pointerType;
  1235. (* ============================================ *)
  1236. PROCEDURE (f : SymFileReader)procedureType() : D.Type,NEW;
  1237. (* Assert: the current symbol is pTpSy. *)
  1238. (* ProcType = TypeHeader pTpSy FormalType. *)
  1239. BEGIN
  1240. f.GetSym(); (* read past pTpSy *)
  1241. RETURN f.getFormalType(Ty.newPrcTp(), 0);
  1242. END procedureType;
  1243. (* ============================================ *)
  1244. PROCEDURE (f : SymFileReader)eventType() : D.Type,NEW;
  1245. (* Assert: the current symbol is evtSy. *)
  1246. (* EventType = TypeHeader evtSy FormalType. *)
  1247. BEGIN
  1248. f.GetSym(); (* read past evtSy *)
  1249. RETURN f.getFormalType(Ty.newEvtTp(), 0);
  1250. END eventType;
  1251. (* ============================================ *)
  1252. PROCEDURE (f : SymFileReader)arrayType() : Ty.Array,NEW;
  1253. (* Assert: at entry the current symbol is arrSy. *)
  1254. (* Array = TypeHeader arrSy TypeOrd (Byte | Number | ) endAr. *)
  1255. (* -- nullable phrase is array length for fixed length arrays *)
  1256. VAR rslt : Ty.Array;
  1257. eTyp : D.Type;
  1258. BEGIN
  1259. rslt := Ty.newArrTp();
  1260. rslt.elemTp := f.typeOf(readOrd(f.file));
  1261. f.GetSym();
  1262. IF f.sSym = bytSy THEN
  1263. rslt.length := f.iAtt;
  1264. f.GetSym();
  1265. ELSIF f.sSym = numSy THEN
  1266. rslt.length := SHORT(f.lAtt);
  1267. f.GetSym();
  1268. (* ELSE length := 0 *)
  1269. END;
  1270. f.ReadPast(endAr);
  1271. RETURN rslt;
  1272. END arrayType;
  1273. (* ============================================ *)
  1274. PROCEDURE (f : SymFileReader)vectorType() : Ty.Vector,NEW;
  1275. (* Assert: at entry the current symbol is vecSy. *)
  1276. (* Vector = TypeHeader vecSy TypeOrd endAr. *)
  1277. VAR rslt : Ty.Vector;
  1278. eTyp : D.Type;
  1279. BEGIN
  1280. rslt := Ty.newVecTp();
  1281. rslt.elemTp := f.typeOf(readOrd(f.file));
  1282. f.GetSym();
  1283. f.ReadPast(endAr);
  1284. RETURN rslt;
  1285. END vectorType;
  1286. (* ============================================ *)
  1287. PROCEDURE^ (f : SymFileReader)procedure() : Id.PrcId,NEW;
  1288. PROCEDURE^ (f : SymFileReader)method() : Id.MthId,NEW;
  1289. PROCEDURE^ (f : SymFileReader)constant() : Id.ConId,NEW;
  1290. PROCEDURE^ (f : SymFileReader)variable() : Id.VarId,NEW;
  1291. (* ============================================ *)
  1292. (*
  1293. * Read a record type from the symbol file.
  1294. *)
  1295. PROCEDURE (f : SymFileReader)recordType(old : D.Type) : D.Type,NEW;
  1296. (* Assert: at entry the current symbol is recSy. *)
  1297. (* Record = TypeHeader recSy recAtt [truSy | falSy | <others>] *)
  1298. (* [basSy TypeOrd] [iFcSy {basSy TypeOrd}] *)
  1299. (* {Name TypeOrd} {Method} {Statics} endRc. *)
  1300. CONST
  1301. vlTp = Ty.valRc;
  1302. VAR rslt : Ty.Record;
  1303. fldD : Id.FldId;
  1304. varD : Id.VarId;
  1305. mthD : Id.MthId;
  1306. conD : Id.ConId;
  1307. prcD : Id.PrcId;
  1308. typD : Id.TypId;
  1309. oldS : INTEGER;
  1310. attr : INTEGER;
  1311. mskd : INTEGER;
  1312. BEGIN
  1313. WITH old : Ty.Record DO rslt := old ELSE rslt := Ty.newRecTp() END;
  1314. attr := read(f.file);
  1315. mskd := attr MOD 8;
  1316. (*
  1317. * The recAtt field has two other bits piggy-backed onto it.
  1318. * The noNew Field of xAttr is just added on in the writing
  1319. * and is stripped off here. The valRc field is used to lock
  1320. * in foreign value classes, even though they have basTp # NIL.
  1321. *)
  1322. IF attr >= Ty.clsRc THEN
  1323. DEC(attr,Ty.clsRc); INCL(rslt.xAttr,D.clsTp);
  1324. ELSIF attr >= Ty.valRc THEN
  1325. DEC(attr,Ty.valRc); INCL(rslt.xAttr,D.valTp);
  1326. END;
  1327. rslt.recAtt := attr MOD 8;
  1328. f.GetSym(); (* Get past recSy rAtt *)
  1329. IF f.sSym = falSy THEN
  1330. INCL(rslt.xAttr, D.isFn); (* This record type is foreign *)
  1331. INCL(rslt.xAttr, D.noNew); (* Remove if ctor found later *)
  1332. f.GetSym();
  1333. ELSIF f.sSym = truSy THEN
  1334. INCL(rslt.xAttr, D.isFn); (* This record type is foreign *)
  1335. INCL(rslt.xAttr, D.fnInf); (* This record is an interface *)
  1336. INCL(rslt.xAttr, D.noCpy); (* Record has no __copy__ *)
  1337. INCL(rslt.xAttr, D.noNew); (* Record has no constructor *)
  1338. f.GetSym();
  1339. END;
  1340. (*
  1341. * Do not override extrnNm values set
  1342. * by *Maker.Init for Native* types.
  1343. *)
  1344. IF (f.impS.scopeNm # NIL) & (rslt.extrnNm = NIL) THEN
  1345. rslt.extrnNm := f.impS.scopeNm;
  1346. END;
  1347. IF f.sSym = basSy THEN
  1348. (*
  1349. * Do not override baseTp values set
  1350. * by *Maker.Init for Native* types.
  1351. *)
  1352. IF rslt.baseTp = NIL THEN
  1353. rslt.baseTp := f.typeOf(f.iAtt);
  1354. IF (f.iAtt # Ty.anyRec) & ~(D.valTp IN rslt.xAttr) THEN
  1355. INCL(rslt.xAttr, D.clsTp);
  1356. END;
  1357. END;
  1358. f.GetSym();
  1359. END;
  1360. IF f.sSym = iFcSy THEN
  1361. f.GetSym();
  1362. WHILE f.sSym = basSy DO
  1363. typD := Id.newSfAnonId(f.iAtt);
  1364. typD.type := f.typeOf(f.iAtt);
  1365. D.AppendType(rslt.interfaces, typD.type);
  1366. f.GetSym();
  1367. END;
  1368. END;
  1369. WHILE f.sSym = namSy DO
  1370. fldD := Id.newFldId();
  1371. fldD.SetMode(f.iAtt);
  1372. fldD.hash := Nh.enterStr(f.strAtt);
  1373. fldD.fldNm := BOX(f.strAtt^);
  1374. fldD.type := f.typeOf(readOrd(f.file));
  1375. fldD.recTyp := rslt;
  1376. f.GetSym();
  1377. IF rslt.symTb.enter(fldD.hash, fldD) THEN
  1378. D.AppendIdnt(rslt.fields, fldD);
  1379. END;
  1380. END;
  1381. WHILE (f.sSym = mthSy) OR
  1382. (f.sSym = prcSy) OR
  1383. (f.sSym = varSy) OR
  1384. (f.sSym = conSy) DO
  1385. oldS := f.sSym; f.GetSym();
  1386. IF oldS = mthSy THEN
  1387. mthD := f.method();
  1388. mthD.bndType := rslt;
  1389. mthD.type(Ty.Procedure).receiver := rslt;
  1390. InsertInRec(mthD,rslt,f);
  1391. D.AppendIdnt(rslt.methods, mthD);
  1392. ELSIF oldS = prcSy THEN
  1393. prcD := f.procedure();
  1394. prcD.bndType := rslt;
  1395. InsertInRec(prcD,rslt,f);
  1396. D.AppendIdnt(rslt.statics, prcD);
  1397. IF prcD.kind = Id.ctorP THEN
  1398. IF prcD.type(Ty.Procedure).formals.tide = 0 THEN
  1399. EXCL(rslt.xAttr, D.noNew);
  1400. ELSE
  1401. INCL(rslt.xAttr, D.xCtor);
  1402. END;
  1403. END;
  1404. ELSIF oldS = varSy THEN
  1405. varD := f.variable();
  1406. varD.recTyp := rslt;
  1407. InsertInRec(varD,rslt,f);
  1408. D.AppendIdnt(rslt.statics, varD);
  1409. ELSIF oldS = conSy THEN
  1410. conD := f.constant();
  1411. conD.recTyp := rslt;
  1412. InsertInRec(conD,rslt,f);
  1413. ELSE
  1414. Abandon(f);
  1415. END;
  1416. END;
  1417. (* #### *
  1418. * #### *)
  1419. f.ReadPast(endRc);
  1420. RETURN rslt;
  1421. END recordType;
  1422. (* ============================================ *)
  1423. PROCEDURE (f : SymFileReader)enumType() : D.Type,NEW;
  1424. (* Assert: at entry the current symbol is eTpSy. *)
  1425. (* Enum = TypeHeader eTpSy { Constant} endRc. *)
  1426. VAR rslt : Ty.Enum;
  1427. cnst : D.Idnt;
  1428. BEGIN
  1429. rslt := Ty.newEnuTp();
  1430. f.GetSym(); (* Get past recSy *)
  1431. WHILE f.sSym = conSy DO
  1432. f.GetSym();
  1433. cnst := f.constant();
  1434. Insert(cnst, rslt.symTb);
  1435. D.AppendIdnt(rslt.statics, cnst);
  1436. END;
  1437. f.ReadPast(endRc);
  1438. RETURN rslt;
  1439. END enumType;
  1440. (* ============================================ *)
  1441. PROCEDURE (f : SymFileReader)Type(),NEW;
  1442. (* Type = typSy Name TypeOrd. *)
  1443. VAR newI : Id.TypId;
  1444. oldI : D.Idnt;
  1445. type : D.Type;
  1446. BEGIN
  1447. (*
  1448. * Post: every previously unknown typId 'id'
  1449. * has the property: id.type.idnt = id.
  1450. * If oldI # newT, then the new typId has
  1451. * newT.type.idnt = oldI.
  1452. *)
  1453. newI := Id.newTypId(NIL);
  1454. newI.SetMode(f.iAtt);
  1455. newI.hash := Nh.enterStr(f.strAtt);
  1456. newI.SetNameFromHash(newI.hash);
  1457. newI.type := f.getTypeFromOrd();
  1458. newI.dfScp := f.impS;
  1459. oldI := testInsert(newI, f.impS);
  1460. IF oldI # newI THEN
  1461. f.tArray.a[newI.type.dump - D.tOffset] := oldI.type;
  1462. END;
  1463. (*
  1464. * In the case of symbol files created by J2CPS
  1465. * it is possible that oldI.vMod may be set to the
  1466. * default value private (0), while the real definition
  1467. * in newI should be public. ==> override oldI.vMod !
  1468. *)
  1469. IF newI.type.idnt = NIL THEN newI.type.idnt := oldI; oldI.SetMode(newI.vMod); END;
  1470. END Type;
  1471. (* ============================================ *)
  1472. PROCEDURE (f : SymFileReader)Import(),NEW;
  1473. (* Import = impSy Name [String] Key. *)
  1474. (* -- optional string is external name *)
  1475. (* first symbol should be namSy here. *)
  1476. VAR impD : Id.BlkId;
  1477. oldS : Id.BlkId;
  1478. oldD : D.Idnt;
  1479. BEGIN
  1480. impD := Id.newImpId();
  1481. impD.dfScp := impD; (* ImpId define their own scope *)
  1482. INCL(impD.xAttr, D.weak);
  1483. impD.SetMode(f.iAtt);
  1484. impD.hash := Nh.enterStr(f.strAtt);
  1485. f.ReadPast(namSy);
  1486. IF impD.hash = f.modS.hash THEN (* Importing own imp indirectly *)
  1487. (* Shouldn't this be an error? *)
  1488. D.AppendScope(f.sArray, f.modS);
  1489. IF f.sSym = strSy THEN
  1490. (* probably don't need to do anything here ... *)
  1491. f.GetSym();
  1492. END;
  1493. ELSE (* Importing some other module. *)
  1494. oldD := testInsert(impD, f.modS);
  1495. IF f.sSym = strSy THEN
  1496. impD.scopeNm := Lt.arrToCharOpen(f.strAtt, f.strLen);
  1497. f.GetSym();
  1498. END;
  1499. IF (oldD # impD) & (oldD.kind = Id.impId) THEN
  1500. oldS := oldD(Id.BlkId);
  1501. D.AppendScope(f.sArray, oldS);
  1502. IF (oldS.modKey # 0) & (f.iAtt # oldS.modKey) THEN
  1503. S.SemError.RepSt1(133, (* Detected bad KeyVal *)
  1504. Nh.charOpenOfHash(impD.hash)^,
  1505. S.line, S.col);
  1506. END;
  1507. ELSE
  1508. D.AppendScope(f.sArray, impD);
  1509. END;
  1510. impD.modKey := f.iAtt;
  1511. END;
  1512. f.ReadPast(keySy);
  1513. END Import;
  1514. (* ============================================ *)
  1515. PROCEDURE (f : SymFileReader)constant() : Id.ConId,NEW;
  1516. (* Constant = conSy Name Literal. *)
  1517. (* Name = namSy byte UTFstring. *)
  1518. (* Assert: f.sSym = namSy. *)
  1519. VAR newC : Id.ConId;
  1520. anyI : D.Idnt;
  1521. BEGIN
  1522. newC := Id.newConId();
  1523. newC.SetMode(f.iAtt);
  1524. newC.hash := Nh.enterStr(f.strAtt);
  1525. newC.dfScp := f.impS;
  1526. f.ReadPast(namSy);
  1527. newC.conExp := f.getLiteral();
  1528. newC.type := newC.conExp.type;
  1529. RETURN newC;
  1530. END constant;
  1531. (* ============================================ *)
  1532. PROCEDURE (f : SymFileReader)variable() : Id.VarId,NEW;
  1533. (* Variable = varSy Name TypeOrd. *)
  1534. VAR newV : Id.VarId;
  1535. anyI : D.Idnt;
  1536. BEGIN
  1537. newV := Id.newVarId();
  1538. newV.SetMode(f.iAtt);
  1539. newV.hash := Nh.enterStr(f.strAtt);
  1540. newV.type := f.getTypeFromOrd();
  1541. newV.dfScp := f.impS;
  1542. RETURN newV;
  1543. END variable;
  1544. (* ============================================ *)
  1545. PROCEDURE (f : SymFileReader)procedure() : Id.PrcId,NEW;
  1546. (* Procedure = prcSy Name[String]FormalType. *)
  1547. (* This is a static proc, mths come with Recs *)
  1548. VAR newP : Id.PrcId;
  1549. anyI : D.Idnt;
  1550. BEGIN
  1551. newP := Id.newPrcId();
  1552. newP.setPrcKind(Id.conPrc);
  1553. newP.SetMode(f.iAtt);
  1554. newP.hash := Nh.enterStr(f.strAtt);
  1555. newP.dfScp := f.impS;
  1556. f.ReadPast(namSy);
  1557. IF f.sSym = strSy THEN
  1558. newP.prcNm := Lt.arrToCharOpen(f.strAtt, f.strLen);
  1559. (* and leave scopeNm = NIL *)
  1560. f.GetSym();
  1561. END;
  1562. IF f.sSym = truSy THEN (* ### this is a constructor ### *)
  1563. f.GetSym();
  1564. newP.setPrcKind(Id.ctorP);
  1565. END; (* ### this is a constructor ### *)
  1566. newP.type := f.getFormalType(Ty.newPrcTp(), 0);
  1567. (* IF this is a java module, do some semantic checks *)
  1568. (* ... *)
  1569. RETURN newP;
  1570. END procedure;
  1571. (* ============================================ *)
  1572. PROCEDURE (f : SymFileReader)method() : Id.MthId,NEW;
  1573. (* Method = mthSy Name byte byte TypeOrd [String][Name] FormalType. *)
  1574. VAR newM : Id.MthId;
  1575. rcvD : Id.ParId;
  1576. rFrm : INTEGER;
  1577. mAtt : SET;
  1578. BEGIN
  1579. newM := Id.newMthId();
  1580. newM.SetMode(f.iAtt);
  1581. newM.setPrcKind(Id.conMth);
  1582. newM.hash := Nh.enterStr(f.strAtt);
  1583. newM.dfScp := f.impS;
  1584. IF CSt.verbose THEN newM.SetNameFromHash(newM.hash) END;
  1585. rcvD := Id.newParId();
  1586. rcvD.varOrd := 0;
  1587. (* byte1 is the method attributes *)
  1588. mAtt := BITS(read(f.file));
  1589. (* byte2 is param form of receiver *)
  1590. rFrm := read(f.file);
  1591. (* next 1 or 2 bytes are rcv-type *)
  1592. rcvD.type := f.typeOf(readOrd(f.file));
  1593. f.GetSym();
  1594. rcvD.parMod := rFrm;
  1595. IF f.sSym = strSy THEN
  1596. newM.prcNm := Lt.arrToCharOpen(f.strAtt, f.strLen);
  1597. (* and leave scopeNm = NIL *)
  1598. f.GetSym();
  1599. END;
  1600. (* Skip over optional receiver name string *)
  1601. IF f.sSym = namSy THEN (* rcvD.hash := Nh.enterString(f.strAtt); *)
  1602. f.GetSym();
  1603. END;
  1604. (* End skip over optional receiver name *)
  1605. newM.type := f.getFormalType(Ty.newPrcTp(), 1);
  1606. newM.type.idnt := newM;
  1607. newM.mthAtt := mAtt;
  1608. newM.rcvFrm := rcvD;
  1609. (* IF this is a java module, do some semantic checks *)
  1610. RETURN newM;
  1611. END method;
  1612. (* ============================================ *)
  1613. PROCEDURE (f : SymFileReader)TypeList(),NEW;
  1614. (* TypeList = start { Array | Record | Pointer *)
  1615. (* | ProcType | Vector} close. *)
  1616. (* TypeHeader = tDefS Ord [fromS Ord Name]. *)
  1617. VAR modOrd : INTEGER;
  1618. typOrd : INTEGER;
  1619. typIdx : INTEGER;
  1620. tpDesc : D.Type;
  1621. tpIdnt : Id.TypId;
  1622. prevTp : D.Type;
  1623. impScp : D.Scope;
  1624. basBlk : Id.BlkId;
  1625. linkIx : INTEGER;
  1626. bndTyp : D.Type;
  1627. typeFA : TypeLinker;
  1628. (* ================================ *)
  1629. PROCEDURE getDetails(f : SymFileReader; p : D.Type) : D.Type;
  1630. VAR rslt : D.Type;
  1631. BEGIN
  1632. CASE f.sSym OF
  1633. | arrSy : rslt := f.arrayType();
  1634. | vecSy : rslt := f.vectorType();
  1635. | recSy : rslt := f.recordType(p);
  1636. | pTpSy : rslt := f.procedureType();
  1637. | evtSy : rslt := f.eventType();
  1638. | eTpSy : rslt := f.enumType();
  1639. | ptrSy : rslt := f.pointerType(p);
  1640. ELSE rslt := Ty.newNamTp();
  1641. END;
  1642. RETURN rslt;
  1643. END getDetails;
  1644. (* ================================ *)
  1645. BEGIN
  1646. WHILE f.sSym = tDefS DO
  1647. linkIx := 0;
  1648. tpIdnt := NIL;
  1649. impScp := NIL;
  1650. (* Do type header *)
  1651. typOrd := f.iAtt;
  1652. typIdx := typOrd - D.tOffset;
  1653. prevTp := f.tArray.a[typIdx];
  1654. f.ReadPast(tDefS);
  1655. (*
  1656. * The [fromS modOrd typNam] appears if the type is imported.
  1657. * There are two cases:
  1658. * (1) this is the first time that "mod.typNam" has been
  1659. * seen during this compilation
  1660. * ==> insert a new typId descriptor in mod.symTb
  1661. * (2) this name is already in the mod.symTb table
  1662. * ==> fetch the previous descriptor
  1663. *)
  1664. IF f.sSym = fromS THEN
  1665. modOrd := f.iAtt;
  1666. impScp := f.sArray.a[modOrd];
  1667. f.GetSym();
  1668. tpIdnt := Id.newTypId(NIL);
  1669. tpIdnt.SetMode(f.iAtt);
  1670. tpIdnt.hash := Nh.enterStr(f.strAtt);
  1671. tpIdnt.dfScp := impScp;
  1672. tpIdnt := testInsert(tpIdnt, impScp)(Id.TypId);
  1673. f.ReadPast(namSy);
  1674. tpDesc := getDetails(f, prevTp);
  1675. (*
  1676. * In the new symbol table format we do not wish
  1677. * to include details of indirectly imported types.
  1678. * However, there may be a reference to the bound
  1679. * type of an indirectly imported pointer. In this
  1680. * case we need to make sure that the otherwise
  1681. * bound type declaration catches the same opaque
  1682. * type descriptor.
  1683. *)
  1684. IF tpDesc # NIL THEN
  1685. WITH tpDesc : Ty.Pointer DO
  1686. bndTyp := tpDesc.boundTp;
  1687. IF (bndTyp # NIL) & (bndTyp.kind = Ty.tmpTp) THEN
  1688. linkIx := bndTyp.dump - D.tOffset;
  1689. END;
  1690. ELSE (* skip *)
  1691. END;
  1692. END;
  1693. tpDesc := Ty.newNamTp();
  1694. tpDesc.idnt := tpIdnt;
  1695. IF linkIx # 0 THEN
  1696. ASSERT(linkIx > typIdx);
  1697. f.tArray.a[linkIx] := tpDesc;
  1698. END;
  1699. (*
  1700. * A name has been declared for this type, tpIdnt is
  1701. * the (possibly previously known) id descriptor, and
  1702. * tpDesc is the newly parsed descriptor of the type.
  1703. *)
  1704. IF tpIdnt.type = NIL THEN
  1705. tpIdnt.type := tpDesc;
  1706. ELSE
  1707. tpDesc := tpIdnt.type;
  1708. END;
  1709. IF tpDesc.idnt = NIL THEN tpDesc.idnt := tpIdnt END;
  1710. ELSE
  1711. tpDesc := getDetails(f, prevTp);
  1712. ASSERT(tpDesc # NIL);
  1713. IF (prevTp # NIL) &
  1714. (prevTp.idnt # NIL) THEN
  1715. IF (prevTp.kind = Ty.namTp) &
  1716. (prevTp.idnt.dfScp # f.impS) THEN
  1717. (*
  1718. * This is the special case of an anonymous
  1719. * bound type of an imported pointer. In the
  1720. * new type resolver we want this to remain
  1721. * as an opaque type until *all* symbol files
  1722. * have been fully processed.
  1723. * So ... override the parsed type.
  1724. *)
  1725. tpDesc := prevTp;
  1726. ELSE
  1727. prevTp.idnt.type := tpDesc; (* override opaque *)
  1728. tpDesc.idnt := prevTp.idnt;
  1729. END;
  1730. END;
  1731. (*
  1732. * This is the normal case
  1733. *)
  1734. WITH tpDesc : Ty.Pointer DO
  1735. bndTyp := tpDesc.boundTp;
  1736. IF (bndTyp # NIL) & (bndTyp.kind = Ty.tmpTp) THEN
  1737. linkIx := bndTyp.dump - D.tOffset;
  1738. IF linkIx # 0 THEN
  1739. ASSERT(linkIx > typIdx);
  1740. f.tArray.a[linkIx] := tpDesc.boundTp;
  1741. END;
  1742. END;
  1743. ELSE (* skip *)
  1744. END;
  1745. END;
  1746. f.tArray.a[typIdx] := tpDesc;
  1747. END; (* while *)
  1748. FOR linkIx := 0 TO f.tArray.tide - 1 DO
  1749. tpDesc := f.tArray.a[linkIx];
  1750. (*
  1751. * First we fix up all symbolic references in the
  1752. * the type array. Postcondition is : no element
  1753. * of the type array directly or indirectly refers
  1754. * to a temporary type.
  1755. *)
  1756. tpDesc.TypeFix(f.tArray);
  1757. END;
  1758. FOR linkIx := 0 TO f.tArray.tide - 1 DO
  1759. tpDesc := f.tArray.a[linkIx];
  1760. (*
  1761. * At this stage we want to check the base types
  1762. * of every defined record type. If the base type
  1763. * is imported then we check.
  1764. * Define 'set' := dfScp.xAttr * {weak, need}; then ...
  1765. *
  1766. * set = {D.need} ==> module is explicitly imported
  1767. *
  1768. * set = {D.weak} ==> module must be imported, but is not
  1769. * on the import worklist at this stage
  1770. * set = {D.weak, D.need} ==> module must be imported, and is
  1771. * already on the import worklist.
  1772. *)
  1773. IF tpDesc # NIL THEN
  1774. WITH tpDesc : Ty.Record DO
  1775. IF tpDesc.baseTp # NIL THEN
  1776. prevTp := tpDesc.baseTp;
  1777. IF (prevTp.kind = Ty.namTp) &
  1778. (prevTp.idnt # NIL) &
  1779. (prevTp.idnt.dfScp # NIL) THEN
  1780. basBlk := prevTp.idnt.dfScp(Id.BlkId);
  1781. IF basBlk.xAttr * {D.weak, D.need} = {D.weak} THEN
  1782. INCL(basBlk.xAttr, D.need);
  1783. D.AppendScope(f.rScp.work, prevTp.idnt.dfScp);
  1784. END;
  1785. END;
  1786. END;
  1787. ELSE (* skip other types *)
  1788. END; (* with *)
  1789. END;
  1790. END; (* for linkIx do *)
  1791. (*
  1792. * We now fix up all references in the symbol table
  1793. * that still refer to temporary symbol-file types.
  1794. *)
  1795. NEW(typeFA);
  1796. typeFA.sym := f;
  1797. f.impS.symTb.Apply(typeFA); (* Apply a TypeLinker to the sym-tab *)
  1798. f.ReadPast(close);
  1799. (*
  1800. * Now check that all overloaded ids are necessary
  1801. *)
  1802. FOR linkIx := 0 TO f.oArray.tide - 1 DO
  1803. f.oArray.a[linkIx].OverloadFix();
  1804. f.oArray.a[linkIx] := NIL;
  1805. END;
  1806. END TypeList;
  1807. (* ============================================ *)
  1808. PROCEDURE (f : SymFileReader)SymFile(IN nm : ARRAY OF CHAR),NEW;
  1809. (*
  1810. // SymFile = Header [String (falSy | truSy | <others>)]
  1811. // {Import | Constant | Variable | Type | Procedure}
  1812. // TypeList Key.
  1813. // Header = magic modSy Name.
  1814. //
  1815. // magic has already been recognized.
  1816. *)
  1817. VAR oldS : INTEGER;
  1818. BEGIN
  1819. f.ReadPast(modSy);
  1820. IF f.sSym = namSy THEN (* do something with f.strAtt *)
  1821. IF nm # f.strAtt^ THEN
  1822. Error.WriteString("Wrong name in symbol file. Expected <");
  1823. Error.WriteString(nm + ">, found <");
  1824. Error.WriteString(f.strAtt^ + ">");
  1825. Error.WriteLn;
  1826. HALT(1);
  1827. END;
  1828. f.GetSym();
  1829. ELSE RTS.Throw("Bad symfile header");
  1830. END;
  1831. IF f.sSym = strSy THEN (* optional name *)
  1832. f.impS.scopeNm := Lt.arrToCharOpen(f.strAtt, f.strLen);
  1833. f.GetSym();
  1834. IF f.sSym = falSy THEN
  1835. INCL(f.impS.xAttr, D.isFn);
  1836. f.GetSym();
  1837. ELSIF f.sSym = truSy THEN
  1838. INCL(f.impS.xAttr, D.isFn);
  1839. INCL(f.impS.xAttr, D.fnInf);
  1840. f.GetSym();
  1841. ELSE RTS.Throw("Bad explicit name");
  1842. END;
  1843. END;
  1844. IF f.sSym = numSy THEN (* optional strong name info. *)
  1845. NEW(f.impS.verNm); (* POINTER TO ARRAY 6 OF INTEGER *)
  1846. f.impS.verNm[0] := RTS.hiInt(f.lAtt);
  1847. f.impS.verNm[1] := RTS.loInt(f.lAtt);
  1848. f.GetSym();
  1849. f.impS.verNm[2] := RTS.hiInt(f.lAtt);
  1850. f.impS.verNm[3] := RTS.loInt(f.lAtt);
  1851. f.GetSym();
  1852. f.impS.verNm[4] := RTS.hiInt(f.lAtt);
  1853. f.impS.verNm[5] := RTS.loInt(f.lAtt);
  1854. f.GetSym();
  1855. IF CSt.verbose THEN
  1856. Console.WriteString("version:");
  1857. Console.WriteInt(f.impS.verNm[0],1); Console.Write(".");
  1858. Console.WriteInt(f.impS.verNm[1],1); Console.Write(".");
  1859. Console.WriteInt(f.impS.verNm[2],1); Console.Write(".");
  1860. Console.WriteInt(f.impS.verNm[3],1);
  1861. Console.WriteHex(f.impS.verNm[4],9);
  1862. Console.WriteHex(f.impS.verNm[5],9); Console.WriteLn;
  1863. END;
  1864. (*
  1865. // The CPS format only provides for version information if
  1866. // there is also a strong key token. Do not propagate random
  1867. // junk with PeToCps from assemblies with version info only
  1868. *)
  1869. IF (f.impS.verNm[4] = 0) OR (f.impS.verNm[5] = 0) THEN
  1870. f.impS := NIL;
  1871. END;
  1872. END;
  1873. LOOP
  1874. oldS := f.sSym;
  1875. f.GetSym();
  1876. CASE oldS OF
  1877. | start : EXIT;
  1878. | typSy : f.Type(); (* Declare public tp *)
  1879. | impSy : f.Import(); (* Declare an import *)
  1880. | conSy : Insert(f.constant(), f.impS.symTb); (* Const. definition *)
  1881. | varSy : Insert(f.variable(), f.impS.symTb); (* Var. declaration *)
  1882. | prcSy : Insert(f.procedure(), f.impS.symTb); (* Proc. declaration *)
  1883. ELSE RTS.Throw("Bad object");
  1884. END;
  1885. END;
  1886. (*
  1887. * Now read the typelist.
  1888. *)
  1889. f.TypeList();
  1890. (*
  1891. * Now check the module key.
  1892. *)
  1893. IF f.sSym = keySy THEN
  1894. IF f.impS.modKey = 0 THEN
  1895. f.impS.modKey := f.iAtt;
  1896. ELSIF f.impS.modKey # f.iAtt THEN
  1897. S.SemError.Report(173, S.line, S.col); (* Detected bad KeyVal *)
  1898. END;
  1899. ELSE RTS.Throw("Missing keySy");
  1900. END;
  1901. (* FIXME -- parse optional comment
  1902. f.GetSym();
  1903. IF f.sSym = strSy THEN
  1904. Console.WriteString(f.strAtt);
  1905. Console.WriteLn;
  1906. END;
  1907. *)
  1908. END SymFile;
  1909. (* ============================================================ *)
  1910. (* ======== SymFileSFA visitor method ======= *)
  1911. (* ============================================================ *)
  1912. PROCEDURE (t : SymFileSFA)Op*(id : D.Idnt);
  1913. BEGIN
  1914. IF (id.kind = Id.impId) OR (id.vMod # D.prvMode) THEN
  1915. CASE id.kind OF
  1916. | Id.typId : t.sym.EmitTypeId(id(Id.TypId));
  1917. | Id.conId : t.sym.EmitConstId(id(Id.ConId));
  1918. | Id.impId : t.sym.EmitImportId(id(Id.BlkId));
  1919. | Id.varId : t.sym.EmitVariableId(id(Id.VarId));
  1920. | Id.conPrc : t.sym.EmitProcedureId(id(Id.PrcId));
  1921. ELSE (* skip *)
  1922. END;
  1923. END;
  1924. END Op;
  1925. (* ============================================================ *)
  1926. (* ======== TypeLinker visitor method ======= *)
  1927. (* ============================================================ *)
  1928. PROCEDURE (t : TypeLinker)Op*(id : D.Idnt);
  1929. VAR oldT : D.Type;
  1930. BEGIN
  1931. IF id.type = NIL THEN RETURN
  1932. ELSIF id.type.kind = Ty.tmpTp THEN
  1933. oldT := id.type;
  1934. id.type := Ty.update(t.sym.tArray, id.type);
  1935. ELSE
  1936. id.type.TypeFix(t.sym.tArray);
  1937. END;
  1938. IF (id IS Id.TypId) &
  1939. (id.type.idnt = NIL) THEN id.type.idnt := id END;
  1940. END Op;
  1941. (* ============================================================ *)
  1942. (* ======== ResolveAll visitor method ======= *)
  1943. (* ============================================================ *)
  1944. PROCEDURE (t : ResolveAll)Op*(id : D.Idnt);
  1945. BEGIN
  1946. IF id.type # NIL THEN
  1947. IF id.namStr = NIL THEN id.SetNameFromHash(id.hash) END;
  1948. id.type := id.type.resolve(1);
  1949. END;
  1950. END Op;
  1951. (* ============================================================ *)
  1952. (* ======== Symbol file parser method ======= *)
  1953. (* ============================================================ *)
  1954. PROCEDURE (res : ImpResScope)ReadThisImport(imp : Id.BlkId),NEW;
  1955. VAR syFil : SymFileReader;
  1956. BEGIN
  1957. INCL(imp.xAttr, D.fixd);
  1958. syFil := newSymFileReader(res.host);
  1959. syFil.rScp := res;
  1960. syFil.Parse(imp);
  1961. END ReadThisImport;
  1962. (* ============================================ *)
  1963. PROCEDURE WalkImports*(VAR imps : D.ScpSeq; modI : Id.BlkId);
  1964. VAR indx : INTEGER;
  1965. blkI : Id.BlkId;
  1966. fScp : ImpResScope;
  1967. rAll : ResolveAll;
  1968. BEGIN
  1969. (*
  1970. * The list of scopes has been constructed by
  1971. * the parser, while reading the import list.
  1972. * In the case of already known scopes the list
  1973. * references the original descriptor.
  1974. *
  1975. * Unlike the previous version (SymFileRW) this
  1976. * routine may mutate the length of the sequence.
  1977. *)
  1978. NEW(fScp);
  1979. (*
  1980. * Copy the incoming sequence.
  1981. *)
  1982. fScp.work := imps;
  1983. fScp.host := modI;
  1984. (*
  1985. * Now import modules on the list.
  1986. *)
  1987. indx := 0;
  1988. WHILE indx < fScp.work.tide DO
  1989. blkI := fScp.work.a[indx](Id.BlkId);
  1990. IF blkI.kind = Id.alias THEN
  1991. blkI.symTb := blkI.dfScp.symTb;
  1992. ELSIF ~(D.fixd IN blkI.xAttr) THEN
  1993. fScp.ReadThisImport(blkI);
  1994. END;
  1995. INC(indx);
  1996. END;
  1997. (*
  1998. * If sysLib has NOT been explicitly imported, then
  1999. * insert dummy definitions for the native object methods
  2000. * so that user code may explictly extend RTS.NativeObject
  2001. * and override these methods.
  2002. *)
  2003. IF ~(D.fixd IN CSt.sysLib.xAttr) THEN
  2004. CSt.ImportObjectFeatures();
  2005. END;
  2006. FOR indx := 0 TO fScp.work.tide-1 DO
  2007. blkI := fScp.work.a[indx](Id.BlkId);
  2008. NEW(rAll);
  2009. blkI.symTb.Apply(rAll); (* Apply ResolveAll to sym-tab *)
  2010. END;
  2011. (*
  2012. * Copy the (possibly mutated) sequence out.
  2013. *)
  2014. imps := fScp.work;
  2015. END WalkImports;
  2016. (* ============================================================ *)
  2017. BEGIN
  2018. lastKey := 0;
  2019. fSepArr[0] := GF.fileSep;
  2020. END NewSymFileRW.
  2021. (* ============================================================ *)