DataErrors.Mod 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. (* CAPO - Computational Analysis Platform for Oberon - by Alan Freed and Felix Friedrich. *)
  2. (* Version 1, Update 2 *)
  3. MODULE DataErrors; (** AUTHOR "adf, fof"; PURPOSE "For reporting runtime warnings & errors into file Error.Log"; *)
  4. (** Error.Log is an error log file that can be viewed with any ASCII editor, and is overwritten with each session.
  5. If no errors or warnings were logged, the file will be empty. File Error.Log is automatically opened/closed whenever
  6. module DataErrors.Mod is loaded-into/freed-from the system. The Error.Log file from the previous session is saved in
  7. file Error.Log.Bak.
  8. Logging of the first error message of a session produces an audible SOS beep to inform the user to check this file.
  9. Logging of the first warning message of a session produces just 3 beeps (instead of 9) in the SOS tone sequence.
  10. Errors are for catostropic events, e.g., division by zero.
  11. Warnings are for non-optimal events, e.g., a series did not converge. *)
  12. IMPORT SYSTEM, Machine, Kernel, Modules, Files, Beep, NbrInt, NbrRat, NbrRe, NbrCplx;
  13. VAR
  14. beepedError, beepedWarning: BOOLEAN; F: Files.File; W: Files.Writer;
  15. (***! BEGIN part from Traps, todo: simplify and adjust to needs *)
  16. TYPE
  17. Variable = RECORD
  18. adr, type, size, n, tdadr: LONGINT
  19. END; (* variable descriptor *)
  20. CONST
  21. MaxString = 64; MaxArray = 8; MaxCols = 70; Sep = " "; SepLen = 2;
  22. (* Write the specified procedure name and returns parameters for use with NextVar and Variables. *)
  23. (* Find a procedure in the reference block. Return index of name, or -1 if not found. *)
  24. PROCEDURE FindProc( refs: Modules.Bytes; modpc: LONGINT ): LONGINT;
  25. VAR i, m, t, proc: LONGINT; ch: CHAR;
  26. BEGIN
  27. proc := -1; i := 0; m := LEN( refs^ ); ch := refs[i]; INC( i );
  28. WHILE (i < m) & ((ch = 0F8X) OR (ch = 0F9X)) DO (* proc *)
  29. GetNum( refs, i, t ); (* pofs *)
  30. IF t > modpc THEN (* previous procedure was the one *)
  31. ch := 0X (* stop search *)
  32. ELSE (* ~found *)
  33. IF ch = 0F9X THEN
  34. GetNum( refs, i, t ); (* nofPars *)
  35. INC( i, 3 ) (* RetType, procLev, slFlag *)
  36. END;
  37. proc := i; (* remember this position, just before the name *)
  38. REPEAT ch := refs[i]; INC( i ) UNTIL ch = 0X; (* pname *)
  39. IF i < m THEN
  40. ch := refs[i]; INC( i ); (* 1X | 3X | 0F8X | 0F9X *)
  41. WHILE (i < m) & (ch >= 1X) & (ch <= 3X) DO (* var *)
  42. ch := refs[i]; INC( i ); (* type *)
  43. IF (ch >= 81X) OR (ch = 16X) OR (ch = 1DX) THEN
  44. GetNum( refs, i, t ) (* dim/tdadr *)
  45. END;
  46. GetNum( refs, i, t ); (* vofs *)
  47. REPEAT ch := refs[i]; INC( i ) UNTIL ch = 0X; (* vname *)
  48. IF i < m THEN ch := refs[i]; INC( i ) END (* 1X | 3X | 0F8X | 0F9X *)
  49. END
  50. END
  51. END
  52. END;
  53. IF (proc = -1) & (i # 0) THEN proc := i END; (* first procedure *)
  54. RETURN proc
  55. END FindProc;
  56. PROCEDURE WriteProc0( mod: Modules.Module; pc, fp: LONGINT; VAR refs: Modules.Bytes; VAR refpos, base: LONGINT );
  57. VAR ch: CHAR;
  58. BEGIN
  59. refpos := -1;
  60. IF mod = NIL THEN
  61. IF pc = 0 THEN W.String( "NIL" ) ELSE W.String( "Unknown PC=" ); W.Hex( pc, 8 ); W.Char( "H" ) END;
  62. IF fp # -1 THEN W.String( " FP=" ); W.Hex( fp, 8 ); W.Char( "H" ) END
  63. ELSE
  64. W.String( mod.name ); DEC( pc, LONGINT(ADDRESSOF( mod.code[0] )) ); refs := mod.refs;
  65. IF (refs # NIL ) & (LEN( refs ) # 0) THEN
  66. refpos := FindProc( refs, pc );
  67. IF refpos # -1 THEN
  68. W.Char( "." ); ch := refs[refpos]; INC( refpos );
  69. IF ch = "$" THEN base := LONGINT(mod.sb) ELSE base := fp END; (* for variables *)
  70. WHILE ch # 0X DO W.Char( ch ); ch := refs[refpos]; INC( refpos ) END
  71. END
  72. END;
  73. W.String( " pc=" ); W.Int( pc, 1 )
  74. END
  75. END WriteProc0;
  76. (* Find procedure name and write it. *)
  77. PROCEDURE WriteProc( pc: LONGINT );
  78. VAR refs: Modules.Bytes; refpos, base: LONGINT;
  79. BEGIN
  80. WriteProc0( Modules.ThisModuleByAdr( pc ), pc, -1, refs, refpos, base )
  81. END WriteProc;
  82. (* Write a simple variable value. *)
  83. PROCEDURE WriteSimpleVar( adr, type, tdadr: LONGINT; VAR col: LONGINT );
  84. VAR ch: CHAR; sval: SHORTINT; ival: INTEGER; lval: LONGINT;
  85. BEGIN
  86. CASE type OF
  87. 1, 3: (* BYTE, CHAR *)
  88. SYSTEM.GET( adr, ch );
  89. IF (ch > " ") & (ch <= "~") THEN W.Char( ch ); INC( col ) ELSE W.Hex( ORD( ch ), -2 ); W.Char( "X" ); INC( col, 3 ) END
  90. | 2: (* BOOLEAN *)
  91. SYSTEM.GET( adr, ch );
  92. IF ch = 0X THEN W.String( "FALSE" )
  93. ELSIF ch = 1X THEN W.String( "TRUE" )
  94. ELSE W.Int( ORD( ch ), 1 )
  95. END;
  96. INC( col, 5 )
  97. | 4: (* SHORTINT *)
  98. SYSTEM.GET( adr, sval );
  99. W.Int( sval, 1 ); INC( col, 4 )
  100. (*Streams.WriteString(w, " ("); Streams.WriteHex(w, sval, -3); Streams.WriteString(w, "H)")*)
  101. | 5: (* INTEGER *)
  102. SYSTEM.GET( adr, ival );
  103. W.Int( ival, 1 ); INC( col, 5 )
  104. (*Streams.WriteString(w, " ("); Streams.WriteHex(w, ival, 8); Streams.WriteString(w, "H)")*)
  105. | 6: (* LONGINT *)
  106. SYSTEM.GET( adr, lval );
  107. W.Int( lval, 1 ); INC( col, 5 );
  108. IF ABS( lval ) >= 10000H THEN W.String( " (" ); W.Hex( lval, 8 ); W.String( "H)" ); INC( col, 12 ) END
  109. | 7, 8, 13, 16, 29: (* REAL, LONGREAL, POINTER *)
  110. INC( col, 9 );
  111. IF (type = 8) OR (type = 16) THEN SYSTEM.GET( adr + 4, lval ); W.Hex( lval, 8 ); INC( col, 8 ) END;
  112. SYSTEM.GET( adr, lval ); W.Hex( lval, 8 ); W.Char( "H" )
  113. | 9: (* SET *)
  114. SYSTEM.GET( adr, lval );
  115. W.Set( SYSTEM.VAL( SET, lval ) ); INC( col, 8 ) (* col is guess *)
  116. | 22: (* RECORD *)
  117. W.String( "Rec." ); W.Hex( tdadr, 8 ); W.Char( "H" ); INC( col, 13 )
  118. | 14: (* PROC *)
  119. SYSTEM.GET( adr, lval ); WriteProc( lval ); INC( col, 25 )
  120. END
  121. END WriteSimpleVar;
  122. (* Write a variable value. The v parameter is a variable descriptor obtained with NextVar. Parameter col is incremented with
  123. the (approximate) number of characters written. *)
  124. PROCEDURE WriteVar( v: Variable; VAR col: LONGINT );
  125. VAR ch: CHAR;
  126. BEGIN
  127. IF v.type = 15 THEN
  128. W.Char( 22X );
  129. LOOP
  130. IF v.n = 0 THEN EXIT END;
  131. SYSTEM.GET( v.adr, ch ); INC( v.adr );
  132. IF (ch < " ") OR (ch > "~") THEN EXIT END;
  133. W.Char( ch ); INC( col ); DEC( v.n )
  134. END;
  135. W.Char( 22X ); INC( col, 2 );
  136. IF ch # 0X THEN W.Char( "!" ) END
  137. ELSE
  138. WHILE v.n > 0 DO
  139. WriteSimpleVar( v.adr, v.type, v.tdadr, col ); DEC( v.n ); INC( v.adr, v.size );
  140. IF v.n > 0 THEN W.String( ", " ); INC( col, 2 ) END
  141. END
  142. END
  143. END WriteVar;
  144. (* Get a compressed refblk number. *)
  145. PROCEDURE GetNum( refs: Modules.Bytes; VAR i, num: LONGINT );
  146. VAR n, s: LONGINT; x: CHAR;
  147. BEGIN
  148. s := 0; n := 0; x := refs[i]; INC( i );
  149. WHILE ORD( x ) >= 128 DO INC( n, ASH( ORD( x ) - 128, s ) ); INC( s, 7 ); x := refs[i]; INC( i ) END;
  150. num := n + ASH( ORD( x ) MOD 64 - ORD( x ) DIV 64 * 64, s )
  151. END GetNum;
  152. (* Step to the next variable in the refs block. The name parameter returns empty if no more variables are found. The attributes
  153. are returned in v. Parameter refpos is modified. *)
  154. PROCEDURE NextVar( refs: Modules.Bytes; VAR refpos: LONGINT; base: LONGINT; VAR name: ARRAY OF CHAR; VAR v: Variable );
  155. VAR x: Variable; j: LONGINT; ch, mode: CHAR;
  156. BEGIN
  157. name[0] := 0X; (* empty name signals end or error *)
  158. IF refpos < LEN( refs^ ) - 1 THEN
  159. mode := refs[refpos]; INC( refpos );
  160. IF (mode >= 1X) & (mode <= 3X) THEN (* var *)
  161. x.type := ORD( refs[refpos] ); INC( refpos );
  162. IF x.type > 80H THEN
  163. IF x.type = 83H THEN x.type := 15 ELSE DEC( x.type, 80H ) END;
  164. GetNum( refs, refpos, x.n )
  165. ELSIF (x.type = 16H) OR (x.type = 1DH) THEN GetNum( refs, refpos, x.tdadr ); x.n := 1
  166. ELSE
  167. IF x.type = 15 THEN x.n := MaxString (* best guess *) ELSE x.n := 1 END
  168. END;
  169. (* get address *)
  170. GetNum( refs, refpos, x.adr );
  171. INC( x.adr, base ); (* convert to absolute address *)
  172. IF x.n = 0 THEN (* open array (only on stack, not global variable) *)
  173. SYSTEM.GET( x.adr + 4, x.n ) (* real LEN from stack *)
  174. END;
  175. IF mode # 1X THEN SYSTEM.GET( x.adr, x.adr ) END; (* indirect *)
  176. (* get size *)
  177. CASE x.type OF
  178. 1..4, 15:
  179. x.size := 1
  180. | 5: x.size := 2
  181. | 6..7, 9, 13, 14, 29:
  182. x.size := 4
  183. | 8, 16:
  184. x.size := 8
  185. | 22:
  186. x.size := 0;
  187. ASSERT ( x.n <= 1 )
  188. ELSE x.size := -1
  189. END;
  190. IF x.size >= 0 THEN (* ok, get name *)
  191. ch := refs[refpos]; INC( refpos ); j := 0;
  192. WHILE ch # 0X DO
  193. IF j < LEN( name ) - 1 THEN name[j] := ch; INC( j ) END; (* truncate long names *)
  194. ch := refs[refpos]; INC( refpos )
  195. END;
  196. name[j] := 0X; v := x (* non-empty name *)
  197. END
  198. END
  199. END
  200. END NextVar;
  201. (* Find the specified global variable and return its descriptor. Returns TRUE iff the variable is found. *)
  202. PROCEDURE Variables( refs: Modules.Bytes; refpos, base: LONGINT );
  203. VAR v: Variable; j, col: LONGINT;
  204. name: ARRAY 64 OF CHAR;
  205. etc: BOOLEAN;
  206. BEGIN
  207. LOOP
  208. NextVar( refs, refpos, base, name, v );
  209. IF name[0] = 0X THEN EXIT END;
  210. (* write name *)
  211. IF (col # 0) & (v.n > 1) & (v.type # 15) THEN (* Ln before array (except string) *)
  212. W.Ln(); col := 0
  213. END;
  214. W.String( Sep ); W.String( name ); W.Char( "=" ); j := 0;
  215. WHILE name[j] # 0X DO INC( j ) END;
  216. INC( col, SepLen + 1 + j );
  217. (* write variable *)
  218. IF (v.adr >= -4) & (v.adr < 4096) THEN (* must be NIL VAR parameter *)
  219. W.String( "NIL (" ); W.Hex( v.adr, 8 ); W.Char( ")" ); INC( col, 14 )
  220. ELSE
  221. etc := FALSE;
  222. IF v.type = 15 THEN
  223. IF v.n > MaxString THEN etc := TRUE; v.n := MaxString END
  224. ELSE
  225. IF v.n > MaxArray THEN etc := TRUE; v.n := MaxArray END
  226. END;
  227. WriteVar( v, col ); (* write value *)
  228. IF etc THEN W.String( "..." ); INC( col, 3 ) END
  229. END;
  230. IF col > MaxCols THEN W.Ln(); col := 0 END
  231. END;
  232. IF col # 0 THEN W.Ln() END
  233. END Variables;
  234. PROCEDURE InitVar( mod: Modules.Module; VAR refs: Modules.Bytes; VAR refpos, base: LONGINT );
  235. VAR ch: CHAR;
  236. BEGIN
  237. refpos := -1;
  238. IF mod # NIL THEN
  239. refs := mod.refs; base := LONGINT(mod.sb);
  240. IF (refs # NIL ) & (LEN( refs ) # 0) THEN
  241. refpos := FindProc( refs, 0 );
  242. IF refpos # -1 THEN
  243. ch := refs[refpos]; INC( refpos );
  244. WHILE ch # 0X DO ch := refs[refpos]; INC( refpos ) END
  245. END
  246. END
  247. END
  248. END InitVar;
  249. PROCEDURE ModuleState( mod: Modules.Module );
  250. VAR refpos, base: LONGINT; refs: Modules.Bytes;
  251. BEGIN
  252. InitVar( mod, refs, refpos, base );
  253. IF refpos # -1 THEN W.String( "State " ); W.String( mod.name ); W.Char( ":" ); W.Ln(); Variables( refs, refpos, base ) END
  254. END ModuleState;
  255. (* Display call trackback. *)
  256. PROCEDURE StackTraceBack( eip, ebp: LONGINT; long: BOOLEAN );
  257. VAR count, refpos, base: LONGINT; m: Modules.Module; refs: Modules.Bytes;
  258. CONST MaxFrames = 16;
  259. BEGIN
  260. count := 0; (* frame count *)
  261. REPEAT
  262. m := Modules.ThisModuleByAdr( eip );
  263. IF (m # NIL ) OR (count = 0) THEN
  264. WriteProc0( m, eip, ebp, refs, refpos, base ); W.Ln();
  265. IF long & ((count > 0)) THEN (* show variables *)
  266. IF refpos # -1 THEN Variables( refs, refpos, base ) END;
  267. IF (m # NIL ) & (base # m.sb) & (count = 0) THEN ModuleState( m ) END
  268. END;
  269. SYSTEM.GET( ebp + 4, eip ); (* return addr from stack *)
  270. SYSTEM.GET( ebp, ebp ); (* follow dynamic link *)
  271. INC( count )
  272. ELSE ebp := 0
  273. END
  274. UNTIL (ebp = 0) OR (count = MaxFrames);
  275. IF ebp # 0 THEN W.String( "..." ) END
  276. END StackTraceBack;
  277. (***! END part from Traps *)
  278. (* From antsPortability *)
  279. PROCEDURE ErrorCaller( VAR m: Modules.Module; VAR pc, ebp, eip: NbrInt.Integer );
  280. VAR i, reg: NbrInt.Integer; timer: Kernel.Timer;
  281. BEGIN
  282. reg := LONGINT(SYSTEM.GetFramePointer ());
  283. SYSTEM.GET( reg, ebp ); (* stack frame of caller *)
  284. SYSTEM.GET( ebp + 4, eip ); (* return address from caller *)
  285. m := Modules.ThisModuleByAdr( eip );
  286. IF m # NIL THEN pc := LONGINT(eip - ADDRESSOF( m.code[0] )) ELSE pc := MAX( LONGINT ) END;
  287. IF ~beepedError THEN
  288. beepedError := TRUE; NEW( timer );
  289. FOR i := 1 TO 3 DO Beep.Beep( 125 ); timer.Sleep( 100 ); Beep.Beep( 0 ); timer.Sleep( 100 ) END;
  290. FOR i := 1 TO 3 DO Beep.Beep( 100 ); timer.Sleep( 350 ); Beep.Beep( 0 ); timer.Sleep( 150 ) END;
  291. FOR i := 1 TO 3 DO Beep.Beep( 125 ); timer.Sleep( 100 ); Beep.Beep( 0 ); timer.Sleep( 100 ) END
  292. END
  293. END ErrorCaller;
  294. PROCEDURE WarningCaller( VAR m: Modules.Module; VAR pc, ebp, eip: NbrInt.Integer );
  295. VAR reg: NbrInt.Integer; timer: Kernel.Timer;
  296. BEGIN
  297. reg := LONGINT(SYSTEM.GetFramePointer ());
  298. SYSTEM.GET( reg, ebp ); (* stack frame of caller *)
  299. SYSTEM.GET( ebp + 4, eip ); (* return address from caller *)
  300. m := Modules.ThisModuleByAdr( eip );
  301. IF m # NIL THEN pc := LONGINT(eip - ADDRESSOF( m.code[0] )) ELSE pc := MAX( LONGINT ) END;
  302. IF ~beepedWarning THEN
  303. beepedWarning := TRUE; NEW( timer ); Beep.Beep( 125 ); timer.Sleep( 100 ); Beep.Beep( 0 );
  304. timer.Sleep( 100 ); Beep.Beep( 100 ); timer.Sleep( 100 ); Beep.Beep( 0 ); timer.Sleep( 100 );
  305. Beep.Beep( 125 ); timer.Sleep( 100 ); Beep.Beep( 0 ); timer.Sleep( 100 )
  306. END
  307. END WarningCaller;
  308. PROCEDURE IdentifyProcedure( VAR m: Modules.Module; pc: NbrInt.Integer; VAR module, type, proc: ARRAY OF CHAR );
  309. VAR i: NbrInt.Integer; ch: CHAR; refs: Modules.Bytes; refpos: LONGINT;
  310. BEGIN
  311. module[0] := 0X; type[0] := 0X; proc[0] := 0X;
  312. IF m = NIL THEN
  313. IF pc = 0 THEN COPY( "NIL", proc ) ELSE COPY( "unknown pointer", proc ) END
  314. ELSE
  315. COPY( m.name, module ); refs := m.refs; refpos := FindProc( refs, pc );
  316. IF refpos # -1 THEN
  317. ch := refs[refpos]; NbrInt.Inc( refpos ); i := 0;
  318. WHILE (ch # 0X) DO
  319. proc[i] := ch; ch := refs[refpos]; NbrInt.Inc( refpos ); NbrInt.Inc( i );
  320. IF ch = "." THEN ch := refs[refpos]; NbrInt.Inc( refpos ); proc[i] := 0X; COPY( proc, type ); i := 0 END
  321. END;
  322. proc[i] := 0X
  323. ELSE COPY( "unknown", proc )
  324. END
  325. END
  326. END IdentifyProcedure;
  327. PROCEDURE Location( module, type, proc: ARRAY OF CHAR );
  328. BEGIN
  329. IF module[0] # 0X THEN W.String( " module: " ); W.String( module ); W.Ln END;
  330. IF type[0] # 0X THEN
  331. W.String( " type: " ); W.String( type ); W.Ln;
  332. IF proc[0] # 0X THEN W.String( " method: " ); W.String( proc ); W.Ln END
  333. ELSE
  334. IF proc[0] # 0X THEN W.String( " procedure: " ); W.String( proc ); W.Ln END
  335. END
  336. END Location;
  337. PROCEDURE DetailedErrorReport( VAR m: Modules.Module; pc: LONGINT; eip, ebp: LONGINT );
  338. VAR refs: Modules.Bytes; refpos: LONGINT; adr: LONGINT;
  339. BEGIN
  340. IF m # NIL THEN
  341. refs := m.refs; refpos := FindProc( refs, pc );
  342. GetNum( refs, refpos, adr );
  343. INC( adr, LONGINT(m.sb)); (* convert to absolute address *)
  344. W.Hex(adr,8);W.Ln;
  345. W.String( "Detailed Error Report" ); W.Ln;
  346. IF m# NIL THEN W.String( "Module State:" ); W.Ln; ModuleState( m ); END;
  347. W.String( "Stack trace back" ); W.Ln;
  348. IF (eip # 0) & (ebp # 0) THEN StackTraceBack( eip, ebp, TRUE ); END;
  349. END;
  350. END DetailedErrorReport;
  351. (** Log an error message to file Error.Log. *)
  352. PROCEDURE Error*( message: ARRAY OF CHAR );
  353. VAR m: Modules.Module; pc: NbrInt.Integer;
  354. module, type, proc: ARRAY 64 OF CHAR;
  355. ebp, eip: LONGINT;
  356. BEGIN {EXCLUSIVE}
  357. IF W # NIL THEN
  358. ErrorCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "An error of:" ); W.Ln; W.String( " " );
  359. W.String( message ); W.Ln; W.String( "occurred in:" ); W.Ln; Location( module, type, proc ); W.Ln;
  360. DetailedErrorReport(m,pc,eip,ebp);
  361. W.Update
  362. END
  363. END Error;
  364. (** Log an error message to file Error.Log when an error arises from a passed parameter whose value was int. *)
  365. PROCEDURE IntError*( int: NbrInt.Integer; message: ARRAY OF CHAR );
  366. VAR m: Modules.Module; pc: NbrInt.Integer;
  367. module, type, proc, string: ARRAY 64 OF CHAR;
  368. ebp, eip: LONGINT;
  369. BEGIN {EXCLUSIVE}
  370. IF W # NIL THEN
  371. ErrorCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "An ERROR occurred in:" ); W.Ln;
  372. Location( module, type, proc ); W.String( "The argument passed that caused this error was: " ); W.Ln; W.String( " " ); NbrInt.IntToString( int, string );
  373. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln;
  374. DetailedErrorReport(m,pc,eip,ebp);
  375. W.Update
  376. END
  377. END IntError;
  378. (** Log an error message to file Error.Log when an error arises from a passed parameter whose value was rat. *)
  379. PROCEDURE RatError*( rat: NbrRat.Rational; message: ARRAY OF CHAR );
  380. VAR m: Modules.Module; pc: NbrInt.Integer;
  381. module, type, proc, string: ARRAY 64 OF CHAR;
  382. ebp, eip: LONGINT;
  383. BEGIN {EXCLUSIVE}
  384. IF W # NIL THEN
  385. ErrorCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "An ERROR occurred in:" ); W.Ln;
  386. Location( module, type, proc ); W.String( "The argument passed that caused this error was: " ); W.Ln; W.String( " " ); NbrRat.RatToString( rat, string );
  387. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln;
  388. DetailedErrorReport(m,pc,eip,ebp);
  389. W.Update
  390. END
  391. END RatError;
  392. (** Log an error message to file Error.Log when an error arises from a passed parameter whose value was re. *)
  393. PROCEDURE ReError*( re: NbrRe.Real; message: ARRAY OF CHAR );
  394. VAR m: Modules.Module; pc: NbrInt.Integer;
  395. module, type, proc, string: ARRAY 64 OF CHAR;
  396. ebp, eip: LONGINT;
  397. BEGIN {EXCLUSIVE}
  398. IF W # NIL THEN
  399. ErrorCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "An ERROR occurred in:" ); W.Ln;
  400. Location( module, type, proc ); W.String( "The argument passed that caused this error was: " ); W.Ln; W.String( " " ); NbrRe.ReToString( re, 15, string );
  401. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln;
  402. DetailedErrorReport(m,pc,eip,ebp);
  403. W.Update
  404. END
  405. END ReError;
  406. (** Log an error message to file Error.Log when an error arises from a passed parameter whose value was cplx. *)
  407. PROCEDURE CplxError*( cplx: NbrCplx.Complex; message: ARRAY OF CHAR );
  408. VAR m: Modules.Module; pc: NbrInt.Integer;
  409. module, type, proc, string: ARRAY 64 OF CHAR;
  410. ebp, eip: LONGINT;
  411. BEGIN {EXCLUSIVE}
  412. IF W # NIL THEN
  413. ErrorCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "An ERROR occurred in:" ); W.Ln;
  414. Location( module, type, proc ); W.String( "The argument passed that caused this error was: " ); W.Ln; W.String( " " ); NbrCplx.CplxToPolarString( cplx, 15, string );
  415. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln;
  416. DetailedErrorReport(m,pc,eip,ebp); W.Update
  417. END
  418. END CplxError;
  419. (** Log a warning message to file Error.Log. *)
  420. PROCEDURE Warning*( message: ARRAY OF CHAR );
  421. VAR m: Modules.Module; pc: NbrInt.Integer;
  422. module, type, proc: ARRAY 64 OF CHAR;
  423. ebp, eip: LONGINT;
  424. BEGIN {EXCLUSIVE}
  425. IF W # NIL THEN
  426. WarningCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "A WARNING of:" ); W.Ln; W.String( " " );
  427. W.String( message ); W.Ln; W.String( "occurred in:" ); W.Ln; Location( module, type, proc ); W.Ln; W.Update
  428. END
  429. END Warning;
  430. (** Log a warning message to file Error.Log when a warning arises from a passed parameter whose value was int. *)
  431. PROCEDURE IntWarning*( int: NbrInt.Integer; message: ARRAY OF CHAR );
  432. VAR m: Modules.Module; pc: NbrInt.Integer;
  433. module, type, proc, string: ARRAY 64 OF CHAR;
  434. ebp, eip: LONGINT;
  435. BEGIN {EXCLUSIVE}
  436. IF W # NIL THEN
  437. WarningCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "A WARNING occurred in:" ); W.Ln;
  438. Location( module, type, proc ); W.String( "The argument passed that caused this warning was: " ); W.Ln; W.String( " " ); NbrInt.IntToString( int, string );
  439. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln; W.Update
  440. END
  441. END IntWarning;
  442. (** Log a warning message to file Error.Log when a warning arises from a passed parameter whose value was rat. *)
  443. PROCEDURE RatWarning*( rat: NbrRat.Rational; message: ARRAY OF CHAR );
  444. VAR m: Modules.Module; pc: NbrInt.Integer;
  445. module, type, proc, string: ARRAY 64 OF CHAR;
  446. ebp, eip: LONGINT;
  447. BEGIN {EXCLUSIVE}
  448. IF W # NIL THEN
  449. WarningCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "A WARNING occurred in:" ); W.Ln;
  450. Location( module, type, proc ); W.String( "The argument passed that caused this warning was: " ); W.Ln; W.String( " " ); NbrRat.RatToString( rat, string );
  451. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln; W.Update
  452. END
  453. END RatWarning;
  454. (** Log a warning message to file Error.Log when a warning arises from a passed parameter whose value was re. *)
  455. PROCEDURE ReWarning*( re: NbrRe.Real; message: ARRAY OF CHAR );
  456. VAR m: Modules.Module; pc: NbrInt.Integer;
  457. module, type, proc, string: ARRAY 64 OF CHAR;
  458. ebp, eip: LONGINT;
  459. BEGIN {EXCLUSIVE}
  460. IF W # NIL THEN
  461. WarningCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "A WARNING occurred in:" ); W.Ln;
  462. Location( module, type, proc ); W.String( "The argument passed that caused this warning was: " ); W.Ln; W.String( " " ); NbrRe.ReToString( re, 15, string );
  463. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln; W.Update
  464. END
  465. END ReWarning;
  466. (** Log a warning message to file Error.Log when a warning arises from a passed parameter whose value was cplx. *)
  467. PROCEDURE CplxWarning*( cplx: NbrCplx.Complex; message: ARRAY OF CHAR );
  468. VAR m: Modules.Module; pc: NbrInt.Integer;
  469. module, type, proc, string: ARRAY 64 OF CHAR;
  470. ebp, eip: LONGINT;
  471. BEGIN {EXCLUSIVE}
  472. IF W # NIL THEN
  473. WarningCaller( m, pc, ebp, eip ); IdentifyProcedure( m, pc, module, type, proc ); W.String( "A WARNING occurred in:" ); W.Ln;
  474. Location( module, type, proc ); W.String( "The argument passed that caused this warning was: " ); W.Ln; W.String( " " ); NbrCplx.CplxToPolarString( cplx, 15, string );
  475. W.String( string ); W.Ln; W.String( "resulting in the following error message:" ); W.Ln; W.String( " " ); W.String( message ); W.Ln; W.Ln; W.Update
  476. END
  477. END CplxWarning;
  478. (** Opens the file Error.Log, saving the prior log file to Error.Log.Bak.
  479. Error.Log is automatically opened whenever this module is loaded into memory,
  480. and it only needs to be reopened manually if you had previously closed it manually. *)
  481. PROCEDURE Open*;
  482. VAR ignor: WORD; backup, current: Files.FileName;
  483. BEGIN
  484. beepedError := FALSE; beepedWarning := FALSE; COPY( "Error.Log", current ); COPY( "Error.Log.Bak", backup ); Files.Delete( backup, ignor );
  485. Files.Rename( current, backup, ignor ); F := Files.New( current ); Files.OpenWriter( W, F, 0 )
  486. END Open;
  487. (** Closes the file Error.Log.
  488. Error.Log is automatically closed whenever this module is garbage collected.
  489. Executing Close forces the file to close immediately. *)
  490. PROCEDURE Close*;
  491. BEGIN
  492. IF F # NIL THEN Files.Register( F ); W := NIL; F := NIL END
  493. END Close;
  494. BEGIN
  495. Open; Modules.InstallTermHandler( Close )
  496. END DataErrors.
  497. DataErrors.Close ~
  498. EditTools.OpenAscii Error.Log ~
  499. EditTools.OpenAscii Error.Log.Bak ~