Generic.Reflection.Mod 36 KB

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