Generic.Reflection.Mod 33 KB

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