Generic.Reflection.Mod 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153
  1. MODULE Reflection;
  2. (** (c) Felix Friedrich, ETH Zurich, 2016 -- Reflection with more structured references section emitted by FoxCompiler *)
  3. IMPORT Modules, Streams, SYSTEM, Machine, Heaps, Objects, Trace;
  4. CONST
  5. ShowAllProcs = TRUE;
  6. MaxFrames = 128;
  7. MaxString = 64;
  8. MaxArray = 8;
  9. MaxCols = 70;
  10. Sep = " ";
  11. SepLen = 2;
  12. LineDelay = 0;
  13. CONST
  14. sfTypeNone* = 0X;
  15. sfTypeCHAR* = 01X;
  16. sfTypeCHAR8* = 02X;
  17. sfTypeCHAR16* = 03X;
  18. sfTypeCHAR32* = 04X;
  19. sfTypeRANGE* = 05X;
  20. sfTypeSHORTINT* = 06X;
  21. sfTypeINTEGER* = 07X;
  22. sfTypeLONGINT* = 08X;
  23. sfTypeHUGEINT* = 09X;
  24. sfTypeWORD* = 0AX;
  25. sfTypeLONGWORD* = 0BX;
  26. sfTypeSIGNED8* = 0CX;
  27. sfTypeSIGNED16* = 0DX;
  28. sfTypeSIGNED32* = 0EX;
  29. sfTypeSIGNED64* = 0FX;
  30. sfTypeUNSIGNED8* = 10X;
  31. sfTypeUNSIGNED16* = 11X;
  32. sfTypeUNSIGNED32* = 12X;
  33. sfTypeUNSIGNED64* = 13X;
  34. sfTypeREAL* = 14X;
  35. sfTypeLONGREAL* = 15X;
  36. sfTypeCOMPLEX* = 16X;
  37. sfTypeLONGCOMPLEX* = 17X;
  38. sfTypeBOOLEAN* = 18X;
  39. sfTypeSET* = 19X;
  40. sfTypeANY* = 1AX;
  41. sfTypeOBJECT* = 1BX;
  42. sfTypeBYTE* = 1CX;
  43. sfTypeADDRESS* = 1DX;
  44. sfTypeSIZE* = 1EX;
  45. sfTypeRecord* = 20X;
  46. sfTypePointerToRecord* = 21X;
  47. sfTypePointerToArray* = 22X;
  48. sfTypeOpenArray* = 23X;
  49. sfTypeStaticArray* = 24X;
  50. sfTypeDynamicArray* = 25X;
  51. sfTypeMathStaticArray* = 26X;
  52. sfTypeMathOpenArray* = 27X;
  53. sfTypeMathTensor* = 28X;
  54. sfTypeDelegate* = 29X;
  55. sfTypeENUM* = 2AX;
  56. sfTypeCELL* = 2BX;
  57. sfTypePORT* = 2CX;
  58. sfIN* = 0X;
  59. sfOUT* = 1X;
  60. (* variable / parameter addressing modes *)
  61. sfAbsolute* = 0X; (* global vars *)
  62. sfRelative* = 1X; (* variables, value parameters *)
  63. sfIndirect* = 2X; (* var parameters *)
  64. sfScopeBegin* = 0F0X;
  65. sfScopeEnd* = 0F1X;
  66. sfProcedure* = 0F2X;
  67. sfVariable* = 0F3X;
  68. sfTypeDeclaration* = 0F4X;
  69. sfModule*= 0FFX;
  70. (*
  71. References section format:
  72. Scope = sfScopeBegin {variable:Variable} {procedure:Procedure} {typeDecl:TypeDeclaration} sfScopeEnd.
  73. Module = sfModule prevSymbolOffset:SIZE name:String Scope.
  74. Procedure = sfProcedure prevSymbolOffset:SIZE name:String start:ADR end:ADR returnType:Type {parameter:Variable} Scope.
  75. Variable = sfVariable prevSymbolOffset:SIZE name:String (sfRelative offset: SIZE | sfIndirec offset: SIZE | sfAbsolute address:ADDRESS) type:Type.
  76. TypeDeclaration = sfTypeDeclaration prevSymbolOffset:SIZE name:String typeInfo:ADR Scope.
  77. Type =
  78. sfTypePointerToRecord
  79. | sfTypePointerToArray Type
  80. | sfTypeOpenArray Type
  81. | sfTypeDynamicArray Type
  82. | sfTypeStaticArray length:SIZE Type
  83. | sfTypeMathOpenArray Type
  84. | sfTypeMathStaticArray length:SIZE Type
  85. | sfTypeMathTensor Type
  86. | sfTypeRecord tdAdr:ADDRESS
  87. | sfTypeDelegate {Parameter} return:Type
  88. | sfTypePort (sfIN | sfOUT)
  89. | sfTypeBOOLEAN
  90. | sfTypeCHAR | sfTypeCHAR8 | sfTypeCHAR16 | sfTypeCHAR32
  91. | sfTypeSHORTINT | sfTypeINTEGER | sfTypeLONGINT | sfTypeHUGEINT
  92. | sfTypeSIGNED8 | sfTypeSIGNED16 | sfTypeSIGNED32 | sfTypeSIGNED64
  93. | sfTypeUNSIGNED8 | sfTypeUNSIGNED16 | sfTypeUNSIGNED32 | sfTypeUNSIGNED64
  94. | sfTypeWORD | sfTypeLONGWORD
  95. | sfTypeREAL | sfTypeLONGREAL
  96. | sfTypeCOMPLEX | sfTypeLONGCOMPLEX
  97. | sfTypeSET | sfTypeANY | sfTypeOBJECT | sfTypeBYTE | sfTypeADDRESS | sfTypeSIZE.
  98. *)
  99. VAR
  100. modes: ARRAY 25 OF CHAR;
  101. TYPE
  102. Name = ARRAY 128 OF CHAR;
  103. Meta* = RECORD
  104. module-: Modules.Module;
  105. refs-: Modules.Bytes;
  106. offset*: LONGINT;
  107. END;
  108. PROCEDURE CheckHeapAddress(address: ADDRESS): BOOLEAN;
  109. BEGIN
  110. RETURN Machine.ValidHeapAddress(address);
  111. END CheckHeapAddress;
  112. PROCEDURE Wait(w: Streams.Writer);
  113. VAR i: LONGINT;
  114. BEGIN
  115. IF LineDelay > 0 THEN
  116. FOR i := 0 TO LineDelay DO END;
  117. w.Update
  118. END;
  119. END Wait;
  120. PROCEDURE Expect(b: BOOLEAN): BOOLEAN;
  121. BEGIN
  122. IF ~b THEN Trace.String("Format error in references section"); Trace.Ln END;
  123. RETURN b;
  124. END Expect;
  125. (* consume a char from the byte stream *)
  126. PROCEDURE GetChar*(refs: Modules.Bytes; VAR offset: LONGINT): CHAR;
  127. VAR c: CHAR;
  128. BEGIN
  129. IF ~Expect(offset < LEN(refs)) THEN RETURN 0X END;
  130. c := refs[offset];
  131. INC(offset);
  132. RETURN c;
  133. END GetChar;
  134. (* skip a char in the byte stream *)
  135. PROCEDURE SkipChar*(VAR offset: LONGINT);
  136. BEGIN
  137. INC(offset, SIZEOF(CHAR));
  138. END SkipChar;
  139. (* consume an address in the byte stream *)
  140. PROCEDURE GetAddress*(refs: Modules.Bytes; VAR offset: LONGINT): ADDRESS;
  141. VAR adr: ADDRESS; i: LONGINT;
  142. BEGIN
  143. IF ~Expect(offset < LEN(refs)) THEN RETURN 0 END;
  144. FOR i := 0 TO SIZEOF(ADDRESS)-1 DO
  145. SYSTEM.PUT8(ADDRESSOF(adr)+i, GetChar(refs, offset));
  146. END;
  147. RETURN adr;
  148. END GetAddress;
  149. (* skip an address in the byte stream *)
  150. PROCEDURE SkipAddress*(VAR offset: LONGINT);
  151. BEGIN
  152. INC(offset, SIZEOF(ADDRESS));
  153. END SkipAddress;
  154. (* consume a size in the byte stream *)
  155. PROCEDURE GetSize*(refs: Modules.Bytes; VAR offset: LONGINT): SIZE;
  156. VAR size: SIZE; i: LONGINT;
  157. BEGIN
  158. IF ~Expect(offset < LEN(refs)) THEN RETURN 0 END;
  159. FOR i := 0 TO SIZEOF(SIZE)-1 DO
  160. SYSTEM.PUT8(ADDRESSOF(size)+i, refs[offset]);
  161. INC(offset);
  162. END;
  163. RETURN size;
  164. END GetSize;
  165. (* skip a size in the byte stream *)
  166. PROCEDURE SkipSize*(VAR offset: LONGINT);
  167. BEGIN
  168. INC(offset, SIZEOF(SIZE));
  169. END SkipSize;
  170. (* consume a string in the byte stream *)
  171. PROCEDURE GetString*(refs: Modules.Bytes; VAR offset: LONGINT; VAR string: ARRAY OF CHAR);
  172. VAR ch: CHAR; i: LONGINT;
  173. BEGIN
  174. i := 0;
  175. REPEAT
  176. ch := GetChar(refs, offset);
  177. string[i] := ch;
  178. INC(i);
  179. UNTIL ch = 0X;
  180. END GetString;
  181. (* skip a string in the byte stream *)
  182. PROCEDURE SkipString*(refs: Modules.Bytes; VAR offset: LONGINT);
  183. BEGIN
  184. WHILE(refs[offset] # 0X) DO INC(offset) END; INC(offset);
  185. END SkipString;
  186. (* extract a full name from the byte stream by traversing up the symbols in their scopes *)
  187. PROCEDURE GetFullName*(refs: Modules.Bytes; offset: LONGINT; VAR name: ARRAY OF CHAR);
  188. VAR n: LONGINT;
  189. PROCEDURE Traverse(offset: LONGINT);
  190. VAR c: CHAR;
  191. BEGIN
  192. IF offset >= 0 THEN
  193. c := GetChar(refs, offset);
  194. IF (c = sfProcedure) OR (c=sfVariable) OR (c=sfTypeDeclaration) OR (c=sfModule) THEN
  195. Traverse(GetSize(refs, offset));
  196. END;
  197. IF (n > 0) & (n<LEN(name)) THEN name[n] := "."; INC(n); END;
  198. WHILE (n<LEN(name)) & (refs[offset] # 0X) DO
  199. name[n] := refs[offset];
  200. INC(n); INC(offset);
  201. END;
  202. END;
  203. END Traverse;
  204. BEGIN
  205. n := 0;
  206. Traverse(offset);
  207. name[n] := 0X;
  208. END GetFullName;
  209. (* "lock free" version of Modules.ThisTypeByAdr *)
  210. PROCEDURE ThisTypeByAdr(adr: ADDRESS; VAR m: Modules.Module; VAR t: Modules.TypeDesc);
  211. BEGIN
  212. IF adr # 0 THEN
  213. SYSTEM.GET (adr + Heaps.TypeDescOffset, adr);
  214. IF CheckHeapAddress(adr) THEN
  215. t := SYSTEM.VAL(Modules.TypeDesc, adr);
  216. m := t.mod;
  217. ELSE
  218. m := NIL; t := NIL
  219. END
  220. ELSE
  221. m := NIL; t := NIL
  222. END
  223. END ThisTypeByAdr;
  224. (* output type descriptor information *)
  225. PROCEDURE WriteType*(w: Streams.Writer; adr: ADDRESS);
  226. VAR module: Modules.Module; typeDesc: Modules.TypeDesc;
  227. BEGIN
  228. IF CheckHeapAddress(adr) THEN
  229. ThisTypeByAdr(adr, module, typeDesc);
  230. IF module # NIL THEN
  231. w.String(module.name);
  232. ELSE
  233. w.String("NIL"); RETURN
  234. END;
  235. w.String(".");
  236. IF typeDesc # NIL THEN
  237. IF typeDesc.name = "" THEN
  238. w.String("ANONYMOUS")
  239. ELSE
  240. w.String(typeDesc.name);
  241. END;
  242. ELSE
  243. w.String("NIL");
  244. END;
  245. ELSE
  246. w.String("UNKNOWN");
  247. END;
  248. END WriteType;
  249. (* Write the specified procedure name and returns parameters for use with Variables *)
  250. PROCEDURE WriteProc0(w: Streams.Writer; mod: Modules.Module; pc, fp: ADDRESS; VAR refs: Modules.Bytes; VAR refpos: LONGINT; VAR base: ADDRESS);
  251. VAR ch: CHAR; startpc, end: ADDRESS; offset: LONGINT; name: Name;
  252. BEGIN
  253. refpos := -1;
  254. IF mod = NIL THEN
  255. IF pc = 0 THEN w.String("NIL")
  256. ELSE
  257. w.String("Unknown PC="); w.Address(pc); w.Char("H")
  258. END;
  259. IF fp # -1 THEN
  260. w.String(" FP="); w.Address(fp); w.Char("H")
  261. END
  262. ELSE
  263. refs := mod.refs;
  264. refpos := FindByAdr(refs, 0, pc);
  265. IF refpos >= 0 THEN
  266. offset := refpos;
  267. IF GetChar(refs, offset) = sfProcedure THEN
  268. SkipSize(offset);
  269. SkipString(refs, offset);
  270. GetFullName(refs, refpos, name);
  271. startpc := GetAddress(refs, offset);
  272. end := GetAddress(refs, offset);
  273. w.String(name);
  274. w.Char(":"); w.Int(LONGINT(pc-startpc),1);
  275. base := fp; (*! only for local !! *)
  276. refpos := offset;
  277. END;
  278. ELSE
  279. w.String("procedure not found in module "); w.String(mod.name);
  280. END;
  281. w.String(" pc="); w.Int(LONGINT(pc),1); w.String(" ["); w.Address (pc); w.String("H]");
  282. w.String(" = "); w.Int(LONGINT(startpc),1); w.String(" + "); w.Int(LONGINT(pc-startpc),1);
  283. w.String(" crc="); w.Hex(mod.crc,-8);
  284. (*Wait(w);*)
  285. END
  286. END WriteProc0;
  287. PROCEDURE WriteBasicValue*(w: Streams.Writer; type: CHAR; adr: ADDRESS; VAR size: SIZE);
  288. VAR
  289. b: BOOLEAN;
  290. c: CHAR; c8: CHAR8; c16: CHAR16; c32: CHAR32;
  291. s: SHORTINT; i: INTEGER; l: LONGINT; h: HUGEINT;
  292. sz: SIZE; a: ADDRESS;
  293. word: WORD; lword: LONGWORD;
  294. s8: SIGNED8; s16: SIGNED16; s32: SIGNED32; s64: SIGNED64;
  295. u8: UNSIGNED8; u16: UNSIGNED16; u32: UNSIGNED32; u64: UNSIGNED64;
  296. r: REAL; x: LONGREAL;
  297. cplx: COMPLEX; lcplx: LONGCOMPLEX;
  298. set: SET;
  299. byte: SYSTEM.BYTE;
  300. PROCEDURE Signed(i: HUGEINT);
  301. BEGIN
  302. w.Int(i,1);
  303. END Signed;
  304. PROCEDURE Unsigned(i: HUGEINT; size: LONGINT);
  305. BEGIN
  306. w.Hex(i,-2*size);
  307. END Unsigned;
  308. BEGIN
  309. CASE type OF
  310. | sfTypePointerToRecord, sfTypeANY, sfTypeOBJECT:
  311. size := SIZEOF(ADDRESS);
  312. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  313. | sfTypeBOOLEAN:
  314. size := SIZEOF(BOOLEAN);
  315. SYSTEM.GET(adr, b); IF b THEN w.String("true") ELSE w.String("false") END;
  316. | sfTypeCHAR, sfTypeCHAR8:
  317. size := SIZEOF(CHAR);
  318. SYSTEM.GET(adr, c); IF (c > " ") & (c <= "~") THEN w.Char( c ); ELSE w.Hex( ORD( c ), -2 ); w.Char( "X" ) END;
  319. | sfTypeCHAR16:
  320. size := SIZEOF(CHAR16);
  321. SYSTEM.GET(adr, i); w.Hex(i,-4); w.Char("X");
  322. | sfTypeCHAR32:
  323. size := SIZEOF(CHAR32);
  324. SYSTEM.GET(adr, l); w.Hex(l,-8); w.Char("X");
  325. | sfTypeSHORTINT:
  326. size := SIZEOF(SHORTINT);
  327. SYSTEM.GET(adr, s); Signed(s);
  328. | sfTypeINTEGER:
  329. size := SIZEOF(INTEGER);
  330. SYSTEM.GET(adr, i); Signed(i);
  331. | sfTypeLONGINT:
  332. size := SIZEOF(LONGINT);
  333. SYSTEM.GET(adr, l); Signed(l);
  334. | sfTypeHUGEINT:
  335. size := SIZEOF(HUGEINT);
  336. SYSTEM.GET(adr, h); Signed(h);
  337. | sfTypeWORD:
  338. size := SIZEOF(WORD);
  339. SYSTEM.GET(adr, word); Signed(word);
  340. | sfTypeLONGWORD:
  341. size := SIZEOF(LONGWORD);
  342. SYSTEM.GET(adr, lword); Signed(lword);;
  343. | sfTypeSIGNED8:
  344. size := SIZEOF(SIGNED8);
  345. SYSTEM.GET(adr, s8); Signed(s8);
  346. | sfTypeSIGNED16:
  347. size := SIZEOF(SIGNED16);
  348. SYSTEM.GET(adr, s16); Signed(s16);
  349. | sfTypeSIGNED32:
  350. size := SIZEOF(SIGNED32);
  351. SYSTEM.GET(adr, s32); Signed(s32);
  352. | sfTypeSIGNED64:
  353. size := SIZEOF(SIGNED64);
  354. SYSTEM.GET(adr, s64); Signed(s64);
  355. | sfTypeUNSIGNED8:
  356. size := SIZEOF(UNSIGNED8);
  357. SYSTEM.GET(adr, u8); Unsigned(u8, SIZEOF(UNSIGNED8));
  358. | sfTypeUNSIGNED16:
  359. size := SIZEOF(UNSIGNED16);
  360. SYSTEM.GET(adr, u16); Unsigned(u16, SIZEOF(UNSIGNED16));
  361. | sfTypeUNSIGNED32:
  362. size := SIZEOF(UNSIGNED32);
  363. SYSTEM.GET(adr, u32); Unsigned(u32, SIZEOF(UNSIGNED32));
  364. | sfTypeUNSIGNED64:
  365. size := SIZEOF(UNSIGNED64);
  366. SYSTEM.GET(adr, s64); Unsigned(s64, SIZEOF(UNSIGNED64));
  367. | sfTypeREAL:
  368. size := SIZEOF(REAL);
  369. SYSTEM.GET(adr, r); w.Float(r,7);
  370. w.String(" (");
  371. SYSTEM.GET(adr, u32); Unsigned(u32, SIZEOF(UNSIGNED32));
  372. w.String(")");
  373. | sfTypeLONGREAL:
  374. size := SIZEOF(LONGREAL);
  375. SYSTEM.GET(adr, x); w.Float(x,13);
  376. w.String(" (");
  377. SYSTEM.GET(adr, s64); Unsigned(s64, SIZEOF(UNSIGNED64));
  378. w.String(")");
  379. | sfTypeCOMPLEX:
  380. size := SIZEOF(COMPLEX);
  381. SYSTEM.GET(adr, cplx); w.Float(RE(cplx),7); w.String("+ i*"); w.Float(IM(cplx),7);
  382. | sfTypeLONGCOMPLEX:
  383. size := SIZEOF(LONGCOMPLEX);
  384. SYSTEM.GET(adr, x); w.Float(x,13); SYSTEM.GET(adr + SIZEOF(LONGREAL), x); w.String("+ i*"); w.Float(x,13);
  385. | sfTypeSET:
  386. size := SIZEOF(SET);
  387. SYSTEM.GET(adr, set); w.Set(set);
  388. | sfTypeBYTE:
  389. size := SIZEOF(SYSTEM.BYTE);
  390. SYSTEM.GET(adr, c); Unsigned(ORD(c), 1);
  391. | sfTypeRANGE:
  392. size := SIZEOF(RANGE);
  393. SYSTEM.GET(adr, sz); Unsigned(sz,SIZEOF(SIZE)); w.String(".."); Unsigned(sz, SIZEOF(SIZE));
  394. | sfTypeADDRESS:
  395. size := SIZEOF(ADDRESS);
  396. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  397. | sfTypeSIZE:
  398. size := SIZEOF(SIZE);
  399. SYSTEM.GET(adr, sz); Signed(sz); w.String("["); Unsigned(sz, SIZEOF(SIZE)); w.String("]");
  400. | sfTypeENUM:
  401. SYSTEM.GET(adr, word); Signed(word);
  402. | sfTypePORT:
  403. SYSTEM.GET(adr, a); Unsigned(a, SIZEOF(ADDRESS));
  404. ELSE
  405. w.String("UNKOWN TYPE "); Unsigned(ORD(type),1);
  406. END;
  407. w.Update;
  408. END WriteBasicValue;
  409. PROCEDURE OnHeapOrStack(adr: ADDRESS; low, high: ADDRESS): BOOLEAN;
  410. BEGIN
  411. RETURN (low <= adr) & (adr < high) OR CheckHeapAddress(adr);
  412. END OnHeapOrStack;
  413. PROCEDURE WriteValueString*(w: Streams.Writer; adr: ADDRESS; maxLen: LONGINT; low, high: ADDRESS);
  414. CONST MaxString = 32;
  415. VAR ch: CHAR;
  416. BEGIN
  417. IF maxLen > MaxString THEN maxLen := MaxString END;
  418. w.Char('"');
  419. LOOP
  420. IF (maxLen <= 0) OR ~OnHeapOrStack(adr, low, high) THEN
  421. EXIT END;
  422. SYSTEM.GET(adr, ch);
  423. IF (ch < " ") OR (ch > "~") THEN EXIT END;
  424. w.Char(ch);
  425. INC(adr);
  426. DEC(maxLen);
  427. END;
  428. w.Char('"');
  429. END WriteValueString;
  430. PROCEDURE WriteValue*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT; adr: ADDRESS; low, high: ADDRESS);
  431. VAR type: CHAR; a: ADDRESS; size: SIZE; len: SIZE;
  432. BEGIN
  433. IF ~OnHeapOrStack(adr, low, high) THEN
  434. SkipType(refs, offset);
  435. w.String("INVALID ADR:"); w.Address(adr);
  436. RETURN;
  437. END;
  438. type := GetChar(refs, offset);
  439. CASE type OF
  440. sfTypeNone:
  441. w.String("NONE");
  442. | sfTypePointerToRecord, sfTypeANY, sfTypeOBJECT:
  443. WriteBasicValue(w,type, adr, size);
  444. SYSTEM.GET(adr, a);
  445. IF a = 0 THEN
  446. w.String("NIL");
  447. ELSIF CheckHeapAddress(a) THEN
  448. SYSTEM.GET(a + Heaps.TypeDescOffset, a);
  449. w.String(" (");
  450. WriteType(w,a);
  451. w.String(")");
  452. ELSE
  453. w.String("(UNKNOWN)");
  454. END;
  455. | sfTypePointerToArray:
  456. WriteBasicValue(w, sfTypeANY, adr, size);
  457. SYSTEM.GET(adr, a);
  458. IF ~OnHeapOrStack(a,low,high) THEN w.String(" (INVALID)") END;
  459. SkipType(refs, offset)
  460. | sfTypeOpenArray:
  461. IF (refs[offset] = sfTypeCHAR) OR (refs[offset] = sfTypeCHAR8) THEN (* ARRAY OF CHAR *)
  462. SYSTEM.GET(adr, a);
  463. WriteValueString(w, a, MaxString, low, high);
  464. ELSE
  465. w.String("... (NO STRING)")
  466. END;
  467. SkipType(refs, offset);
  468. | sfTypeStaticArray:
  469. len := GetSize(refs, offset);
  470. IF (refs[offset] = sfTypeCHAR) OR (refs[offset] = sfTypeCHAR8) THEN (* ARRAY x OF CHAR *)
  471. WriteValueString(w, adr, len, low, high);
  472. ELSE
  473. w.String("... (NO STRING)");
  474. END;
  475. SkipType(refs, offset);
  476. | sfTypeDynamicArray:
  477. w.String("... (DYNAMIC ARRAY)");
  478. SkipType(refs, offset);
  479. | sfTypeMathOpenArray:
  480. w.String("... (MATH OPEN ARRAY)");
  481. SkipType(refs, offset);
  482. | sfTypeMathStaticArray:
  483. w.String("... (MATH STATIC ARRAY)");
  484. SkipSize(offset); SkipType(refs, offset);
  485. | sfTypeMathTensor:
  486. w.String("...(MATH TENSOR)");
  487. SkipType(refs, offset);
  488. | sfTypeRecord:
  489. w.String("...");
  490. w.String("(");
  491. a := GetAddress(refs, offset);
  492. WriteType(w,a);
  493. w.String(")");
  494. | sfTypeDelegate:
  495. w.String("(DELEGATE)");
  496. WHILE refs[offset] = sfVariable DO SkipVariable(refs, offset) END;
  497. SkipType(refs, offset);
  498. | sfTypePORT:
  499. WriteBasicValue(w, type, adr, size);
  500. SkipChar(offset);
  501. ELSE
  502. WriteBasicValue(w, type, adr, size);
  503. END;
  504. w.Update;
  505. END WriteValue;
  506. PROCEDURE WriteVariable*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT; base: ADDRESS; low, high: ADDRESS);
  507. VAR name: ARRAY 128 OF CHAR; adr: LONGINT; prevScope: SIZE; c: CHAR;
  508. BEGIN
  509. IF ~Expect(GetChar(refs, offset) = sfVariable) THEN RETURN END;
  510. prevScope := GetSize(refs, offset);
  511. GetString(refs, offset, name);
  512. w.String(Sep); w.String(name); w.Char("=");
  513. c := GetChar(refs, offset);
  514. IF c = sfRelative THEN
  515. adr := base + GetSize(refs, offset)
  516. ELSIF c = sfIndirect THEN
  517. adr := base + GetSize(refs, offset);
  518. w.Address(adr); w.String("->");
  519. IF ~OnHeapOrStack(adr,low,high) THEN w.String(" (INVALID)");
  520. SkipType(refs,offset);
  521. RETURN;
  522. END;
  523. SYSTEM.GET(adr, adr);
  524. ELSE (* absolute *)
  525. adr := GetAddress(refs, offset);
  526. END;
  527. WriteValue(w, refs, offset, adr, low, high);
  528. END WriteVariable;
  529. (* write variables taking meta information from stream in stream at offset, potentially stored at base address
  530. *)
  531. PROCEDURE WriteVariables*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT; base: ADDRESS; low, high: ADDRESS);
  532. VAR count: LONGINT;
  533. BEGIN
  534. WHILE refs[offset] = sfVariable DO
  535. WriteVariable(w, refs, offset, base, low, high); w.Ln;
  536. (*INC(count); *)
  537. END;
  538. IF count > 0 THEN w.Ln; Wait(w); END;
  539. END WriteVariables;
  540. (* skip type metadata in stream *)
  541. PROCEDURE SkipType*(refs: Modules.Bytes; VAR offset: LONGINT);
  542. VAR size: SIZE; adr: LONGINT; c: CHAR;
  543. BEGIN
  544. c := GetChar(refs, offset);
  545. CASE c OF
  546. sfTypeNone .. sfTypeSIZE:
  547. | sfTypePointerToRecord:
  548. | sfTypePointerToArray: SkipType(refs, offset);
  549. | sfTypeOpenArray: SkipType(refs, offset);
  550. | sfTypeStaticArray: SkipSize(offset); SkipType(refs, offset);
  551. | sfTypeDynamicArray: SkipType(refs, offset);
  552. | sfTypeMathOpenArray: SkipType(refs, offset);
  553. | sfTypeMathStaticArray: SkipSize(offset); SkipType(refs, offset);
  554. | sfTypeMathTensor: SkipType(refs, offset);
  555. | sfTypeRecord: SkipSize(offset);
  556. | sfTypeDelegate:
  557. WHILE refs[offset] = sfVariable DO SkipVariable(refs, offset) END;
  558. SkipType(refs, offset);
  559. | sfTypeENUM:
  560. | sfTypePORT: SkipChar(offset);
  561. ELSE (* ?? *)
  562. END;
  563. END SkipType;
  564. (* skip procedure metadata in stream *)
  565. PROCEDURE SkipProcedure*(refs: Modules.Bytes; VAR offset: LONGINT);
  566. BEGIN
  567. IF ~Expect(GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  568. SkipSize(offset);
  569. SkipString(refs, offset);
  570. SkipAddress(offset);
  571. SkipAddress(offset);
  572. WHILE (refs[offset] = sfVariable) DO SkipVariable(refs, offset) END;
  573. SkipType(refs, offset);
  574. SkipScope(refs, offset);
  575. END SkipProcedure;
  576. (* skip variable metadata in stream *)
  577. PROCEDURE SkipVariable*(refs: Modules.Bytes; VAR offset: LONGINT);
  578. BEGIN
  579. IF ~Expect(GetChar(refs, offset) = sfVariable) THEN RETURN END;
  580. SkipSize(offset);
  581. SkipString(refs, offset);
  582. SkipChar(offset);
  583. SkipAddress(offset);
  584. SkipType(refs, offset);
  585. END SkipVariable;
  586. (* skip type declaration meta data in stream *)
  587. PROCEDURE SkipTypeDeclaration*(refs: Modules.Bytes; VAR offset: LONGINT);
  588. BEGIN
  589. IF ~Expect(GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  590. SkipSize(offset);
  591. SkipString(refs, offset);
  592. SkipAddress(offset);
  593. IF refs[offset] = sfScopeBegin THEN SkipScope(refs, offset) END;
  594. END SkipTypeDeclaration;
  595. (* skip type declaration meta data in stream *)
  596. PROCEDURE SkipModule*(refs: Modules.Bytes; VAR offset: LONGINT);
  597. BEGIN
  598. IF ~Expect(GetChar(refs, offset) = sfModule) THEN RETURN END;
  599. SkipSize(offset);
  600. SkipString(refs, offset);
  601. IF refs[offset] = sfScopeBegin THEN SkipScope(refs, offset) END;
  602. END SkipModule;
  603. (* skip a scope in stream *)
  604. PROCEDURE SkipScope*(refs: Modules.Bytes; VAR offset: LONGINT);
  605. BEGIN
  606. IF ~Expect(GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  607. WHILE (refs[offset] = sfVariable) DO SkipVariable(refs, offset) END;
  608. WHILE (refs[offset] = sfProcedure) DO SkipProcedure(refs, offset) END;
  609. WHILE (refs[offset] = sfTypeDeclaration) DO SkipTypeDeclaration(refs, offset) END;
  610. IF ~Expect(GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  611. END SkipScope;
  612. TYPE
  613. Search = RECORD
  614. name: ARRAY 256 OF CHAR; (* for search by name *)
  615. nameOffset: LONGINT; (* to incrementally search through scopes *)
  616. minLevel: LONGINT; (* in order to stop scope search *)
  617. pc: ADDRESS; (* for search by address *)
  618. pos: LONGINT; (* symbol position in stream, -1 if not found *)
  619. found: BOOLEAN; (* if found *)
  620. END;
  621. (* check if stream contains the string part stored in search record with respective offset *)
  622. PROCEDURE FindString(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  623. VAR ofs: LONGINT;
  624. BEGIN
  625. IF find.minLevel > level THEN
  626. SkipString(refs, offset)
  627. ELSE
  628. ofs := find.nameOffset;
  629. WHILE (refs[offset] # 0X) & (find.name[ofs] = refs[offset]) DO
  630. INC(offset); INC(ofs);
  631. END;
  632. IF (refs[offset] = 0X) THEN
  633. IF find.name[ofs] = 0X THEN
  634. find.found := TRUE;
  635. ELSIF find.name[ofs] = "." THEN
  636. find.minLevel := level+1;
  637. find.nameOffset := ofs+1;
  638. END;
  639. END;
  640. WHILE(refs[offset] # 0X) DO INC(offset) END;
  641. INC(offset);
  642. END;
  643. END FindString;
  644. (* find a symbol by name or pc starting from the procedure stream section *)
  645. PROCEDURE FindInProcedure(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  646. VAR name: ARRAY 128 OF CHAR; start, end, pos: LONGINT;
  647. BEGIN
  648. pos := offset;
  649. IF ~Expect(GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  650. SkipSize(offset);
  651. FindString(refs, offset, level, find);
  652. start := GetAddress(refs, offset);
  653. end := GetAddress(refs, offset);
  654. find.found := find.found OR (start <= find.pc) & (find.pc < end);
  655. IF find.found THEN
  656. find.pos := pos;
  657. RETURN;
  658. END;
  659. WHILE (refs[offset] = sfVariable) DO
  660. IF find.minLevel <= level+1 THEN
  661. FindInVariable(refs, offset, level+1, find);
  662. IF find.found THEN RETURN END;
  663. ELSE
  664. SkipVariable(refs, offset)
  665. END;
  666. END;
  667. SkipType(refs, offset);
  668. FindInScope(refs, offset, level+1, find);
  669. END FindInProcedure;
  670. (* find a symbol by name or pc starting from the variable stream section *)
  671. PROCEDURE FindInVariable(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  672. VAR name: ARRAY 128 OF CHAR; pos: LONGINT;
  673. BEGIN
  674. pos := offset;
  675. IF ~Expect(GetChar(refs, offset) = sfVariable) THEN RETURN END;
  676. SkipSize(offset);
  677. FindString(refs, offset, level, find);
  678. IF find.found THEN
  679. find.pos := pos;
  680. RETURN;
  681. END;
  682. SkipChar(offset);
  683. SkipSize(offset);
  684. SkipType(refs, offset);
  685. END FindInVariable;
  686. (* find a symbol by name or pc starting from the type declaration stream section *)
  687. PROCEDURE FindInTypeDeclaration(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  688. VAR name: ARRAY 128 OF CHAR; adr, pos: LONGINT;
  689. BEGIN
  690. pos := offset;
  691. IF ~Expect(GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  692. SkipSize(offset);
  693. FindString(refs, offset, level, find);
  694. IF find.found THEN
  695. find.pos := pos;
  696. RETURN;
  697. END;
  698. SkipAddress(offset);
  699. IF refs[offset] = sfScopeBegin THEN FindInScope(refs, offset, level+1, find) END;
  700. END FindInTypeDeclaration;
  701. PROCEDURE FindInModule(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  702. VAR pos: LONGINT;
  703. BEGIN
  704. pos := offset;
  705. IF ~Expect(GetChar(refs, offset) = sfModule) THEN RETURN END;
  706. SkipSize(offset);
  707. FindString(refs, offset, level, find);
  708. IF find.found THEN
  709. find.pos := pos;
  710. RETURN;
  711. END;
  712. FindInScope(refs, offset, level+1, find);
  713. END FindInModule;
  714. (* find a symbol by name or pc in a scope in the stream *)
  715. PROCEDURE FindInScope(refs: Modules.Bytes; VAR offset: LONGINT; level: LONGINT; VAR find: Search);
  716. VAR no,i: LONGINT;
  717. BEGIN
  718. IF ~Expect(GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  719. WHILE ~find.found &(refs[offset] = sfVariable) & (find.minLevel <= level) DO (* Variable *)
  720. FindInVariable(refs, offset, level, find);
  721. END;
  722. WHILE ~find.found & (refs[offset] = sfProcedure) & (find.minLevel <= level) DO (* Procedure *)
  723. FindInProcedure(refs, offset, level, find);
  724. END;
  725. WHILE ~find.found & (refs[offset] = sfTypeDeclaration) & (find.minLevel <= level) DO (* TypeDeclaration *)
  726. FindInTypeDeclaration(refs, offset,level, find);
  727. END;
  728. IF find.found OR (find.minLevel > level) THEN RETURN END;
  729. IF ~Expect(GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  730. END FindInScope;
  731. PROCEDURE InitSearch(VAR search: Search);
  732. BEGIN
  733. search.found := FALSE;
  734. search.pos := -1;
  735. search.name := "";
  736. search.nameOffset := 0;
  737. search.minLevel := 0;
  738. search.pc := 0;
  739. END InitSearch;
  740. (* Find a symbol in the stream starting at offset.
  741. If name is supposed to contain the referred to symbol, choose skipFirstSymbol = FALSE
  742. Example FindByName(m.refs, 0, "Reflection.FindByName", FALSE)
  743. otherwise choose skipFirstSymbol = TRUE
  744. Example FindByName(m.refs, 0, "FindByName", TRUE);
  745. *)
  746. PROCEDURE FindByName*(refs: Modules.Bytes; offset: LONGINT; CONST name: ARRAY OF CHAR; skipFirstSymbol: BOOLEAN): SIZE;
  747. VAR search: Search;
  748. BEGIN
  749. InitSearch(search);
  750. COPY(name, search.name);
  751. IF skipFirstSymbol THEN search.minLevel := 1 END;
  752. CASE refs[offset] OF
  753. sfModule: FindInModule(refs, offset, 0, search);
  754. |sfVariable: FindInVariable(refs, offset, 0, search);
  755. |sfProcedure: FindInProcedure(refs, offset, 0, search);
  756. |sfTypeDeclaration: FindInTypeDeclaration(refs, offset, 0, search);
  757. ELSE (* wrong position in stream *)
  758. END;
  759. RETURN search.pos;
  760. END FindByName;
  761. PROCEDURE FindByAdr*(refs: Modules.Bytes; offset: SIZE; pc: ADDRESS): SIZE;
  762. VAR search: Search;
  763. BEGIN
  764. InitSearch(search);
  765. search.pc := pc;
  766. CASE refs[offset] OF
  767. sfModule: FindInModule(refs, offset, 0, search);
  768. |sfVariable: FindInVariable(refs, offset, 0, search);
  769. |sfProcedure: FindInProcedure(refs, offset, 0, search);
  770. |sfTypeDeclaration: FindInTypeDeclaration(refs, offset, 0, search);
  771. ELSE (* wrong position in stream *)
  772. END;
  773. RETURN search.pos;
  774. END FindByAdr;
  775. (** service procedures *)
  776. (** Find procedure name and write it. *)
  777. PROCEDURE WriteProc*(w: Streams.Writer; pc: ADDRESS);
  778. VAR refs: Modules.Bytes; refpos: LONGINT; base: ADDRESS;
  779. BEGIN
  780. WriteProc0(w, Modules.ThisModuleByAdr0(pc), pc, -1, refs, refpos, base)
  781. END WriteProc;
  782. (** Write the state of the specified module. *)
  783. PROCEDURE ModuleState*(w: Streams.Writer; mod: Modules.Module);
  784. VAR offset: LONGINT; base: ADDRESS; refs: Modules.Bytes;
  785. BEGIN
  786. IF mod = NIL THEN RETURN END;
  787. refs := mod.refs;
  788. offset := 0;
  789. w.String("State "); w.String(mod.name); w.Char(":"); w.Ln; Wait(w);
  790. IF (GetChar(refs, offset) = sfModule) THEN
  791. SkipSize(offset);
  792. SkipString(refs, offset);
  793. IF (GetChar(refs, offset) = sfScopeBegin) THEN
  794. WriteVariables(w, refs, offset, 0, 0, 0)
  795. END;
  796. END;
  797. END ModuleState;
  798. PROCEDURE CheckBP(bp: ADDRESS): ADDRESS;
  799. VAR n: ADDRESS;
  800. BEGIN
  801. IF bp # NIL THEN
  802. SYSTEM.GET(bp, n);
  803. IF ODD(n) THEN INC(bp, SIZEOF(ADDRESS)) END;
  804. END;
  805. RETURN bp;
  806. END CheckBP;
  807. (* Display call trackback. *)
  808. PROCEDURE StackTraceBack*(w: Streams.Writer; pc, bp: ADDRESS; low,high: ADDRESS; long, overflow: BOOLEAN);
  809. VAR count,offset: LONGINT; stacklow: ADDRESS; base: ADDRESS; m: Modules.Module; refs: Modules.Bytes;
  810. BEGIN
  811. count := 0; (* frame count *)
  812. REPEAT
  813. m := Modules.ThisModuleByAdr0(pc);
  814. IF (ShowAllProcs OR (m # NIL) OR (count = 0)) & (bp # 0) & (bp >= low) & (bp < high) THEN
  815. IF CheckHeapAddress( pc ) THEN
  816. WriteProc0(w, m, pc, bp, refs, offset, base); w.Ln;Wait(w); w.Update;
  817. IF long & (~overflow OR (count > 0)) THEN (* show variables *)
  818. IF offset >= 0 THEN
  819. WriteVariables(w,refs,offset, base, low, high);
  820. SkipType(refs, offset);
  821. IF Expect(GetChar(refs, offset) = sfScopeBegin) THEN
  822. WriteVariables(w,refs,offset, base, low, high);
  823. END;
  824. END;
  825. IF (m # NIL) & (base # m.sb) & (count = 0) THEN ModuleState(w, m) END
  826. END;
  827. ELSE
  828. w.String( "Unknown external procedure, pc = " ); w.Address( pc ); w.Ln; Wait(w);
  829. END;
  830. bp := CheckBP(bp);
  831. SYSTEM.GET(bp + SIZEOF(ADDRESS), pc); (* return addr from stack *)
  832. SYSTEM.GET(bp, bp); (* follow dynamic link *)
  833. INC(count)
  834. ELSE
  835. bp := 0
  836. END;
  837. UNTIL (bp = 0) OR (count = MaxFrames);
  838. IF bp # 0 THEN w.String("...") END
  839. END StackTraceBack;
  840. (** Write a process's state in one line. *)
  841. PROCEDURE WriteProcess*(w: Streams.Writer; p: Objects.Process);
  842. VAR adr: ADDRESS; mode: LONGINT; m: Modules.Module;
  843. BEGIN
  844. IF p # NIL THEN
  845. w.Int(p.id, 5);
  846. mode := p.mode;
  847. IF (mode >= Objects.Ready) & (mode <= Objects.Terminated) THEN
  848. adr := (mode-Objects.Ready)*4;
  849. FOR adr := adr TO adr+3 DO w.Char(modes[adr]) END
  850. ELSE
  851. w.Char(" "); w.Int(mode, 1)
  852. END;
  853. w.Int(p.procID, 2);
  854. w.Int(p.priority, 2);
  855. w.Update;
  856. w.Address (SYSTEM.VAL(ADDRESS, p.obj));
  857. IF p.obj # NIL THEN
  858. SYSTEM.GET(SYSTEM.VAL(ADDRESS, p.obj) - SIZEOF(ADDRESS), adr);
  859. w.Char(":"); WriteType(w, adr)
  860. END;
  861. w.Update;
  862. w.Char(" "); WriteProc(w, p.state.PC);
  863. IF p.mode = Objects.AwaitingLock THEN
  864. adr := SYSTEM.VAL(ADDRESS, p.waitingOn);
  865. w.Address (adr);
  866. w.Update;
  867. IF adr # 0 THEN (* can be 0 when snapshot is taken *)
  868. SYSTEM.GET(adr - SIZEOF(ADDRESS), adr);
  869. IF adr = SYSTEM.TYPECODE(Modules.Module) THEN
  870. w.Char("-");
  871. m := SYSTEM.VAL(Modules.Module, adr);
  872. w.String(m.name)
  873. ELSE
  874. w.Char(":"); WriteType(w, adr)
  875. END;
  876. w.Update;
  877. END
  878. ELSIF p.mode = Objects.AwaitingCond THEN
  879. w.Char(" "); WriteProc(w, SYSTEM.VAL(ADDRESS, p.condition));
  880. w.Address (p.condFP)
  881. END;
  882. w.Char(" "); w.Set(p.flags)
  883. END
  884. END WriteProcess;
  885. (* for interface compatibility *)
  886. PROCEDURE GetVariableAdr*(fp, pc: ADDRESS; CONST name: ARRAY OF CHAR): SIZE;
  887. BEGIN
  888. RETURN -1;
  889. END GetVariableAdr;
  890. PROCEDURE GetProcedureName*(pc: ADDRESS; VAR name: ARRAY OF CHAR; VAR startpc: ADDRESS);
  891. VAR m: Modules.Module; offset: LONGINT;
  892. BEGIN
  893. name := "";
  894. m := Modules.ThisModuleByAdr0(pc);
  895. IF m # NIL THEN
  896. offset := FindByAdr(m.refs,0,pc);
  897. IF offset >= 0 THEN
  898. GetFullName(m.refs, offset, name);
  899. IF GetChar(m.refs, offset) = sfProcedure THEN
  900. SkipSize(offset);
  901. SkipString(m.refs,offset);
  902. startpc := GetAddress(m.refs, offset);
  903. END;
  904. END;
  905. END;
  906. END GetProcedureName;
  907. TYPE
  908. Variable* = RECORD
  909. adr-: ADDRESS;
  910. type-, size-, n-, tdadr-: LONGINT
  911. END;
  912. PROCEDURE FindVar*(mod: Modules.Module; CONST name: ARRAY OF CHAR; VAR v: Variable): BOOLEAN;
  913. BEGIN
  914. END FindVar;
  915. PROCEDURE WriteVar*(w: Streams.Writer; v: Variable; VAR col: LONGINT);
  916. BEGIN
  917. END WriteVar;
  918. PROCEDURE ReportType*(w:Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT);
  919. VAR size: SIZE; adr: LONGINT; c: CHAR;
  920. BEGIN
  921. c := GetChar(refs, offset);
  922. CASE c OF
  923. sfTypeNone: w.String("no type");
  924. | sfTypePointerToRecord: w.String("POINTER TO RECORD");
  925. | sfTypePointerToArray: w.String("POINTER TO "); ReportType(w, refs, offset);
  926. | sfTypeOpenArray: w.String("ARRAY OF "); ReportType(w, refs, offset);
  927. | sfTypeStaticArray: w.String("ARRAY "); w.Int(GetSize(refs, offset),1 ); w.String(" OF "); ReportType(w, refs, offset);
  928. | sfTypeDynamicArray: w.String("DARRAY OF "); ReportType(w,refs, offset);
  929. | sfTypeMathOpenArray: w.String("ARRAY [*] OF "); ReportType(w, refs, offset);
  930. | sfTypeMathStaticArray: w.String("ARRAY ["); w.Int(GetSize(refs, offset),1); w.String("] OF "); ReportType(w, refs, offset);
  931. | sfTypeMathTensor: w.String("ARRAY [?] OF "); ReportType(w, refs, offset);
  932. | sfTypeRecord: w.String("RECORD "); w.Address(GetAddress(refs, offset));
  933. | sfTypeDelegate:
  934. w.String("PROCEDURE (");
  935. WHILE refs[offset] = sfVariable DO ReportVariable(w, refs, offset) END;
  936. w.String("):"); ReportType(w, refs, offset);
  937. | sfTypeBOOLEAN: w.String("BOOLEAN");
  938. | sfTypeCHAR: w.String("CHAR");
  939. | sfTypeCHAR8: w.String("CHAR8");
  940. | sfTypeCHAR16: w.String("CHAR16");
  941. | sfTypeCHAR32: w.String("CHAR32");
  942. | sfTypeSHORTINT: w.String("SHORTINT");
  943. | sfTypeINTEGER: w.String("INTEGER");
  944. | sfTypeLONGINT: w.String("LONGINT");
  945. | sfTypeHUGEINT: w.String("HUGEINT");
  946. | sfTypeWORD: w.String("WORD");
  947. | sfTypeLONGWORD: w.String("LONGWORD");
  948. | sfTypeSIGNED8: w.String("SIGNED8");
  949. | sfTypeSIGNED16: w.String("SIGNED16");
  950. | sfTypeSIGNED32: w.String("SIGNED32");
  951. | sfTypeSIGNED64: w.String("SIGNED64");
  952. | sfTypeUNSIGNED8: w.String("UNSIGNED8");
  953. | sfTypeUNSIGNED16: w.String("UNSIGNED16");
  954. | sfTypeUNSIGNED32: w.String("UNSIGNED32");
  955. | sfTypeUNSIGNED64: w.String("UNSIGNED64");
  956. | sfTypeREAL: w.String("REAL");
  957. | sfTypeLONGREAL: w.String("LONGREAL");
  958. | sfTypeCOMPLEX: w.String("COMPLEX");
  959. | sfTypeLONGCOMPLEX: w.String("LONGCOMPLEX");
  960. | sfTypeSET: w.String("SET");
  961. | sfTypeANY: w.String("ANY");
  962. | sfTypeOBJECT: w.String("OBJECT");
  963. | sfTypeBYTE: w.String("BYTE");
  964. | sfTypeRANGE: w.String("RANGE");
  965. | sfTypeADDRESS: w.String("ADDRESS");
  966. | sfTypeSIZE: w.String("SIZE");
  967. | sfTypePORT: w.String("PORT"); IF GetChar(refs,offset) = sfIN THEN w.String("IN") ELSE w.String("OUT") END;
  968. ELSE w.String("????? TYPE ?????");
  969. END;
  970. END ReportType;
  971. PROCEDURE ReportProcedure*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT);
  972. VAR name: Name; start, end: LONGINT;
  973. BEGIN
  974. w.Int(offset,1); w.String(":");
  975. w.String("PROCEDURE ");
  976. IF ~Expect(GetChar(refs, offset) = sfProcedure) THEN RETURN END;
  977. SkipSize(offset);
  978. GetString(refs, offset, name);
  979. w.String(name);
  980. start := GetAddress(refs, offset);
  981. end := GetAddress(refs, offset);
  982. w.String("[@"); w.Address(start); w.String(" - "); w.Address(end); w.String("]");
  983. w.String("("); w.Ln;
  984. WHILE refs[offset] = sfVariable DO
  985. ReportVariable(w, refs, offset);
  986. END;
  987. w.String(")");
  988. w.String(":");
  989. ReportType(w, refs, offset);
  990. w.Ln;
  991. ReportScope(w, refs, offset);
  992. END ReportProcedure;
  993. PROCEDURE ReportVariable*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT);
  994. VAR name: ARRAY 128 OF CHAR; adr: ADDRESS; size: SIZE;
  995. BEGIN
  996. w.Int(offset,1); w.String(":");
  997. w.String("VAR ");
  998. IF ~Expect(GetChar(refs, offset) = sfVariable) THEN RETURN END;
  999. SkipSize(offset);
  1000. GetString(refs, offset, name);
  1001. w.String(name);
  1002. IF GetChar(refs, offset) = sfRelative THEN
  1003. size := GetSize(refs, offset);
  1004. w.String("[@"); w.Int(size,1); w.String("]");
  1005. ELSE (* absolute *)
  1006. adr := GetAddress(refs, offset);
  1007. w.String("[@"); w.Address(adr); w.String("]");
  1008. END;
  1009. w.String(":");
  1010. ReportType(w, refs, offset);
  1011. w.Ln;
  1012. END ReportVariable;
  1013. PROCEDURE ReportTypeDeclaration*(w: Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT);
  1014. VAR name: ARRAY 128 OF CHAR; adr: LONGINT;
  1015. BEGIN
  1016. w.Int(offset,1); w.String(":");
  1017. w.String("TYPE ");
  1018. IF ~Expect(GetChar(refs, offset) = sfTypeDeclaration) THEN RETURN END;
  1019. SkipSize(offset);
  1020. GetString(refs, offset, name);
  1021. w.String(name);
  1022. adr := GetAddress(refs, offset);
  1023. w.String(" ");
  1024. w.Address(adr);
  1025. w.Ln;
  1026. IF refs[offset] = sfScopeBegin THEN ReportScope(w, refs, offset) END;
  1027. END ReportTypeDeclaration;
  1028. PROCEDURE ReportScope*(w:Streams.Writer; refs: Modules.Bytes; VAR offset: LONGINT);
  1029. BEGIN
  1030. IF ~Expect(GetChar(refs, offset) = sfScopeBegin) THEN RETURN END;
  1031. w.Int(offset,1); w.String(": Scope"); w.Ln;
  1032. WHILE (refs[offset] = sfVariable) DO (* Variable *)
  1033. ReportVariable(w, refs, offset);
  1034. END;
  1035. WHILE (refs[offset] = sfProcedure) DO (* Procedure *)
  1036. ReportProcedure(w, refs, offset);
  1037. END;
  1038. WHILE (refs[offset] = sfTypeDeclaration) DO (* TypeDeclaration *)
  1039. ReportTypeDeclaration(w, refs, offset);
  1040. END;
  1041. IF ~Expect(GetChar(refs, offset) = sfScopeEnd) THEN RETURN END;
  1042. w.String("END"); w.Ln;
  1043. END ReportScope;
  1044. PROCEDURE ReportModule*(w: Streams.Writer; refs: Modules.Bytes; offset: LONGINT);
  1045. VAR name: Name;
  1046. BEGIN
  1047. w.String("MODULE ");
  1048. IF ~Expect(GetChar(refs, offset) = sfModule) THEN RETURN END;
  1049. SkipSize(offset);
  1050. GetString(refs, offset, name);
  1051. w.String(name);
  1052. ReportScope(w, refs, offset);
  1053. END ReportModule;
  1054. PROCEDURE Report*(w:Streams.Writer; refs: Modules.Bytes; offset: LONGINT);
  1055. BEGIN
  1056. CASE refs[offset] OF
  1057. sfModule: ReportModule(w, refs, offset);
  1058. |sfVariable: ReportVariable(w, refs, offset);
  1059. |sfProcedure: ReportProcedure(w, refs, offset);
  1060. |sfTypeDeclaration: ReportTypeDeclaration(w, refs, offset);
  1061. ELSE (* wrong position in stream *)
  1062. END;
  1063. END Report;
  1064. BEGIN
  1065. modes := " rdy run awl awc awe rip"; (* 4 characters per mode from Objects.Ready to Objects.Terminated *)
  1066. END Reflection.
  1067. StaticLinker.Link --fileFormat=PE32 --fileName=A2.exe --extension=GofW --displacement=401000H Runtime Trace Kernel32 Machine Heaps Modules Objects Kernel KernelLog Streams Commands Files WinFS Clock Dates Reals Strings Diagnostics BitSets StringPool ObjectFile GenericLinker Reflection GenericLoader BootConsole ~