]>
Commit | Line | Data |
---|---|---|
1eee94d3 GM |
1 | (* M2DebugStack.mod display parameter stack. |
2 | ||
a945c346 | 3 | Copyright (C) 2011-2024 Free Software Foundation, Inc. |
1eee94d3 GM |
4 | Contributed by Gaius Mulley <gaius.mulley@southwales.ac.uk>. |
5 | ||
6 | This file is part of GNU Modula-2. | |
7 | ||
8 | GNU Modula-2 is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 3, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU Modula-2 is distributed in the hope that it will be useful, but | |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 | General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU Modula-2; see the file COPYING3. If not see | |
20 | <http://www.gnu.org/licenses/>. *) | |
21 | ||
22 | IMPLEMENTATION MODULE M2DebugStack ; | |
23 | ||
24 | FROM DynamicStrings IMPORT InitString, KillString, Dup, Index, Slice, char, | |
25 | ConCat, ConCatChar, InitStringCharStar, Length, Mark ; | |
26 | ||
27 | FROM SymbolTable IMPORT IsConstLit, IsConstSet, IsConstructor, IsConst, | |
28 | IsArray, IsVar, IsEnumeration, IsFieldEnumeration, | |
29 | IsUnbounded, IsProcType, IsProcedure, IsPointer, IsParameter, | |
30 | IsParameterVar, IsType, IsRecord, IsRecordField, IsVarient, | |
31 | IsModule, IsDefImp, IsSet, IsSubrange, GetSymName, NulSym ; | |
32 | ||
33 | FROM StringConvert IMPORT CardinalToString ; | |
34 | FROM NameKey IMPORT Name, KeyToCharStar ; | |
35 | FROM FIO IMPORT File, StdOut ; | |
36 | FROM SFIO IMPORT WriteS ; | |
37 | FROM M2Error IMPORT InternalError ; | |
38 | FROM M2Printf IMPORT printf0, printf1, printf2, printf3, printf4 ; | |
39 | ||
40 | CONST | |
41 | Debugging = FALSE ; | |
42 | ||
43 | VAR | |
44 | OperandTok, | |
45 | OperandT, | |
46 | OperandF, | |
47 | OperandA, | |
48 | OperandD, | |
49 | OperandRW : ProcedureWord ; | |
50 | OperandAnno: ProcedureString ; | |
51 | ||
52 | ||
53 | (* | |
54 | x - checks to see that a=b. | |
55 | *) | |
56 | ||
57 | PROCEDURE x (a, b: String) : String ; | |
58 | BEGIN | |
59 | IF a#b | |
60 | THEN | |
61 | InternalError ('different string returned') | |
62 | END ; | |
63 | RETURN( a ) | |
64 | END x ; | |
65 | ||
66 | ||
67 | (* | |
68 | IsWhite - returns TRUE if, ch, is a space. | |
69 | *) | |
70 | ||
71 | PROCEDURE IsWhite (ch: CHAR) : BOOLEAN ; | |
72 | BEGIN | |
73 | RETURN( ch=' ' ) | |
74 | END IsWhite ; | |
75 | ||
76 | ||
77 | (* | |
78 | ConCatWord - joins sentances, a, b, together. | |
79 | *) | |
80 | ||
81 | PROCEDURE ConCatWord (a, b: String) : String ; | |
82 | BEGIN | |
83 | IF (Length(a)=1) AND (char(a, 0)='a') | |
84 | THEN | |
85 | a := x(a, ConCatChar(a, 'n')) | |
86 | ELSIF (Length(a)>1) AND (char(a, -1)='a') AND IsWhite(char(a, -2)) | |
87 | THEN | |
88 | a := x(a, ConCatChar(a, 'n')) | |
89 | END ; | |
90 | IF (Length(a)>0) AND (NOT IsWhite(char(a, -1))) | |
91 | THEN | |
92 | a := x(a, ConCatChar(a, ' ')) | |
93 | END ; | |
94 | RETURN( x(a, ConCat(a, b)) ) | |
95 | END ConCatWord ; | |
96 | ||
97 | ||
98 | (* | |
99 | symDesc - | |
100 | *) | |
101 | ||
102 | PROCEDURE symDesc (sym: CARDINAL; o: String) : String ; | |
103 | BEGIN | |
104 | IF sym = NulSym | |
105 | THEN | |
106 | RETURN( ConCatWord(o, Mark(InitString('NulSym'))) ) | |
107 | ELSIF IsConstLit(sym) | |
108 | THEN | |
109 | RETURN( ConCatWord(o, Mark(InitString('constant literal'))) ) | |
110 | ELSIF IsConstSet(sym) | |
111 | THEN | |
112 | RETURN( ConCatWord(o, Mark(InitString('constant set'))) ) | |
113 | ELSIF IsConstructor(sym) | |
114 | THEN | |
115 | RETURN( ConCatWord(o, Mark(InitString('constructor'))) ) | |
116 | ELSIF IsConst(sym) | |
117 | THEN | |
118 | RETURN( ConCatWord(o, Mark(InitString('constant'))) ) | |
119 | ELSIF IsArray(sym) | |
120 | THEN | |
121 | RETURN( ConCatWord(o, Mark(InitString('array'))) ) | |
122 | ELSIF IsVar(sym) | |
123 | THEN | |
124 | RETURN( ConCatWord(o, Mark(InitString('variable'))) ) | |
125 | ELSIF IsEnumeration(sym) | |
126 | THEN | |
127 | RETURN( ConCatWord(o, Mark(InitString('enumeration type'))) ) | |
128 | ELSIF IsFieldEnumeration(sym) | |
129 | THEN | |
130 | RETURN( ConCatWord(o, Mark(InitString('enumeration field'))) ) | |
131 | ELSIF IsUnbounded(sym) | |
132 | THEN | |
133 | RETURN( ConCatWord(o, Mark(InitString('unbounded parameter'))) ) | |
134 | ELSIF IsProcType(sym) | |
135 | THEN | |
136 | RETURN( ConCatWord(o, Mark(InitString('procedure type'))) ) | |
137 | ELSIF IsProcedure(sym) | |
138 | THEN | |
139 | RETURN( ConCatWord(o, Mark(InitString('procedure'))) ) | |
140 | ELSIF IsPointer(sym) | |
141 | THEN | |
142 | RETURN( ConCatWord(o, Mark(InitString('pointer'))) ) | |
143 | ELSIF IsParameter(sym) | |
144 | THEN | |
145 | IF IsParameterVar(sym) | |
146 | THEN | |
147 | RETURN( ConCatWord(o, Mark(InitString('var parameter'))) ) | |
148 | ELSE | |
149 | RETURN( ConCatWord(o, Mark(InitString('parameter'))) ) | |
150 | END | |
151 | ELSIF IsType(sym) | |
152 | THEN | |
153 | RETURN( ConCatWord(o, Mark(InitString('type'))) ) | |
154 | ELSIF IsRecord(sym) | |
155 | THEN | |
156 | RETURN( ConCatWord(o, Mark(InitString('record'))) ) | |
157 | ELSIF IsRecordField(sym) | |
158 | THEN | |
159 | RETURN( ConCatWord(o, Mark(InitString('record field'))) ) | |
160 | ELSIF IsVarient(sym) | |
161 | THEN | |
162 | RETURN( ConCatWord(o, Mark(InitString('varient record'))) ) | |
163 | ELSIF IsModule(sym) | |
164 | THEN | |
165 | RETURN( ConCatWord(o, Mark(InitString('module'))) ) | |
166 | ELSIF IsDefImp(sym) | |
167 | THEN | |
168 | RETURN( ConCatWord(o, Mark(InitString('definition or implementation module'))) ) | |
169 | ELSIF IsSet(sym) | |
170 | THEN | |
171 | RETURN( ConCatWord(o, Mark(InitString('set'))) ) | |
172 | ELSIF IsSubrange(sym) | |
173 | THEN | |
174 | RETURN( ConCatWord(o, Mark(InitString('subrange'))) ) | |
175 | ELSE | |
176 | RETURN( o ) | |
177 | END | |
178 | END symDesc ; | |
179 | ||
180 | ||
181 | (* | |
182 | Output - output string, s, to Stdout. It also disposes of the string, s. | |
183 | *) | |
184 | ||
185 | PROCEDURE Output (s: String) ; | |
186 | BEGIN | |
187 | s := WriteS(StdOut, s) ; | |
188 | s := KillString(s) | |
189 | END Output ; | |
190 | ||
191 | ||
192 | (* | |
193 | GetComment - | |
194 | *) | |
195 | ||
196 | PROCEDURE GetComment (s: String) : INTEGER ; | |
197 | VAR | |
198 | c: INTEGER ; | |
199 | BEGIN | |
200 | c := Index(s, '|', 0) ; | |
201 | WHILE c>=0 DO | |
202 | INC(c) ; | |
203 | IF c>=VAL(INTEGER, Length(s)) | |
204 | THEN | |
205 | RETURN -1 | |
206 | ELSIF char(s, c)='|' | |
207 | THEN | |
208 | RETURN c+1 | |
209 | END ; | |
210 | c := Index(s, '|', c) | |
211 | END ; | |
212 | RETURN -1 | |
213 | END GetComment ; | |
214 | ||
215 | ||
216 | (* | |
217 | doName - concatenate namekey, o, to, p. | |
218 | *) | |
219 | ||
220 | PROCEDURE doName (p: String; o: WORD) : String ; | |
221 | BEGIN | |
222 | RETURN ConCat(p, InitStringCharStar(KeyToCharStar(o))) ; | |
223 | END doName ; | |
224 | ||
225 | ||
226 | (* | |
227 | doSymName - concatenate symbol, o, name to, p. | |
228 | *) | |
229 | ||
230 | PROCEDURE doSymName (p: String; o: WORD) : String ; | |
231 | BEGIN | |
232 | RETURN ConCat(p, InitStringCharStar(KeyToCharStar(GetSymName(o)))) ; | |
233 | END doSymName ; | |
234 | ||
235 | ||
236 | (* | |
237 | doNumber - convert, o, to a cardinal and increment the length, l, | |
238 | by the number of characters required to represent, o. | |
239 | *) | |
240 | ||
241 | PROCEDURE doNumber (p: String; o: WORD) : String ; | |
242 | BEGIN | |
243 | RETURN ConCat(p, CardinalToString(VAL(CARDINAL, o), 0, ' ', 10, TRUE)) | |
244 | END doNumber ; | |
245 | ||
246 | ||
247 | (* | |
248 | doSymbol - handles a symbol indicated by, o. | |
249 | *) | |
250 | ||
251 | PROCEDURE doSymbol (p: String; o: WORD) : String ; | |
252 | BEGIN | |
253 | RETURN symDesc(o, p) | |
254 | END doSymbol ; | |
255 | ||
256 | ||
257 | (* | |
258 | doOperand - | |
259 | *) | |
260 | ||
261 | PROCEDURE doOperand (p, s: String; VAR i: INTEGER; e: INTEGER; o: WORD) : String ; | |
262 | BEGIN | |
263 | INC(i) ; | |
264 | IF i<e | |
265 | THEN | |
266 | CASE char(s, i) OF | |
267 | ||
268 | 's': (* symbol number *) | |
269 | INC(i) ; | |
270 | RETURN doSymbol(p, o) | | |
271 | 'd': (* decimal number *) | |
272 | INC(i) ; | |
273 | RETURN doNumber(p, o) | | |
274 | 'a': (* symbol name key *) | |
275 | INC(i) ; | |
276 | RETURN doSymName(p, o) | | |
277 | 'n': (* ascii name key *) | |
278 | INC(i) ; | |
279 | RETURN doName(p, o) | |
280 | ||
281 | ELSE | |
282 | InternalError ("incorrect format specifier expecting one of 's', 'd' or 'a'") | |
283 | END | |
284 | END ; | |
285 | RETURN p | |
286 | END doOperand ; | |
287 | ||
288 | ||
289 | (* | |
290 | doPercent - | |
291 | *) | |
292 | ||
293 | PROCEDURE doPercent (o, s: String; | |
294 | VAR i: INTEGER; e: INTEGER; n: CARDINAL) : String ; | |
295 | BEGIN | |
296 | INC(i) ; | |
297 | IF i<e | |
298 | THEN | |
299 | CASE char(s, i) OF | |
300 | ||
301 | '1': RETURN doOperand(o, s, i, e, OperandT(n)) | | |
302 | '2': RETURN doOperand(o, s, i, e, OperandF(n)) | | |
303 | '3': RETURN doOperand(o, s, i, e, OperandTok(n)) | |
304 | ||
305 | ELSE | |
306 | InternalError ('unrecognised format specifier - expecting 1, 2 or 3 after the %') | |
307 | END | |
308 | END ; | |
309 | InternalError ('end of field found before format specifier - expecting 1, 2 or 3 after the %') | |
310 | END doPercent ; | |
311 | ||
312 | ||
313 | (* | |
314 | doNameLength - increment, l, by the ascii length of string determined by, o. | |
315 | *) | |
316 | ||
317 | PROCEDURE doNameLength (VAR l: CARDINAL; o: WORD) ; | |
318 | VAR | |
319 | s: String ; | |
320 | BEGIN | |
321 | s := InitStringCharStar(KeyToCharStar(o)) ; | |
322 | INC(l, Length(s)) ; | |
323 | s := KillString(s) | |
324 | END doNameLength ; | |
325 | ||
326 | ||
327 | (* | |
328 | doSymNameLength - increment, l, by the ascii length of symbol, o. | |
329 | *) | |
330 | ||
331 | PROCEDURE doSymNameLength (VAR l: CARDINAL; o: WORD) ; | |
332 | VAR | |
333 | s: String ; | |
334 | BEGIN | |
335 | s := InitStringCharStar(KeyToCharStar(GetSymName(o))) ; | |
336 | INC(l, Length(s)) ; | |
337 | s := KillString(s) | |
338 | END doSymNameLength ; | |
339 | ||
340 | ||
341 | (* | |
342 | doNumberLength - convert, o, to a cardinal and increment the length, l, | |
343 | by the number of characters required to represent, o. | |
344 | *) | |
345 | ||
346 | PROCEDURE doNumberLength (VAR l: CARDINAL; o: WORD) ; | |
347 | VAR | |
348 | s: String ; | |
349 | BEGIN | |
350 | s := CardinalToString(VAL(CARDINAL, o), 0, ' ', 10, TRUE) ; | |
351 | INC(l, Length(s)) ; | |
352 | s := KillString(s) | |
353 | END doNumberLength ; | |
354 | ||
355 | ||
356 | (* | |
357 | doSymbolLength - handles a symbol indicated by, o. | |
358 | *) | |
359 | ||
360 | PROCEDURE doSymbolLength (VAR l: CARDINAL; o: WORD) ; | |
361 | VAR | |
362 | s: String ; | |
363 | BEGIN | |
364 | s := symDesc(o, InitString('')) ; | |
365 | INC(l, Length(s)) ; | |
366 | s := KillString(s) | |
367 | END doSymbolLength ; | |
368 | ||
369 | ||
370 | (* | |
371 | doOperandLength - | |
372 | *) | |
373 | ||
374 | PROCEDURE doOperandLength (s: String; VAR i: INTEGER; e: INTEGER; VAR l: CARDINAL; o: WORD) ; | |
375 | BEGIN | |
376 | INC(i) ; | |
377 | IF i<e | |
378 | THEN | |
379 | CASE char(s, i) OF | |
380 | ||
381 | 's': (* symbol number *) | |
382 | INC(i) ; | |
383 | doSymbolLength(l, o) | | |
384 | 'd': (* decimal number *) | |
385 | INC(i) ; | |
386 | doNumberLength(l, o) | | |
387 | 'a': (* ascii name key *) | |
388 | INC(i) ; | |
389 | doSymNameLength(l, o) | | |
390 | 'n': (* ascii name key *) | |
391 | INC(i) ; | |
392 | doNameLength(l, o) | |
393 | ||
394 | ELSE | |
395 | InternalError ("incorrect format specifier expecting one of 's', 'd' or 'a'") | |
396 | END | |
397 | END | |
398 | END doOperandLength ; | |
399 | ||
400 | ||
401 | (* | |
402 | doPercentLength - | |
403 | *) | |
404 | ||
405 | PROCEDURE doPercentLength (s: String; VAR i: INTEGER; e: INTEGER; | |
406 | VAR l: CARDINAL; n: CARDINAL) ; | |
407 | BEGIN | |
408 | INC(i) ; | |
409 | IF i<e | |
410 | THEN | |
411 | CASE char(s, i) OF | |
412 | ||
413 | '1': doOperandLength(s, i, e, l, OperandT(n)) | | |
414 | '2': doOperandLength(s, i, e, l, OperandF(n)) | | |
415 | '3': doOperandLength(s, i, e, l, OperandTok(n)) | | |
416 | ||
417 | ELSE | |
418 | InternalError ('unrecognised format specifier - expecting 1, 2 or 3 after the %') | |
419 | END | |
420 | END | |
421 | END doPercentLength ; | |
422 | ||
423 | ||
424 | (* | |
425 | doFieldLength - compute the string length given in annotation | |
426 | at position, n, on the stack between characters | |
427 | b and e. | |
428 | ||
429 | The string description between: b..e can contain any | |
430 | of these patterns: | |
431 | ||
432 | %a ascii name key. | |
433 | %s symbol number. | |
434 | %d decimal cardinal number. | |
435 | | indicates the next field. | |
436 | *) | |
437 | ||
438 | PROCEDURE doFieldLength (b, e: INTEGER; n: CARDINAL) : CARDINAL ; | |
439 | VAR | |
440 | l: CARDINAL ; | |
441 | i: INTEGER ; | |
442 | s: String ; | |
443 | BEGIN | |
444 | IF b=-1 | |
445 | THEN | |
446 | RETURN( 0 ) | |
447 | END ; | |
448 | s := OperandAnno(n) ; | |
449 | IF e=-1 | |
450 | THEN | |
451 | e := Length(s) | |
452 | END ; | |
453 | l := 0 ; | |
454 | i := b ; | |
455 | WHILE i<e DO | |
456 | CASE char(s, i) OF | |
457 | ||
458 | '|': RETURN l | | |
459 | '%': doPercentLength(s, i, e, l, n) ; | |
460 | ||
461 | ELSE | |
462 | INC(l) | |
463 | END ; | |
464 | INC(i) | |
465 | END ; | |
466 | RETURN l | |
467 | END doFieldLength ; | |
468 | ||
469 | ||
470 | (* | |
471 | stop - | |
472 | *) | |
473 | ||
474 | PROCEDURE stop ; | |
475 | BEGIN | |
476 | END stop ; | |
477 | ||
478 | ||
479 | (* | |
480 | doMaxCard - returns the maximum of two CARDINALs. | |
481 | *) | |
482 | ||
483 | PROCEDURE doMaxCard (a, b: CARDINAL) : CARDINAL ; | |
484 | BEGIN | |
485 | IF (a>100) OR (b>100) | |
486 | THEN | |
487 | stop | |
488 | END ; | |
489 | IF a>b | |
490 | THEN | |
491 | RETURN a | |
492 | ELSE | |
493 | RETURN b | |
494 | END | |
495 | END doMaxCard ; | |
496 | ||
497 | ||
498 | (* | |
499 | GetAnnotationFieldLength - | |
500 | *) | |
501 | ||
502 | PROCEDURE GetAnnotationFieldLength (n: CARDINAL; f: CARDINAL) : CARDINAL ; | |
503 | VAR | |
504 | c, e: INTEGER ; | |
505 | BEGIN | |
506 | c := GetComment(OperandAnno(n)) ; | |
507 | IF c>0 | |
508 | THEN | |
509 | IF Debugging | |
510 | THEN | |
511 | printf0('full anno is: ') ; Output(Dup(OperandAnno(n))) ; printf0('\n') ; | |
512 | printf0('comment field is: ') ; Output(Slice(OperandAnno(n), c, 0)) ; printf0('\n') | |
513 | END ; | |
514 | e := Index(OperandAnno(n), '|', c) ; | |
515 | IF f=0 | |
516 | THEN | |
517 | RETURN doFieldLength(c, e, n) | |
518 | ELSE | |
519 | IF e>=0 | |
520 | THEN | |
521 | INC(e) | |
522 | END ; | |
523 | RETURN doFieldLength(e, -1, n) | |
524 | END | |
525 | ELSE | |
526 | RETURN 0 | |
527 | END | |
528 | END GetAnnotationFieldLength ; | |
529 | ||
530 | ||
531 | (* | |
532 | GetAnnotationLength - | |
533 | *) | |
534 | ||
535 | PROCEDURE GetAnnotationLength (n: CARDINAL; f: CARDINAL) : CARDINAL ; | |
536 | VAR | |
537 | l: CARDINAL ; | |
538 | BEGIN | |
539 | IF OperandAnno(n)=NIL | |
540 | THEN | |
541 | l := 0 ; | |
542 | IF f=0 | |
543 | THEN | |
544 | doNumberLength(l, OperandT(n)) | |
545 | ELSE | |
546 | doNumberLength(l, OperandF(n)) | |
547 | END ; | |
548 | RETURN l | |
549 | ELSE | |
550 | RETURN GetAnnotationFieldLength(n, f) | |
551 | END | |
552 | END GetAnnotationLength ; | |
553 | ||
554 | ||
555 | (* | |
556 | GetFieldLength - returns the number of characters used in field, f, | |
557 | at position, n, on the stack. | |
558 | *) | |
559 | ||
560 | PROCEDURE GetFieldLength (n: CARDINAL; f: CARDINAL) : CARDINAL ; | |
561 | VAR | |
562 | c, b, e: INTEGER ; | |
563 | BEGIN | |
564 | c := GetComment(OperandAnno(n)) ; | |
565 | IF c>1 | |
566 | THEN | |
567 | e := c-2 | |
568 | ELSE | |
569 | e := Length(OperandAnno(n)) | |
570 | END ; | |
571 | IF f=0 | |
572 | THEN | |
573 | b := 0 | |
574 | ELSE | |
575 | b := Index(OperandAnno(n), '|', 0) ; | |
576 | IF b=-1 | |
577 | THEN | |
578 | RETURN 0 | |
579 | ELSE | |
580 | INC(b) | |
581 | END | |
582 | END ; | |
583 | RETURN doFieldLength(b, e, n) | |
584 | END GetFieldLength ; | |
585 | ||
586 | ||
587 | (* | |
588 | GetMaxFieldAnno - returns the maximum number of characters required | |
589 | by either the annotation or field, f, at position, n, | |
590 | on the stack. | |
591 | *) | |
592 | ||
593 | PROCEDURE GetMaxFieldAnno (n: CARDINAL; f: CARDINAL) : CARDINAL ; | |
594 | BEGIN | |
595 | RETURN doMaxCard(GetAnnotationLength(n, f), GetFieldLength(n, f)) | |
596 | END GetMaxFieldAnno ; | |
597 | ||
598 | ||
599 | (* | |
600 | GetStackFieldLengths - assigns, tn, and, fn, with the | |
601 | maximum field width values. | |
602 | *) | |
603 | ||
604 | PROCEDURE GetStackFieldLengths (VAR tn, fn, tk: CARDINAL; amount: CARDINAL) ; | |
605 | VAR | |
606 | i: CARDINAL ; | |
607 | BEGIN | |
608 | i := 1 ; | |
609 | tn := 0 ; | |
610 | fn := 0 ; | |
611 | tk := 0 ; | |
612 | WHILE i<=amount DO | |
613 | tn := doMaxCard(tn, GetMaxFieldAnno(i, 0)) ; | |
614 | fn := doMaxCard(fn, GetMaxFieldAnno(i, 1)) ; | |
615 | tk := doMaxCard(tk, GetMaxFieldAnno(i, 2)) ; | |
616 | INC(i) | |
617 | END | |
618 | END GetStackFieldLengths ; | |
619 | ||
620 | ||
621 | (* | |
622 | DisplayRow - | |
623 | *) | |
624 | ||
625 | PROCEDURE DisplayRow (tn, fn, tk: CARDINAL; initOrFinal: BOOLEAN) ; | |
626 | VAR | |
627 | i: CARDINAL ; | |
628 | BEGIN | |
629 | printf0('+-') ; | |
630 | FOR i := 1 TO tn DO | |
631 | printf0('-') | |
632 | END ; | |
633 | IF (fn=0) AND (tk=0) | |
634 | THEN | |
635 | IF initOrFinal | |
636 | THEN | |
637 | printf0('-+-') | |
638 | ELSE | |
639 | printf0('-|-') | |
640 | END | |
641 | ELSE | |
642 | IF initOrFinal | |
643 | THEN | |
644 | printf0('-+-') | |
645 | ELSE | |
646 | printf0('-|-') | |
647 | END ; | |
648 | IF fn#0 | |
649 | THEN | |
650 | FOR i := 1 TO fn DO | |
651 | printf0('-') | |
652 | END | |
653 | END ; | |
654 | IF initOrFinal | |
655 | THEN | |
656 | printf0('-+-') | |
657 | ELSE | |
658 | printf0('-|-') | |
659 | END ; | |
660 | IF tk#0 | |
661 | THEN | |
662 | FOR i := 1 TO tk DO | |
663 | printf0('-') | |
664 | END ; | |
665 | printf0('-+\n') | |
666 | END | |
667 | END | |
668 | END DisplayRow ; | |
669 | ||
670 | ||
671 | (* | |
672 | SkipToField - | |
673 | *) | |
674 | ||
675 | PROCEDURE SkipToField (s: String; n: CARDINAL) : INTEGER ; | |
676 | VAR | |
677 | i, h: INTEGER ; | |
678 | BEGIN | |
679 | i := 0 ; | |
680 | h := Length(s) ; | |
681 | WHILE (n>0) AND (i<h) DO | |
682 | IF Index(s, '|', i)>0 | |
683 | THEN | |
684 | DEC(n) ; | |
685 | IF (i<h) AND (char(s, i+1)='|') | |
686 | THEN | |
687 | (* comment seen, no field available *) | |
688 | RETURN -1 | |
689 | END ; | |
690 | i := Index(s, '|', i) | |
691 | ELSE | |
692 | RETURN -1 | |
693 | END ; | |
694 | INC(i) | |
695 | END ; | |
696 | IF i=h | |
697 | THEN | |
698 | i := -1 | |
699 | END ; | |
700 | RETURN i | |
701 | END SkipToField ; | |
702 | ||
703 | ||
704 | (* | |
705 | Pad - padds out string, s, to paddedLength characters. | |
706 | *) | |
707 | ||
708 | PROCEDURE Pad (o: String; paddedLength: CARDINAL) : String ; | |
709 | VAR | |
710 | i: CARDINAL ; | |
711 | BEGIN | |
712 | i := Length(o) ; | |
713 | IF i<paddedLength | |
714 | THEN | |
715 | REPEAT | |
716 | o := ConCatChar(o, ' ') ; | |
717 | INC(i) | |
718 | UNTIL i=paddedLength | |
719 | END ; | |
720 | RETURN o | |
721 | END Pad ; | |
722 | ||
723 | ||
724 | (* | |
725 | doField - compute the string length given in annotation | |
726 | at position, n, on the stack between characters | |
727 | b and e. | |
728 | ||
729 | The string description between: b..e can contain any | |
730 | of these patterns: | |
731 | ||
732 | %a ascii name key. | |
733 | %s symbol number. | |
734 | %d decimal cardinal number. | |
735 | | indicates the next field. | |
736 | *) | |
737 | ||
738 | PROCEDURE doField (s: String; n: CARDINAL; f: CARDINAL; l: CARDINAL) : String ; | |
739 | VAR | |
740 | h, i, j: INTEGER ; | |
741 | o : String ; | |
742 | BEGIN | |
743 | h := Length(s) ; | |
744 | i := SkipToField(s, f) ; | |
745 | o := InitString('') ; | |
746 | IF i>=0 | |
747 | THEN | |
748 | j := SkipToField(s, f+1) ; | |
749 | IF j=-1 | |
750 | THEN | |
751 | j := h | |
752 | END ; | |
753 | WHILE i<h DO | |
754 | CASE char(s, i) OF | |
755 | ||
756 | '|': i := h | | |
757 | '%': o := doPercent(o, s, i, h, n) | |
758 | ||
759 | ELSE | |
760 | o := ConCatChar(o, char(s, i)) ; | |
761 | INC(i) | |
762 | END | |
763 | END | |
764 | END ; | |
765 | o := Pad(o, l) ; | |
766 | RETURN o | |
767 | END doField ; | |
768 | ||
769 | ||
770 | (* | |
771 | doAnnotation - | |
772 | *) | |
773 | ||
774 | PROCEDURE doAnnotation (s: String; n: CARDINAL; | |
775 | field: CARDINAL; width: CARDINAL) : String ; | |
776 | VAR | |
777 | c : INTEGER ; | |
778 | cf, o: String ; | |
779 | BEGIN | |
780 | c := GetComment(s) ; | |
781 | IF c>=0 | |
782 | THEN | |
783 | cf := Slice(s, c, 0) ; | |
784 | o := doField(cf, n, field, width) ; | |
785 | cf := KillString(cf) ; | |
786 | RETURN o | |
787 | ELSE | |
788 | RETURN InitString('') | |
789 | END | |
790 | END doAnnotation ; | |
791 | ||
792 | ||
793 | (* | |
794 | DisplayFields - | |
795 | *) | |
796 | ||
797 | PROCEDURE DisplayFields (n: CARDINAL; tn, fn, tk: CARDINAL) ; | |
798 | VAR | |
799 | s : String ; | |
800 | t, f, k: CARDINAL ; | |
801 | BEGIN | |
802 | s := OperandAnno(n) ; | |
803 | IF s=NIL | |
804 | THEN | |
805 | t := OperandT(n) ; | |
806 | f := OperandF(n) ; | |
807 | k := OperandTok(n) ; | |
808 | printf0('| ') ; | |
809 | Output(Pad(CardinalToString(VAL(CARDINAL, t), 0, ' ', 10, TRUE), tn)) ; | |
810 | printf0(' | ') ; | |
811 | Output(Pad(CardinalToString(VAL(CARDINAL, f), 0, ' ', 10, TRUE), fn)) ; | |
812 | printf0(' | ') ; | |
813 | Output(Pad(CardinalToString(VAL(CARDINAL, k), 0, ' ', 10, TRUE), tk)) ; | |
814 | printf0(' |\n') | |
815 | ELSE | |
816 | IF tn>0 | |
817 | THEN | |
818 | printf0('| ') ; | |
819 | Output(doField(s, n, 0, tn)) | |
820 | END ; | |
821 | IF fn>0 | |
822 | THEN | |
823 | printf0(' | ') ; | |
824 | Output(doField(s, n, 1, fn)) | |
825 | END ; | |
826 | IF tk>0 | |
827 | THEN | |
828 | printf0(' | ') ; | |
829 | Output(doField(s, n, 2, tk)) | |
830 | END ; | |
831 | printf0(' |\n') ; | |
832 | IF tn>0 | |
833 | THEN | |
834 | printf0('| ') ; | |
835 | Output(doAnnotation(s, n, 0, tn)) | |
836 | END ; | |
837 | IF fn>0 | |
838 | THEN | |
839 | printf0(' | ') ; | |
840 | Output(doAnnotation(s, n, 1, fn)) | |
841 | END ; | |
842 | IF tk>0 | |
843 | THEN | |
844 | printf0(' | ') ; | |
845 | Output(doAnnotation(s, n, 2, tk)) | |
846 | END ; | |
847 | printf0(' |\n') | |
848 | END | |
849 | END DisplayFields ; | |
850 | ||
851 | ||
852 | (* | |
853 | DebugStack - displays the stack. | |
854 | *) | |
855 | ||
856 | PROCEDURE DebugStack (amount: CARDINAL; | |
857 | opt, opf, opa, opd, oprw, optk: ProcedureWord; | |
858 | opanno: ProcedureString) ; | |
859 | VAR | |
860 | i : CARDINAL ; | |
861 | tn, fn, tk: CARDINAL ; | |
862 | BEGIN | |
863 | OperandT := opt ; | |
864 | OperandF := opf ; | |
865 | OperandA := opa ; | |
866 | OperandD := opd ; | |
867 | OperandRW := oprw ; | |
868 | OperandAnno := opanno ; | |
869 | OperandTok := optk ; | |
870 | GetStackFieldLengths(tn, fn, tk, amount) ; | |
871 | i := 1 ; | |
872 | WHILE i<=amount DO | |
873 | IF i=1 | |
874 | THEN | |
875 | DisplayRow(tn, fn, tk, TRUE) | |
876 | END ; | |
877 | DisplayFields(i, tn, fn, tk) ; | |
878 | DisplayRow(tn, fn, tk, i=amount) ; | |
879 | INC(i) | |
880 | END | |
881 | END DebugStack ; | |
882 | ||
883 | ||
884 | END M2DebugStack. |