SymbolFile.cp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. (* ==================================================================== *)
  2. (* *)
  3. (* SymFileRW: Symbol-file reading and writing for GPCP. *)
  4. (* Copyright (c) John Gough 1999, 2000. *)
  5. (* *)
  6. (* ==================================================================== *)
  7. MODULE SymbolFile;
  8. IMPORT
  9. GPCPcopyright,
  10. RTS,
  11. Error,
  12. GPBinFiles,
  13. FileNames,
  14. CompState,
  15. MH := ModuleHandler;
  16. (* ========================================================================= *
  17. // Collected syntax ---
  18. //
  19. // SymFile = Header [String (falSy | truSy | <other attribute>)]
  20. // [ VersionName ]
  21. // {Import | Constant | Variable | Type | Procedure}
  22. // TypeList Key.
  23. // -- optional String is external name.
  24. // -- falSy ==> Java class
  25. // -- truSy ==> Java interface
  26. // -- others ...
  27. // Header = magic modSy Name.
  28. // VersionName= numSy longint numSy longint numSy longint.
  29. // -- mj# mn# bld rv# 8xbyte extract
  30. // Import = impSy Name [String] Key.
  31. // -- optional string is explicit external name of class
  32. // Constant = conSy Name Literal.
  33. // Variable = varSy Name TypeOrd.
  34. // Type = typSy Name TypeOrd.
  35. // Procedure = prcSy Name [String] FormalType.
  36. // -- optional string is explicit external name of procedure
  37. // Method = mthSy Name byte byte TypeOrd [String] FormalType.
  38. // -- optional string is explicit external name of method
  39. // FormalType = [retSy TypeOrd] frmSy {parSy byte TypeOrd} endFm.
  40. // -- optional phrase is return type for proper procedures
  41. // TypeOrd = ordinal.
  42. // TypeHeader = tDefS Ord [fromS Ord Name].
  43. // -- optional phrase occurs if:
  44. // -- type not from this module, i.e. indirect export
  45. // TypeList = start { Array | Record | Pointer | ProcType } close.
  46. // Array = TypeHeader arrSy TypeOrd (Byte | Number | <empty>) endAr.
  47. // -- nullable phrase is array length for fixed length arrays
  48. // Vector = TypeHeader vecSy TypeOrd endAr.
  49. // Pointer = TypeHeader ptrSy TypeOrd.
  50. // EventType = TypeHeader evtSy FormalType.
  51. // ProcType = TypeHeader pTpSy FormalType.
  52. // Record = TypeHeader recSy recAtt [truSy | falSy]
  53. // [basSy TypeOrd] [ iFcSy {basSy TypeOrd}]
  54. // {Name TypeOrd} {OtherStuff} endRc.
  55. // -- truSy ==> is an extension of external interface
  56. // -- falSy ==> is an extension of external class
  57. // -- basSy option defines base type, if not ANY / j.l.Object
  58. // OtherStuff = Method | Procedure | Variable | Constant.
  59. // Enum = TypeHeader eTpSy { Constant } endRc.
  60. // Name = namSy byte UTFstring.
  61. // Literal = Number | String | Set | Char | Real | falSy | truSy.
  62. // Byte = bytSy byte.
  63. // String = strSy UTFstring.
  64. // Number = numSy longint.
  65. // Real = fltSy ieee-double.
  66. // Set = setSy integer.
  67. // Key = keySy integer..
  68. // Char = chrSy unicode character.
  69. //
  70. // Notes on the syntax:
  71. // All record types must have a Name field, even though this is often
  72. // redundant. The issue is that every record type (including those that
  73. // are anonymous in CP) corresponds to a IR class, and the definer
  74. // and the user of the class _must_ agree on the IR name of the class.
  75. // The same reasoning applies to procedure types, which must have equal
  76. // interface names in all modules.
  77. // ======================================================================== *)
  78. CONST
  79. modSy = ORD('H'); namSy = ORD('$'); bytSy = ORD('\');
  80. numSy = ORD('#'); chrSy = ORD('c'); strSy = ORD('s');
  81. fltSy = ORD('r'); falSy = ORD('0'); truSy = ORD('1');
  82. impSy = ORD('I'); setSy = ORD('S'); keySy = ORD('K');
  83. conSy = ORD('C'); typSy = ORD('T'); tDefS = ORD('t');
  84. prcSy = ORD('P'); retSy = ORD('R'); mthSy = ORD('M');
  85. varSy = ORD('V'); parSy = ORD('p'); start = ORD('&');
  86. close = ORD('!'); recSy = ORD('{'); endRc = ORD('}');
  87. frmSy = ORD('('); fromS = ORD('@'); endFm = ORD(')');
  88. arrSy = ORD('['); endAr = ORD(']'); pTpSy = ORD('%');
  89. ptrSy = ORD('^'); basSy = ORD('+'); eTpSy = ORD('e');
  90. iFcSy = ORD('~'); evtSy = ORD('v'); vecSy = ORD('*');
  91. CONST
  92. magic = 0DEADD0D0H;
  93. syMag = 0D0D0DEADH;
  94. VAR
  95. file* : GPBinFiles.FILE;
  96. fileName* : FileNames.NameString;
  97. sSym : INTEGER;
  98. cAtt : CHAR;
  99. iAtt : INTEGER;
  100. lAtt : LONGINT;
  101. rAtt : REAL;
  102. sAtt : FileNames.NameString;
  103. (* ============================================================ *)
  104. (* ======== Various reading utility procedures ======= *)
  105. (* ============================================================ *)
  106. PROCEDURE read() : INTEGER;
  107. BEGIN
  108. RETURN GPBinFiles.readByte(file);
  109. END read;
  110. (* ======================================= *)
  111. PROCEDURE ReadUTF(OUT nam : ARRAY OF CHAR);
  112. CONST
  113. bad = "Bad UTF-8 string";
  114. VAR num : INTEGER;
  115. bNm : INTEGER;
  116. idx : INTEGER;
  117. chr : INTEGER;
  118. BEGIN
  119. num := 0;
  120. bNm := read() * 256 + read();
  121. FOR idx := 0 TO bNm-1 DO
  122. chr := read();
  123. IF chr <= 07FH THEN
  124. nam[num] := CHR(chr); INC(num);
  125. ELSIF chr DIV 32 = 06H THEN
  126. bNm := chr MOD 32 * 64;
  127. chr := read();
  128. IF chr DIV 64 = 02H THEN
  129. nam[num] := CHR(bNm + chr MOD 64); INC(num);
  130. ELSE
  131. RTS.Throw(bad);
  132. END;
  133. ELSIF chr DIV 16 = 0EH THEN
  134. bNm := chr MOD 16 * 64;
  135. chr := read();
  136. IF chr DIV 64 = 02H THEN
  137. bNm := (bNm + chr MOD 64) * 64;
  138. chr := read();
  139. IF chr DIV 64 = 02H THEN
  140. nam[num] := CHR(bNm + chr MOD 64); INC(num);
  141. ELSE
  142. RTS.Throw(bad);
  143. END;
  144. ELSE
  145. RTS.Throw(bad);
  146. END;
  147. ELSE
  148. RTS.Throw(bad);
  149. END;
  150. END;
  151. nam[num] := 0X;
  152. END ReadUTF;
  153. (* ======================================= *)
  154. PROCEDURE readChar() : CHAR;
  155. BEGIN
  156. RETURN CHR(read() * 256 + read());
  157. END readChar;
  158. (* ======================================= *)
  159. PROCEDURE readInt() : INTEGER;
  160. BEGIN [UNCHECKED_ARITHMETIC]
  161. (* overflow checking off here *)
  162. RETURN ((read() * 256 + read()) * 256 + read()) * 256 + read();
  163. END readInt;
  164. (* ======================================= *)
  165. PROCEDURE readLong() : LONGINT;
  166. VAR result : LONGINT;
  167. index : INTEGER;
  168. BEGIN [UNCHECKED_ARITHMETIC]
  169. (* overflow checking off here *)
  170. result := read();
  171. FOR index := 1 TO 7 DO
  172. result := result * 256 + read();
  173. END;
  174. RETURN result;
  175. END readLong;
  176. (* ======================================= *)
  177. PROCEDURE readReal() : REAL;
  178. VAR result : LONGINT;
  179. BEGIN
  180. result := readLong();
  181. RETURN RTS.longBitsToReal(result);
  182. END readReal;
  183. (* ======================================= *)
  184. PROCEDURE readOrd() : INTEGER;
  185. VAR chr : INTEGER;
  186. BEGIN
  187. chr := read();
  188. IF chr <= 07FH THEN RETURN chr;
  189. ELSE
  190. DEC(chr, 128);
  191. RETURN chr + read() * 128;
  192. END;
  193. END readOrd;
  194. (* ============================================================ *)
  195. (* ======== Symbol File Reader ======= *)
  196. (* ============================================================ *)
  197. PROCEDURE SymError(IN msg : ARRAY OF CHAR);
  198. BEGIN
  199. Error.WriteString("Error in <" + fileName + "> : ");
  200. Error.WriteString(msg); Error.WriteLn;
  201. END SymError;
  202. (* ======================================= *)
  203. PROCEDURE GetSym();
  204. BEGIN
  205. sSym := read();
  206. CASE sSym OF
  207. | namSy :
  208. iAtt := read(); ReadUTF(sAtt);
  209. | strSy :
  210. ReadUTF(sAtt);
  211. | retSy, fromS, tDefS, basSy :
  212. iAtt := readOrd();
  213. | bytSy :
  214. iAtt := read();
  215. | keySy, setSy :
  216. iAtt := readInt();
  217. | numSy :
  218. lAtt := readLong();
  219. | fltSy :
  220. rAtt := readReal();
  221. | chrSy :
  222. cAtt := readChar();
  223. ELSE (* nothing to do *)
  224. END;
  225. END GetSym;
  226. (* ======================================= *)
  227. PROCEDURE Check(sym : INTEGER);
  228. BEGIN
  229. IF sSym # sym THEN
  230. Error.WriteString("Expected " );
  231. Error.WriteInt(sym,0);
  232. Error.WriteString(" but got " );
  233. Error.WriteInt(sSym,0);
  234. Error.WriteLn;
  235. THROW("Bad symbol file format");
  236. END;
  237. END Check;
  238. PROCEDURE CheckAndGet(sym : INTEGER);
  239. VAR
  240. ok : BOOLEAN;
  241. BEGIN
  242. IF sSym # sym THEN
  243. Error.WriteString("Expected " );
  244. Error.WriteInt(sym,0);
  245. Error.WriteString(" but got " );
  246. Error.WriteInt(sSym,0);
  247. Error.WriteLn;
  248. THROW("Bad symbol file format");
  249. END;
  250. GetSym();
  251. END CheckAndGet;
  252. (* ======================================= *)
  253. PROCEDURE OpenSymbolFile*(IN name : ARRAY OF CHAR; onPath : BOOLEAN);
  254. BEGIN
  255. fileName := name + ".cps";
  256. IF onPath THEN
  257. file := GPBinFiles.findOnPath(CompState.cpSymX, fileName);
  258. ELSE
  259. file := GPBinFiles.findLocal(fileName);
  260. END;
  261. END OpenSymbolFile;
  262. (* ======================================= *)
  263. PROCEDURE SkipFormalType();
  264. (*
  265. // FormalType = [retSy TypeOrd] frmSy {parSy byte TypeOrd} endFm.
  266. // -- optional phrase is return type for proper procedures
  267. *)
  268. VAR
  269. byte : INTEGER;
  270. BEGIN
  271. IF sSym = retSy THEN GetSym(); END;
  272. CheckAndGet(frmSy);
  273. WHILE sSym = parSy DO
  274. byte := read();
  275. byte := readOrd();
  276. GetSym();
  277. IF sSym = strSy THEN GetSym() END;
  278. END;
  279. CheckAndGet(endFm);
  280. END SkipFormalType;
  281. (* ============================================ *)
  282. PROCEDURE TypeList();
  283. (* TypeList = start { Array | Record | Pointer | ProcType } close. *)
  284. (* TypeHeader = tDefS Ord [fromS Ord Name]. *)
  285. VAR
  286. num, oldS : INTEGER;
  287. tmp : INTEGER;
  288. BEGIN
  289. WHILE sSym = tDefS DO
  290. GetSym();
  291. IF sSym = fromS THEN
  292. GetSym(); (* fromS *)
  293. GetSym(); (* Name *)
  294. END;
  295. (* Get type info. *)
  296. CASE sSym OF
  297. | arrSy : num := readOrd();
  298. GetSym();
  299. IF (sSym = bytSy) OR (sSym = numSy) THEN GetSym(); END;
  300. CheckAndGet(endAr);
  301. | vecSy : num := readOrd();
  302. GetSym();
  303. CheckAndGet(endAr);
  304. | eTpSy : GetSym();
  305. WHILE sSym = conSy DO
  306. GetSym(); (* read past conSy *)
  307. CheckAndGet(namSy);
  308. GetSym(); (* read past literal *)
  309. END;
  310. CheckAndGet(endRc);
  311. | recSy : num := read();
  312. GetSym();
  313. IF (sSym = falSy) OR (sSym = truSy) THEN GetSym(); END;
  314. IF (sSym = basSy) THEN GetSym(); END;
  315. IF sSym = iFcSy THEN
  316. GetSym();
  317. WHILE sSym = basSy DO GetSym() END;
  318. END;
  319. WHILE sSym = namSy DO num := readOrd(); GetSym(); END;
  320. WHILE (sSym = mthSy) OR (sSym = conSy) OR
  321. (sSym = prcSy) OR (sSym = varSy) DO
  322. oldS := sSym; GetSym();
  323. IF oldS = mthSy THEN
  324. (* mthSy Name byte byte TypeOrd [String] FormalType. *)
  325. Check(namSy);
  326. num := read();
  327. num := read();
  328. num := readOrd();
  329. GetSym();
  330. IF sSym = strSy THEN GetSym(); END;
  331. IF sSym = namSy THEN GetSym(); END;
  332. SkipFormalType();
  333. ELSIF oldS = conSy THEN (* Name Literal *)
  334. CheckAndGet(namSy);
  335. GetSym();
  336. ELSIF oldS = prcSy THEN (* Name [String] FormalType. *)
  337. CheckAndGet(namSy);
  338. IF sSym = strSy THEN GetSym(); END;
  339. IF sSym = truSy THEN GetSym(); END;
  340. SkipFormalType();
  341. ELSE (* Name TypeOrd. *)
  342. Check(namSy);
  343. tmp := readOrd();
  344. GetSym();
  345. END;
  346. END;
  347. CheckAndGet(endRc);
  348. | ptrSy : num := readOrd(); GetSym();
  349. | pTpSy, evtSy : GetSym(); SkipFormalType();
  350. ELSE (* skip *)
  351. END;
  352. END;
  353. GetSym();
  354. END TypeList;
  355. (* ============================================ *)
  356. PROCEDURE ReadSymbolFile*(mod : MH.ModInfo; addKeys : BOOLEAN);
  357. (*
  358. // SymFile = Header [String (falSy | truSy | <others>)]
  359. // {Import | Constant | Variable | Type | Procedure}
  360. // TypeList Key.
  361. // Header = magic modSy Name.
  362. //
  363. *)
  364. VAR
  365. marker : INTEGER;
  366. oldS,tmp : INTEGER;
  367. impMod : MH.ModInfo;
  368. BEGIN
  369. impMod := NIL;
  370. marker := readInt();
  371. IF (marker = RTS.loInt(magic)) OR (marker = RTS.loInt(syMag)) THEN
  372. (* normal case, nothing to do *)
  373. ELSE
  374. SymError("Bad symbol file format.");
  375. RETURN;
  376. END;
  377. GetSym();
  378. CheckAndGet(modSy);
  379. Check(namSy);
  380. IF mod.name # sAtt THEN
  381. SymError("Wrong name in symbol file. Expected <" + mod.name +
  382. ">, found <" + sAtt + ">");
  383. RETURN;
  384. END;
  385. GetSym();
  386. IF sSym = strSy THEN (* optional name *)
  387. GetSym();
  388. IF (sSym = falSy) OR (sSym = truSy) THEN
  389. GetSym();
  390. ELSE
  391. SymError("Bad explicit name in symbol file.");
  392. RETURN;
  393. END;
  394. END;
  395. IF sSym = numSy THEN (* optional strong name info. *)
  396. (* ignore major, minor and get next symbol *)
  397. GetSym();
  398. (* ignore build, revision and get next symbol *)
  399. GetSym();
  400. (* ignore assembly publickeytoken and get next symbol *)
  401. GetSym();
  402. END;
  403. LOOP
  404. oldS := sSym;
  405. GetSym();
  406. CASE oldS OF
  407. | start : EXIT;
  408. | typSy, varSy : tmp := readOrd(); GetSym(); (* Name typeOrd *)
  409. | impSy : IF addKeys THEN impMod := MH.GetModule(sAtt); END;
  410. GetSym();
  411. IF sSym = strSy THEN GetSym(); END;
  412. Check(keySy);
  413. IF addKeys THEN MH.AddKey(mod,impMod,iAtt); END;
  414. GetSym();
  415. | conSy : GetSym(); GetSym(); (* Name Literal *)
  416. | prcSy : (* Name [String] FormalType *);
  417. GetSym();
  418. IF sSym = strSy THEN GetSym(); END;
  419. SkipFormalType();
  420. ELSE SymError("Bad symbol file format."); EXIT;
  421. END;
  422. END;
  423. TypeList();
  424. IF sSym = keySy THEN
  425. mod.key := iAtt;
  426. ELSE
  427. SymError("Missing keySy");
  428. END;
  429. GPBinFiles.CloseFile(file);
  430. END ReadSymbolFile;
  431. PROCEDURE CloseSymFile*();
  432. BEGIN
  433. IF file # NIL THEN GPBinFiles.CloseFile(file) END;
  434. END CloseSymFile;
  435. (* ============================================================ *)
  436. BEGIN
  437. END SymbolFile.
  438. (* ============================================================ *)