PCM.Mod 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  1. (* Paco, Copyright 2000 - 2002, Patrik Reali, ETH Zurich *)
  2. MODULE PCM; (** AUTHOR "prk"; PURPOSE "Parallel Compiler: input and output module"; *)
  3. IMPORT
  4. SYSTEM,
  5. KernelLog, Modules, Objects, Streams, Files, Diagnostics,
  6. StringPool, PCDebug, Strings, Reflection,Machine;
  7. CONST
  8. (* value of constant NIL *)
  9. nilval* = 0;
  10. (* target machine minimum values of basic types expressed in host machine format: *)
  11. MinSInt* = -80H;
  12. MinInt* = -8000H;
  13. MinLInt* = LONGINT(80000000H); (* i386: -2147483648*)
  14. (* target machine maximum values of basic types expressed in host machine format: *)
  15. MaxSInt* = 7FH;
  16. MaxInt* = 7FFFH;
  17. MaxLInt* = 7FFFFFFFH; (* i386: 2147483647*)
  18. MaxSet* = 31; (* must be >= 15, else the bootstraped compiler cannot run (IN-tests) *)
  19. (* parametrization of numeric scanner: *)
  20. MaxHDig* = 8; (* maximal hexadecimal longint length *)
  21. MaxHHDig* = 16; (* maximal hexadecimal hugeint length *)
  22. MaxRExp* = 38; (* maximal real exponent *)
  23. MaxLExp* = 308; (* maximal longreal exponent *)
  24. (** code generator options *)
  25. ArrayCheck* = 0; (* x - perform array boundary checks *)
  26. OverflowCheck* = 1; (* v - perform overflow check *)
  27. NilCheck* = 2; (* N - explicit hard-coded nil checks *)
  28. TypeCheck*= 3; (* t - perform type checks *)
  29. PtrInit* = 5; (* p - initialize pointers to NIL *)
  30. AssertCheck* = 6; (* a - evaluate asserts *)
  31. Optimize* = 13;
  32. FullStackInit* = 20; (* z - clear all values on stack *)
  33. AlignedStack*=21; (* A - generate code with stack alignment for unix Aos *)
  34. ExportDefinitions* = 30;
  35. UseDefinitions* = 31;
  36. (** parser options *)
  37. NewSF* = 16; (* s - generation of new symbol file allowed *)
  38. ExtSF* = 17; (* e - generation of extended symbol file allowed *)
  39. Breakpoint* = 18; (* f - find position in code *)
  40. CacheImports* = 19; (* c - Cache imported modules *)
  41. NoFiles* = 21; (* n - don't generate files, parse only*)
  42. NoOpOverloading* = 22; (* o - do NOT allow operator overloading *)
  43. BigEndian* = 23; (* b - generate big endian code, makes only sense together with ARM backend *)
  44. Warnings* = 24; (* W - display warnings *)
  45. SkipOldSFImport* = 25; (* S - skip old symbol file import in PCOM.Export, avoids compiler error when migrating to new object file *) (* ug *)
  46. MultipleModules*= 26; (* M - allow compilation of multiple modules within one file *)
  47. (** sysflags and objflags written to and read from symbol file *)
  48. Untraced* = 4; (** global vars + fields - weak pointer *)
  49. WinAPIParam* = 13; (* ejz *)
  50. CParam*=14; (* fof for linux *)
  51. ReadOnly* = 15; (* fof *)
  52. RealtimeProc* = 21; (* ug *)
  53. RealtimeProcType* = 21; (* ug *)
  54. (** compiler generated traps *)
  55. WithTrap* = 1;
  56. CaseTrap* = 2;
  57. ReturnTrap* = 3;
  58. TypeEqualTrap* = 5;
  59. TypeCheckTrap* = 6;
  60. IndexCheckTrap* = 7;
  61. AssertTrap* = 8;
  62. ArraySizeTrap* = 9;
  63. ArrayFormTrap*=10; (* fof: indicates that array cannot be (re-)allocated since shape, type or size does not match *)
  64. (** file names and extentions *)
  65. FileTag = 0BBX; (* same constants are defined in Linker and Loader *)
  66. NoZeroCompress = 0ADX; (* do. *)
  67. FileVersion* = 0B1X; (* do. *)
  68. FileVersionOC*=0B2X; (* fof, preparation for new compiler *)
  69. LocalUnicodeSupport* = TRUE;
  70. ExportedUnicodeSupport* = FALSE;
  71. InitErrMsgSize = 300; (* initial size of array of error messages *)
  72. MaxErrors = 100; (* maximum number of diagnostic messages *)
  73. MaxWarnings = 100;
  74. InvalidCode* = -1;
  75. InvalidPosition* = Streams.Invalid;
  76. TYPE
  77. SymReader* = Files.Reader;
  78. Rider* = RECORD
  79. symmodF, symF, objF, refF: Files.File;
  80. symmod, sym, obj, ref: Files.Writer; (*temp modlist, temp symfile, main file*)
  81. END;
  82. Attribute* = OBJECT END Attribute;
  83. ErrorMsgs = POINTER TO ARRAY OF StringPool.Index;
  84. VAR
  85. bigEndian*: BOOLEAN;
  86. (** fof >> *)
  87. tracebackOnError: BOOLEAN;
  88. (** << fof *)
  89. (** status *)
  90. codeOptions*, parserOptions*: SET;
  91. error*: BOOLEAN; (** actual compilation status *)
  92. errors, warnings: LONGINT; (* number of errors and warnings *)
  93. errMsg: ErrorMsgs; (*error messages*)
  94. (** input *)
  95. breakpc*: LONGINT; (** code offset to be found or MAX(LONGINT) *)
  96. breakpos*: LONGINT; (** text pos corresponding to breakpc (err 400 pos) *)
  97. (** output *)
  98. prefix*, suffix*: ARRAY 128 OF CHAR;
  99. (** procedure to dump (/D option) *)
  100. dump*: ARRAY 32 OF CHAR;
  101. source-: Files.FileName;
  102. log-: Streams.Writer;
  103. diagnostics-: Diagnostics.Diagnostics;
  104. (** ---------- low level functions --------------------- *)
  105. PROCEDURE GetProcessID*(): ADDRESS;
  106. BEGIN
  107. RETURN SYSTEM.VAL(ADDRESS, Objects.ActiveObject())
  108. END GetProcessID;
  109. (** ---------- file IO functions --------------------- *)
  110. PROCEDURE MakeFileName(VAR file: ARRAY OF CHAR; CONST name, prefix, suffix: ARRAY OF CHAR);
  111. VAR i, j: LONGINT;
  112. BEGIN
  113. i := 0; WHILE prefix[i] # 0X DO file[i] := prefix[i]; INC(i) END;
  114. j := 0; WHILE name[j] # 0X DO file[i+j] := name[j]; INC(j) END;
  115. INC(i, j);
  116. j := 0; WHILE suffix[j] # 0X DO file[i+j] := suffix[j]; INC(j) END;
  117. file[i+j] := 0X;
  118. END MakeFileName;
  119. PROCEDURE WriteString(w: Streams.Writer; CONST s: ARRAY OF CHAR);
  120. VAR i: INTEGER; ch: CHAR;
  121. BEGIN
  122. i:=0; ch:=s[0];
  123. WHILE ch # 0X DO
  124. w.Char(ch); INC(i); ch := s[i];
  125. END;
  126. w.Char(0X);
  127. END WriteString;
  128. (** OpenSymFile - Open a symfile for reading *)
  129. PROCEDURE OpenSymFile*(CONST name: ARRAY OF CHAR; VAR r: SymReader; VAR version: CHAR; VAR zeroCompress: BOOLEAN): BOOLEAN;
  130. VAR res: BOOLEAN; file: Files.FileName; f: Files.File; dummy: LONGINT; ch: CHAR;
  131. BEGIN
  132. res := FALSE; zeroCompress := TRUE;
  133. MakeFileName(file, name, prefix, suffix);
  134. f := Files.Old(file);
  135. IF f # NIL THEN
  136. Files.OpenReader(r, f, 0);
  137. r.Char(ch);
  138. IF ch = FileTag THEN
  139. r.Char(version);
  140. IF version = NoZeroCompress THEN
  141. zeroCompress := FALSE;
  142. r.Char(version);
  143. END;
  144. IF version = FileVersion THEN
  145. r.RawNum(dummy); (*skip symfile size*)
  146. ELSIF version = FileVersionOC THEN
  147. r.RawLInt(dummy);
  148. END;
  149. res := TRUE
  150. END
  151. END;
  152. RETURN res
  153. END OpenSymFile;
  154. PROCEDURE SymW*(VAR R: Rider; ch: CHAR);
  155. BEGIN R.sym.Char(ch) END SymW;
  156. PROCEDURE SymWNum*(VAR R: Rider; i: LONGINT);
  157. BEGIN R.sym.RawNum(i) END SymWNum;
  158. PROCEDURE SymWSet*(VAR R: Rider; s: SET);
  159. BEGIN R.sym.RawNum(SYSTEM.VAL(LONGINT, s)) END SymWSet;
  160. PROCEDURE SymWString*(VAR R: Rider; CONST str: ARRAY OF CHAR);
  161. BEGIN WriteString(R.sym, str) END SymWString;
  162. PROCEDURE SymWMod*(VAR R: Rider; CONST str: ARRAY OF CHAR);
  163. BEGIN WriteString(R.symmod, str) END SymWMod;
  164. PROCEDURE SymWReal*(VAR R: Rider; r: REAL);
  165. BEGIN R.sym.RawReal(r) END SymWReal;
  166. PROCEDURE SymWLReal*(VAR R: Rider; r: LONGREAL);
  167. BEGIN R.sym.RawLReal(r) END SymWLReal;
  168. PROCEDURE ObjWGetPos*(VAR R: Rider; VAR pos: LONGINT);
  169. BEGIN pos := R.obj.Pos()
  170. END ObjWGetPos;
  171. PROCEDURE ObjW*(VAR R: Rider; ch: CHAR);
  172. BEGIN R.obj.Char(ch)
  173. END ObjW;
  174. PROCEDURE ObjWNum*(VAR R: Rider; i: LONGINT);
  175. BEGIN R.obj.RawNum(i)
  176. END ObjWNum;
  177. PROCEDURE ObjWInt*(VAR R: Rider; i: INTEGER);
  178. BEGIN R.obj.RawInt(i)
  179. END ObjWInt;
  180. PROCEDURE ObjWIntAt*(VAR R: Rider; pos: LONGINT; i: INTEGER);
  181. VAR w: Files.Writer;
  182. BEGIN
  183. R.obj.Update;
  184. Files.OpenWriter(w, R.objF, pos);
  185. w.RawInt(i);
  186. w.Update
  187. END ObjWIntAt;
  188. PROCEDURE ObjWLInt*(VAR R: Rider; i: LONGINT);
  189. BEGIN R.obj.RawLInt(i)
  190. END ObjWLInt;
  191. PROCEDURE ObjWLIntAt*(VAR R: Rider; pos: LONGINT; i: LONGINT);
  192. VAR w: Files.Writer;
  193. BEGIN
  194. R.obj.Update;
  195. Files.OpenWriter(w, R.objF, pos);
  196. w.RawLInt(i);
  197. w.Update
  198. END ObjWLIntAt;
  199. PROCEDURE ObjWName*(VAR R: Rider; CONST str: ARRAY OF CHAR);
  200. BEGIN R.obj.RawString(str)
  201. END ObjWName;
  202. PROCEDURE RefW*(VAR R: Rider; ch: CHAR);
  203. BEGIN R.ref.Char(ch)
  204. END RefW;
  205. PROCEDURE RefWNum*(VAR R: Rider; i: LONGINT);
  206. BEGIN R.ref.RawNum(i)
  207. END RefWNum;
  208. PROCEDURE RefWString*(VAR R: Rider; CONST str: ARRAY OF CHAR);
  209. BEGIN R.ref.RawString(str)
  210. END RefWString;
  211. PROCEDURE Open*(CONST name: ARRAY OF CHAR; VAR R: Rider; VAR version: CHAR);
  212. VAR file: Files.FileName;
  213. BEGIN
  214. MakeFileName(file, name, prefix, suffix);
  215. R.symmodF := Files.New("");
  216. R.symF := Files.New("");
  217. R.objF := Files.New(file);
  218. R.refF := Files.New("");
  219. Files.OpenWriter(R.symmod, R.symmodF, 0);
  220. Files.OpenWriter(R.sym, R.symF, 0);
  221. Files.OpenWriter(R.obj, R.objF, 0);
  222. Files.OpenWriter(R.ref, R.refF, 0);
  223. R.obj.Char(FileTag);
  224. R.obj.Char(NoZeroCompress);
  225. R.obj.Char(version)
  226. END Open;
  227. PROCEDURE AppendFile(f: Files.File; to: Streams.Writer);
  228. VAR buffer: ARRAY 1024 OF CHAR; r: Files.Reader; read: LONGINT;
  229. BEGIN
  230. Files.OpenReader(r, f, 0);
  231. REPEAT
  232. r.Bytes(buffer, 0, 1024, read);
  233. to.Bytes(buffer, 0, read)
  234. UNTIL read # 1024
  235. END AppendFile;
  236. PROCEDURE CloseSym*(VAR R: Rider);
  237. BEGIN
  238. R.symmod.Update; (* flush buffers to file *)
  239. R.sym.Update;
  240. (* IF OldFileFormat THEN
  241. R.obj.RawNum(R.symmod.sent + R.sym.sent);
  242. ELSE
  243. R.obj.RawNum(4 + R.symmod.sent + R.sym.sent);
  244. R.obj.RawSet(codeOptions)
  245. END; *)
  246. R.obj.RawNum(4 + R.symmod.sent + R.sym.sent);
  247. R.obj.RawSet(codeOptions);
  248. AppendFile(R.symmodF, R.obj);
  249. AppendFile(R.symF, R.obj)
  250. END CloseSym;
  251. PROCEDURE CloseObj*(VAR R: Rider);
  252. BEGIN
  253. R.ref.Update;
  254. AppendFile(R.refF, R.obj);
  255. R.obj.Update;
  256. Files.Register(R.objF)
  257. END CloseObj;
  258. PROCEDURE RefSize*(VAR R: Rider): LONGINT;
  259. BEGIN RETURN R.ref.Pos()
  260. END RefSize;
  261. (** ---------- text output functions --------------------- *)
  262. PROCEDURE GetMessage (err: WORD; CONST msg: ARRAY OF CHAR; VAR res: ARRAY OF CHAR);
  263. VAR str: ARRAY 128 OF CHAR;
  264. BEGIN
  265. COPY (msg, res);
  266. IF (errMsg # NIL) & (0 <= err) & (err < LEN(errMsg)) THEN
  267. StringPool.GetString(errMsg[err], str);
  268. Strings.Append(res, " ");
  269. Strings.Append(res, str);
  270. END;
  271. END GetMessage;
  272. PROCEDURE TraceBackThis( eip, ebp: ADDRESS ); (* do a stack trace back w.r.t. given instruction and frame pointers *)
  273. BEGIN
  274. log.Ln; log.String( "##################" );
  275. log.Ln; log.String( "# Debugging.TraceBack #" );
  276. log.Ln; log.String( "##################" );
  277. log.Ln; Reflection.StackTraceBack( log, eip, ebp, ebp, 0, TRUE , FALSE );
  278. log.Update;
  279. END TraceBackThis;
  280. PROCEDURE TraceBack*; (* do a stack trace back starting at the calling instruction position *)
  281. BEGIN
  282. TraceBackThis( Machine.CurrentPC(), SYSTEM.GetFramePointer() );
  283. END TraceBack;
  284. PROCEDURE Error* (err: WORD; pos: LONGINT; CONST msg: ARRAY OF CHAR);
  285. VAR str: ARRAY 128 OF CHAR;
  286. BEGIN {EXCLUSIVE}
  287. (** fof >> *)
  288. IF tracebackOnError THEN TraceBack() END;
  289. (** << fof *)
  290. error := error OR (err <= 400) OR (err >= 404);
  291. IF err = 400 THEN breakpos := pos END;
  292. GetMessage (err, msg, str);
  293. IF (err < 400) OR (err > 403) THEN
  294. INC (errors);
  295. IF errors > MaxErrors THEN
  296. RETURN
  297. ELSIF errors = MaxErrors THEN
  298. err := InvalidCode; pos := InvalidPosition; str := "too many errors"
  299. END;
  300. IF diagnostics # NIL THEN
  301. diagnostics.Error (source, pos, str);
  302. END;
  303. ELSE
  304. IF diagnostics # NIL THEN
  305. diagnostics.Information (source, pos, str);
  306. END;
  307. END;
  308. END Error;
  309. PROCEDURE ErrorN* (err: WORD; pos: LONGINT; msg: StringPool.Index);
  310. VAR str: ARRAY 256 OF CHAR;
  311. BEGIN
  312. StringPool.GetString(msg, str);
  313. Error(err, pos, str)
  314. END ErrorN;
  315. PROCEDURE Warning* (err, pos: LONGINT; CONST msg: ARRAY OF CHAR);
  316. VAR str: ARRAY 128 OF CHAR;
  317. BEGIN {EXCLUSIVE}
  318. IF ~(Warnings IN parserOptions) THEN RETURN END;
  319. INC (warnings);
  320. IF warnings > MaxWarnings THEN
  321. RETURN
  322. ELSIF warnings = MaxWarnings THEN
  323. err := InvalidCode; pos := InvalidPosition; str := "too many warnings"
  324. ELSE
  325. GetMessage (err, msg, str);
  326. END;
  327. IF diagnostics # NIL THEN
  328. diagnostics.Warning (source, pos, str);
  329. END;
  330. END Warning;
  331. PROCEDURE LogW* (ch: CHAR);
  332. BEGIN log.Char(ch)
  333. END LogW;
  334. PROCEDURE LogWStr* (CONST str: ARRAY OF CHAR);
  335. BEGIN log.String(str)
  336. END LogWStr;
  337. PROCEDURE LogWStr0* (str: StringPool.Index);
  338. VAR str0: ARRAY 256 OF CHAR;
  339. BEGIN
  340. StringPool.GetString(str, str0); LogWStr(str0)
  341. END LogWStr0;
  342. PROCEDURE LogWHex* (i: LONGINT);
  343. BEGIN log.Hex(i, 0)
  344. END LogWHex;
  345. PROCEDURE LogWNum* (i: LONGINT);
  346. BEGIN log.Int(i, 0)
  347. END LogWNum;
  348. PROCEDURE LogWBool* (b: BOOLEAN);
  349. BEGIN
  350. IF b THEN LogWStr("TRUE") ELSE LogWStr("FALSE") END
  351. END LogWBool;
  352. PROCEDURE LogWType* (p: ANY);
  353. VAR name: ARRAY 32 OF CHAR;
  354. BEGIN
  355. PCDebug.GetTypeName(p, name); LogWStr(name)
  356. END LogWType;
  357. PROCEDURE LogWLn*;
  358. BEGIN log.Ln
  359. END LogWLn;
  360. PROCEDURE LogFlush*;
  361. BEGIN log.Update
  362. END LogFlush;
  363. (** ---------- configuration functions --------------------- *)
  364. (** Init - Prepare module for a new compilation *)
  365. PROCEDURE Init*(CONST s: ARRAY OF CHAR; l: Streams.Writer; d: Diagnostics.Diagnostics); (* don't assume Reset is executed *)
  366. BEGIN
  367. COPY (s, source);
  368. log := l;
  369. IF log = NIL THEN Streams.OpenWriter( log, KernelLog.Send ) END;
  370. diagnostics := d;
  371. error := FALSE;
  372. errors := 0; warnings := 0;
  373. PCDebug.ResetToDo;
  374. END Init;
  375. (** Reset - allow deallocation of structures*)
  376. PROCEDURE Reset*;
  377. BEGIN
  378. PCDebug.ResetToDo;
  379. END Reset;
  380. (** SetErrorMsg - Set message for error n *)
  381. PROCEDURE SetErrorMsg*(n: LONGINT; CONST msg: ARRAY OF CHAR);
  382. BEGIN
  383. IF errMsg = NIL THEN NEW(errMsg, InitErrMsgSize) END;
  384. WHILE LEN(errMsg^) < n DO Expand(errMsg) END;
  385. StringPool.GetIndex(msg, errMsg[n])
  386. END SetErrorMsg;
  387. PROCEDURE Expand(VAR oldAry: ErrorMsgs);
  388. VAR
  389. len, i: LONGINT;
  390. newAry: ErrorMsgs;
  391. BEGIN
  392. IF oldAry = NIL THEN RETURN END;
  393. len := LEN(oldAry^);
  394. NEW(newAry, len * 2);
  395. FOR i := 0 TO len-1 DO
  396. newAry[i] := oldAry[i];
  397. END;
  398. oldAry := newAry;
  399. END Expand;
  400. PROCEDURE InitMod;
  401. BEGIN
  402. PCDebug.ResetToDo
  403. END InitMod;
  404. PROCEDURE SwapBytes*(VAR p: ARRAY OF SYSTEM.BYTE; offset, len: LONGINT);
  405. VAR i: LONGINT;
  406. tmp: SYSTEM.BYTE;
  407. BEGIN
  408. FOR i := 0 TO (len-1) DIV 2 DO
  409. tmp := p[offset+i];
  410. p[offset+i] := p[offset+len-1-i];
  411. p[offset+len-1-i] := tmp;
  412. END;
  413. END SwapBytes;
  414. PROCEDURE MakeErrorFile*;
  415. VAR f: Files.File; w: Files.Writer;
  416. msg, code: ARRAY 256 OF CHAR; i: LONGINT;
  417. BEGIN
  418. f := Files.New("Errors2.XML");
  419. IF f # NIL THEN
  420. Files.OpenWriter(w, f, 0);
  421. WHILE i < LEN(errMsg)-1 DO
  422. StringPool.GetString(errMsg[i], msg);
  423. w.String(" <Error code="); w.Char(CHR(34));
  424. Strings.IntToStr(i, code); w.String(code);
  425. w.Char(CHR(34)); w.String(">");
  426. w.String(msg);
  427. w.String("</Error>");
  428. w.Ln;
  429. INC(i);
  430. END;
  431. w.Update;
  432. Files.Register(f);
  433. ELSE
  434. KernelLog.String("Could not create file"); KernelLog.Ln;
  435. END;
  436. END MakeErrorFile;
  437. (** fof >> *)
  438. PROCEDURE TracebackOnError*;
  439. BEGIN
  440. tracebackOnError := ~tracebackOnError;
  441. IF tracebackOnError THEN LogWStr( "TracebackOnError=TRUE" ); ELSE LogWStr( "TracebackOnError=FALSE" ) END;
  442. LogWLn; LogFlush;
  443. END TracebackOnError;
  444. (** << fof *)
  445. BEGIN
  446. Streams.OpenWriter( log, KernelLog.Send );
  447. InitMod;
  448. prefix := "";
  449. COPY(Modules.extension[0], suffix)
  450. END PCM.
  451. (*
  452. 15.11.06 ug new compiler option /S added, FileVersion incremented
  453. 20.09.03 prk "/Dcode" compiler option added
  454. 24.06.03 prk Remove TDMask (no need to mask typedescriptors)
  455. 22.02.02 prk unicode support
  456. 22.01.02 prk cosmetic changes, some constants renamed
  457. 22.01.02 prk ToDo list moved to PCDebug
  458. 18.01.02 prk AosFS used instead of Files
  459. 10.12.01 prk ENTIER: rounding mode set to chop, rounding modes caches as globals
  460. 22.11.01 prk improved flag handling
  461. 19.11.01 prk definitions
  462. 23.07.01 prk read error messages into stringpool
  463. 05.07.01 prk optional explicit NIL checks
  464. 27.06.01 prk StringPool cleaned up
  465. 14.06.01 prk type descs for dynamic arrays of ptrs generated by the compiler
  466. 17.05.01 prk Delegates
  467. 26.04.01 prk separation of RECORD and OBJECT in the parser
  468. 25.04.01 prk array allocation: if length < 0 then trap PCM.ArraySizeTrap
  469. 30.03.01 prk object file version changed to 01X
  470. 29.03.01 prk Java imports
  471. *)