Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | \ ========== Copyright Header Begin ========================================== |
2 | \ | |
3 | \ Hypervisor Software File: cmn-msg-format.fth | |
4 | \ | |
5 | \ Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. | |
6 | \ | |
7 | \ - Do no alter or remove copyright notices | |
8 | \ | |
9 | \ - Redistribution and use of this software in source and binary forms, with | |
10 | \ or without modification, are permitted provided that the following | |
11 | \ conditions are met: | |
12 | \ | |
13 | \ - Redistribution of source code must retain the above copyright notice, | |
14 | \ this list of conditions and the following disclaimer. | |
15 | \ | |
16 | \ - Redistribution in binary form must reproduce the above copyright notice, | |
17 | \ this list of conditions and the following disclaimer in the | |
18 | \ documentation and/or other materials provided with the distribution. | |
19 | \ | |
20 | \ Neither the name of Sun Microsystems, Inc. or the names of contributors | |
21 | \ may be used to endorse or promote products derived from this software | |
22 | \ without specific prior written permission. | |
23 | \ | |
24 | \ This software is provided "AS IS," without a warranty of any kind. | |
25 | \ ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, | |
26 | \ INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A | |
27 | \ PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN | |
28 | \ MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR | |
29 | \ ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR | |
30 | \ DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN | |
31 | \ OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR | |
32 | \ FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE | |
33 | \ DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, | |
34 | \ ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF | |
35 | \ SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. | |
36 | \ | |
37 | \ You acknowledge that this software is not designed, licensed or | |
38 | \ intended for use in the design, construction, operation or maintenance of | |
39 | \ any nuclear facility. | |
40 | \ | |
41 | \ ========== Copyright Header End ============================================ | |
42 | id: @(#)cmn-msg-format.fth 1.16 06/06/15 17:20:05 | |
43 | purpose: Common messaging framework | |
44 | copyright: Copyright 2006 Sun Microsystems, Inc. All Rights Reserved. | |
45 | copyright: Use is subject to license terms. | |
46 | ||
47 | headerless | |
48 | ||
49 | defer platform-fatal-hook ' noop is platform-fatal-hook | |
50 | defer platform-error-hook ' noop is platform-error-hook | |
51 | defer platform-warning-hook ' noop is platform-warning-hook | |
52 | defer platform-note-hook ' noop is platform-note-hook | |
53 | defer platform-cmn-end-hook ' noop is platform-cmn-end-hook | |
54 | defer platform-cmn-end-hook2 ' noop is platform-cmn-end-hook2 | |
55 | ||
56 | \ System FATAL and ERROR flags | |
57 | \ If you set the fatal state the machine will suppress the boot command | |
58 | \ and will not attempt to auto-boot, it will also print an ugly message. | |
59 | \ If you set the error-state? an auto-boot? may not happen. | |
60 | ||
61 | 0 value system-fatal-state? | |
62 | 0 value system-error-state? | |
63 | ||
64 | headers vocabulary cmn-messaging | |
65 | also cmn-messaging definitions | |
66 | headerless | |
67 | ||
68 | \ Message categories are as follows: | |
69 | \ we are converting these numbers into the matching bitpatterns that the | |
70 | \ verbosity framework uses so we can use simple AND logic to determine if | |
71 | \ the message is printed. | |
72 | ||
73 | VRBS-MAX VRBS-DEBUG or constant cmn-type | |
74 | h# 40 cmn-type or constant cmn-msg | |
75 | VRBS-MED cmn-msg or constant cmn-note | |
76 | VRBS-MIN cmn-note or constant cmn-warning | |
77 | h# 80 cmn-warning or constant cmn-error | |
78 | VRBS-NONE cmn-error or constant cmn-fatal | |
79 | ||
80 | \ Message Frame Data Structure Format | |
81 | \ Each message frame contains the following fields: | |
82 | \ | |
83 | \ 8 bytes - address of the parent frame (0 if no parent) | |
84 | \ 8 bytes - address of the first child frame (0 if no children) | |
85 | \ 8 bytes - address of the next peer frame (0 if no more peers) | |
86 | \ 8 bytes - address of the message buffer (allocated dynamically) | |
87 | \ 8 bytes - phandle of the device pathname associated with message | |
88 | \ 1 byte - category of common message | |
89 | \ 1 byte - message completion flag (true/false) | |
90 | ||
91 | struct | |
92 | /n field >cmn-parent \ address of the parent frame | |
93 | /n field >cmn-child \ address of the first child frame | |
94 | /n field >cmn-peer \ address of the peer frame | |
95 | /n field >cmn-message \ address of the message buffer | |
96 | /n field >cmn-phandle \ phandle of the device pathname | |
97 | /c field >cmn-category \ category of common message | |
98 | /c field >cmn-completion \ message completion flag | |
99 | constant /cmn-frame | |
100 | ||
101 | \ Message Data Structure Format | |
102 | \ Each message contains the following fields: | |
103 | \ | |
104 | \ 2 bytes - max length of the current string | |
105 | \ 2 bytes - length of the current text sting | |
106 | \ N bytes - current text sting itself | |
107 | ||
108 | struct | |
109 | /w field >cmn-message>maxlen \ max length of the long string | |
110 | /w field >cmn-message>lstr \ start of long counted text string | |
111 | constant /cmn-message | |
112 | ||
113 | \ Size of initial message buffer and size of each increment | |
114 | d# 255 constant max-message-len | |
115 | ||
116 | variable current-frame$ 0 current-frame$ ! \ pointer to the current message frame | |
117 | ||
118 | \ Long packed strings format: first 2 bytes - count, then string itself. | |
119 | \ long-count takes long packed string address from the stack and returns | |
120 | \ the string address and the length of the string on the stack. | |
121 | ||
122 | : long-count ( lpstr -- str,len) dup wa1+ swap w@ ; | |
123 | ||
124 | \ Concatenates a string to the end of packed long string | |
125 | : $long-cat ( adr len lpstr -- ) | |
126 | >r r@ long-count ca+ ( adr len end-adr ) ( r: lpstr ) | |
127 | swap dup >r ( adr end-adr len ) ( r: lpstr len ) | |
128 | cmove r> r> ( len lpstr ) | |
129 | dup w@ rot ca+ swap w! | |
130 | ; | |
131 | ||
132 | \ Concatenates a given number of spaces to end of packed long string | |
133 | : $long-spaces ( n lpstr -- ) | |
134 | >r r@ long-count ca+ ( n end-adr ) ( r: lpstr ) | |
135 | over bl fill r> ( n lpstr ) | |
136 | dup w@ rot ca+ swap w! | |
137 | ; | |
138 | ||
139 | \ Returns phandle for active instance or 0 if no instance | |
140 | : ?phandle ( -- phandle|0) my-self dup if ihandle>phandle then ; | |
141 | ||
142 | \ Add a new child to the current frame. | |
143 | \ If this is the first child, it becomes the frame's >cmn-child. | |
144 | \ Otherwise it becomes the last entry in the >cmn-peer chain starting from >cmn-child. | |
145 | ||
146 | : add-new-child ( new-frame-addr -- ) | |
147 | current-frame$ @ >cmn-child | |
148 | begin | |
149 | dup @ | |
150 | while | |
151 | @ >cmn-peer | |
152 | repeat | |
153 | ! | |
154 | ; | |
155 | ||
156 | : current>message ( -- addr) current-frame$ @ >cmn-message ; | |
157 | : current>string ( -- addr) current>message @ >cmn-message>lstr ; | |
158 | : current>maxlen ( -- addr) current>message @ >cmn-message>maxlen ; | |
159 | ||
160 | \ Ensures that current>string is long enough to $long-cat n bytes | |
161 | ||
162 | : expand-current>string ( n -- ) | |
163 | ||
164 | \ Calculate length of new string | |
165 | current>string w@ + ( len ) | |
166 | ||
167 | \ Retrieve the max length of the current message buffer and compare | |
168 | dup current>maxlen w@ > if \ Need allocate bigger message buffer | |
169 | ||
170 | \ Calculate the size of the new message frame | |
171 | max-message-len / 1+ max-message-len * ( new-len ) | |
172 | ||
173 | \ Allocate new message buffer | |
174 | dup /cmn-message + alloc-mem ( new-len new-buffer-addr ) | |
175 | ||
176 | \ Erase new message buffer header | |
177 | dup /cmn-message erase ( new-len new-buffer-addr ) | |
178 | ||
179 | \ Move old message to the new bigger buffer | |
180 | dup >cmn-message>lstr current>string long-count rot $long-cat ( new-len new-buffer-addr ) | |
181 | ||
182 | \ Update new buffer maxlen field | |
183 | tuck >cmn-message>maxlen w! ( new-buffer-addr ) | |
184 | ||
185 | \ Release old message buffer | |
186 | current>message @ ( new-buffer-addr old-buffer-addr ) | |
187 | current>maxlen w@ ( new-buffer-addr old-buffer-addr old-len ) | |
188 | /cmn-message + free-mem ( new-buffer-addr ) | |
189 | ||
190 | \ Update message frame >cmn-message pointer | |
191 | current>message ! ( ) | |
192 | ||
193 | else ( len ) | |
194 | drop ( ) | |
195 | then ( ) | |
196 | ; | |
197 | ||
198 | \ Like "type", but buffered into current message frame | |
199 | : buffered-type ( adr,len -- ) | |
200 | dup expand-current>string ( adr,len ) | |
201 | current>string $long-cat ( ) | |
202 | ; | |
203 | ||
204 | \ Like "spaces", but buffered into current message frame | |
205 | : buffered-spaces ( n -- ) | |
206 | dup expand-current>string ( adr,len ) | |
207 | current>string $long-spaces | |
208 | ; | |
209 | ||
210 | \ There is one [ifdef] in this file: [ifdef] cmn-reentrant? | |
211 | \ this is a place holder so that the entire cmn-append code becomes | |
212 | \ re-entrant. | |
213 | \ | |
214 | \ FWARC/2004/311 format encoder extension | |
215 | \ | |
216 | \ This works by parsing the string from left->right, recursing until all the | |
217 | \ tokens are encoded, and then pushing the stack items into the fmt-data | |
218 | \ structures on the return (unnesting) path. | |
219 | \ | |
220 | \ Once the sequence is complete the stack is logically empty and the entire | |
221 | \ sequence is replayed left-to-right. | |
222 | \ | |
223 | \ Each fmt-data structure will contain the acf of the number->string encoder | |
224 | \ appropriate for the encoding and the actual stack data. | |
225 | \ After each node is processed the node is released. | |
226 | \ | |
227 | \ Everything ends up being funnelled through the (fmt-s) routine, so buffering | |
228 | \ the constructed message should be trivial - though it will be assembled in | |
229 | \ pieces. | |
230 | \ | |
231 | \ How to use this: | |
232 | \ | |
233 | \ 1) man printf and read, this covers the basics. | |
234 | \ 2) the delta with printf is the % behaviour; printf will consume | |
235 | \ the %<illegal> and this implemention does not. | |
236 | \ If you want to print a %x (a reserved sequence) you need to | |
237 | \ escape the % by using another one. %%x | |
238 | \ | |
239 | \ Valid encodings are: | |
240 | \ | |
241 | \ %c - character | |
242 | \ %d - signed decimal 32bit value | |
243 | \ %x - unsigned hex 32bit value | |
244 | \ %ld - signed decimal 64bit value | |
245 | \ %lx - unsigned hex 64bit value | |
246 | \ | |
247 | \ In addition you can encode field widths for all the valid encodings. | |
248 | \ | |
249 | \ An example using decimal. | |
250 | \ | |
251 | \ %5d - put a 32bit signed decimal number in | |
252 | \ a field width of 5, the number is truncated | |
253 | \ and right justified. | |
254 | \ %-5d - put a 32bit signed decimal number in | |
255 | \ a field width of 5, the number is truncated | |
256 | \ and left justified. | |
257 | \ | |
258 | \ A simple example, print a name and an age and a newline. | |
259 | \ | |
260 | \ : display-record ( name$ age -- ) | |
261 | \ cmn-type[ " %s is %d years old"r"n" ]cmn-end | |
262 | \ ; | |
263 | \ | |
264 | \ Note that the arguments are used in the order they appear in the stack | |
265 | \ diagram - from left to right, NOT by their stack positions. | |
266 | \ | |
267 | \ Extending the example a little, to put the name and age in fixed width | |
268 | \ fields: 10 characters for the name, left justified and 3 for the age. | |
269 | \ | |
270 | \ : display-record ( name$ age -- ) | |
271 | \ cmn-type[ " %-10s is %3d years old"r"n" ]cmn-end | |
272 | \ ; | |
273 | ||
274 | variable fmt-head | |
275 | variable fmt-tail | |
276 | struct | |
277 | /n field >fmt-next \ next format block | |
278 | /c field >fmt-width \ field width | |
279 | /c field >fmt-flags \ bit0 = Long Value, bit1 = unsigned | |
280 | /w field >fmt-data | |
281 | /n field >fmt-encode \ type encoder | |
282 | 2 /n* field >fmt-args \ data for encoder | |
283 | constant /fmt-data | |
284 | ||
285 | \ ff is -1. | |
286 | \ a primitive sign extending c@ would be nice - like <w@ | |
287 | ||
288 | [ifnexist] <c@ | |
289 | : <c@ ( n -- x ) c@ dup h# 80 and if d# 256 - then ; | |
290 | [then] | |
291 | ||
292 | \ copy the args out | |
293 | : (fmt-s) ( ptr -- ) | |
294 | >r r@ >fmt-args 2@ ( str len ) | |
295 | r> >fmt-width <c@ ( str len ) | |
296 | ?dup if | |
297 | >r r@ 0< if ( str,len ) | |
298 | r@ abs min ( str,len' ) | |
299 | tuck buffered-type ( len' ) | |
300 | r> + ( n ) | |
301 | negate buffered-spaces exit ( ) | |
302 | else ( str,len ) | |
303 | r@ min ( str,len ) | |
304 | r> over - buffered-spaces ( ) | |
305 | then | |
306 | then | |
307 | buffered-type | |
308 | ; | |
309 | ||
310 | : (fmt-cpy) ( ptr -- ) >fmt-args 2@ buffered-type ; | |
311 | : (fmt-c) ( ptr -- ) | |
312 | >r | |
313 | r@ >fmt-args @ r@ >fmt-data c! | |
314 | r@ >fmt-data 1 r@ >fmt-args 2! | |
315 | r> (fmt-s) | |
316 | ; | |
317 | : (fmt-.n) ( ptr -- ) | |
318 | >r r@ >fmt-args dup @ ( dptr data ) | |
319 | r@ >fmt-flags c@ case ( dptr data ) | |
320 | 0 of over l! dup <l@ (.) endof \ signed 32 bit | |
321 | 1 of (.) endof \ 64 bit, signed | |
322 | 2 of over l! dup l@ (u.) endof \ unsigned 32 bit | |
323 | 3 of (u.) endof \ 64 bit, unsigned | |
324 | endcase | |
325 | rot 2! ( ) | |
326 | r> (fmt-s) ( ) | |
327 | ; | |
328 | ||
329 | : (fmt-.d) ( ptr -- ) decimal (fmt-.n) ; | |
330 | : (fmt-.x) ( ptr -- ) hex (fmt-.n) ; | |
331 | ||
332 | : (fmt-save) ( ?? items ptr -- ) | |
333 | >r case ( ?? ) | |
334 | 0 of endof ( ) | |
335 | 1 of r@ >fmt-args ! endof ( ) | |
336 | 2 of r@ >fmt-args 2! endof ( ) | |
337 | ." Can't support " .d ." arguments in common messaging string" cr | |
338 | abort | |
339 | endcase ( ) | |
340 | r> drop ( ) | |
341 | ; | |
342 | ||
343 | : (fmt-push) ( ?? items code acf -- node ) | |
344 | /fmt-data alloc-mem >r ( ) | |
345 | r@ >fmt-encode ! ( ?? items code ) | |
346 | wbsplit ( ?? items width flags ) | |
347 | r@ >fmt-flags c! ( ?? items width ) | |
348 | r@ >fmt-width c! ( ?? items ) | |
349 | 0 r@ >fmt-next ! ( ?? items ) | |
350 | r@ (fmt-save) ( ) | |
351 | r@ ( node ) | |
352 | fmt-tail dup @ ( node ptr tail ) | |
353 | r@ ( node ptr tail node ) | |
354 | rot ! ( node tail ) | |
355 | ?dup if ( node tail ) | |
356 | >fmt-next ! ( ) | |
357 | else ( node ) | |
358 | fmt-head ! ( ) | |
359 | then ( ) | |
360 | r> ( node ) | |
361 | ; | |
362 | ||
363 | \ Unroll the string | |
364 | : (fmt-exec) ( -- ) | |
365 | fmt-head @ ( ptr ) | |
366 | begin ( ptr ) | |
367 | ?dup while ( ptr ) | |
368 | >r r@ r@ >fmt-encode @ execute ( ptr ) | |
369 | r@ >fmt-next @ ( ptr ) | |
370 | r> /fmt-data free-mem ( ptr ) | |
371 | dup fmt-head ! ( ptr ) | |
372 | repeat ( ) | |
373 | ; | |
374 | ||
375 | : (fmt-valid?) ( ptr -- flag ) | |
376 | c@ case | |
377 | ascii d of true endof \ decimal | |
378 | ascii x of true endof \ hex | |
379 | ascii c of true endof \ char | |
380 | ascii s of true endof \ string | |
381 | ascii p of true endof \ pointer | |
382 | false swap | |
383 | endcase | |
384 | ; | |
385 | ||
386 | \ verify that the string contains a valid encoder sequence. | |
387 | \ return the skip size (2 for ld), (1 for d) for example. | |
388 | \ and a flag. | |
389 | ||
390 | : (sfmt-valid?) ( str,len -- str,len,n,-1 | str,len,0 ) | |
391 | dup 2 >= if ( str,len ) | |
392 | over c@ ascii l = if ( str,len ) | |
393 | over 1+ (fmt-valid?) if ( str,len ) | |
394 | 2 true ( str,len ) | |
395 | else ( str,len ) | |
396 | false ( str,len,0 ) | |
397 | then ( str,len ) | |
398 | exit ( str,len,n,-1 | str,len,0 ) | |
399 | then ( str,len ) | |
400 | then ( str,len ) | |
401 | over (fmt-valid?) if ( str,len ) | |
402 | 1 true ( str,len,1,true ) | |
403 | else ( str,len ) | |
404 | false ( str,len,0 ) | |
405 | then ( str,len,n,-1 | str,len,0 ) | |
406 | ; | |
407 | ||
408 | \ an optimisation for tokens.. | |
409 | : ((fmt-.x)) h# 200 or ['] (fmt-.x) 1 false ; | |
410 | ||
411 | \ convert the character encoding into field widths, and the encoder | |
412 | \ acf | |
413 | : (fmt-decode) ( flags,ptr -- flags,acf,n,flag ) | |
414 | c@ case | |
415 | ascii d of ['] (fmt-.d) 1 false endof \ decimal | |
416 | ascii x of ((fmt-.x)) endof \ hex (unsigned) | |
417 | ascii c of ['] (fmt-c) 1 false endof \ char | |
418 | ascii s of ['] (fmt-s) 2 false endof \ string | |
419 | ascii p of ((fmt-.x)) endof \ hex pointer | |
420 | >r 2 ['] (fmt-cpy) true r> | |
421 | endcase | |
422 | ; | |
423 | ||
424 | \ return true if this string does not have a valid encoding | |
425 | \ else return false, the field with and the encoding acf | |
426 | ||
427 | : (scan-for-fmt) ( str$ -- str$,w,acf,n,0 | str$,true ) | |
428 | recursive | |
429 | over c@ ascii % = if ( str$ ) | |
430 | \ %% forces a % which is a special case | |
431 | 1 /string true ( str$,true ) | |
432 | exit ( str$,true ) | |
433 | then ( str$ ) | |
434 | ||
435 | \ Simple fieldless sequence? | |
436 | (sfmt-valid?) if ( str$,n ) | |
437 | 2 pick >r ( str$,n ) | |
438 | >r r@ /string ( str$' ) | |
439 | 0 r@ 1- bwjoin ( str$,w ) | |
440 | r> 1- r> + (fmt-decode) ( str$,w,acf,n,flag ) | |
441 | exit ( str,len ) | |
442 | then ( str,len ) | |
443 | ||
444 | \ field is left justified? | |
445 | over c@ ascii - = if ( str,len 1 ) | |
446 | -1 1 ( str,len -1 1 ) | |
447 | else ( str,len ) | |
448 | 0 0 ( str,len 1 0 ) | |
449 | then ( str,len 1 0 ) | |
450 | ||
451 | \ skip the numbers | |
452 | 3 pick + 0 ( str,len sign num,len ) | |
453 | begin ( str,len sign num,len ) | |
454 | 2dup + c@ d# 10 digit nip while ( str,len sign num,n ) | |
455 | 1+ ( str,len sign ) | |
456 | repeat ( str,len sign num,len ) | |
457 | ||
458 | \ verify the token following the numbers (if any) | |
459 | ?dup if ( str,len sign num,len ) | |
460 | rot /string ( str,len num,len ) | |
461 | tuck ( str,len len num,len ) | |
462 | $number if ( str,len len ) | |
463 | drop true exit ( str,len,true ) | |
464 | then ( str,len len w ) | |
465 | >r ( str,len len ) | |
466 | dup ( str,len len len ) | |
467 | 3 pick + r> over >r >r ( str,len len fmt ) | |
468 | 2 pick 2 pick - ( str,len len fmt,len ) | |
469 | (sfmt-valid?) if ( str,len len fmt,len s ) | |
470 | >r 2drop ( str,len len ) | |
471 | r@ + /string ( str$ ) | |
472 | r> 1- ( str$ s' ) | |
473 | r> over bwjoin ( str$ s' code ) | |
474 | swap r> + ( str$ code fmt' ) | |
475 | (fmt-decode) ( str$ code,acf,n,flag ) | |
476 | exit | |
477 | else ( str,len len fmt,len ) | |
478 | 2r> 3drop ( str,len len fmt ) | |
479 | then ( str,len len fmt ) | |
480 | then ( str,len len fmt ) | |
481 | 2drop ( str,len ) | |
482 | true ( str$,true ) | |
483 | ; | |
484 | ||
485 | \ the meat of the parsing | |
486 | : (fmt-parse) ( str,len -- ) | |
487 | dup 0= if 2drop exit then | |
488 | recursive | |
489 | ascii % left-parse-string ?dup if ( right$ left$ ) | |
490 | 2 0 ['] (fmt-cpy) (fmt-push) drop ( right$ ) | |
491 | else ( right$ leftva ) | |
492 | drop ( right$ ) | |
493 | then ( right$ ) | |
494 | ?dup if ( right$ ) | |
495 | (scan-for-fmt) if ( right$ ) | |
496 | \ we have a % to print, fake it with a %c conversion | |
497 | ascii % 1 0 ['] (fmt-c) (fmt-push) drop ( right$ ) | |
498 | (fmt-parse) ( ) | |
499 | else ( right$ ) | |
500 | >r 0 -rot (fmt-push) ( right$ ptr ) | |
501 | >r (fmt-parse) ( right$ ) | |
502 | r> r> swap (fmt-save) ( ) | |
503 | then | |
504 | else ( va ) | |
505 | drop ( ) | |
506 | then ( ) | |
507 | ; | |
508 | ||
509 | previous definitions also cmn-messaging | |
510 | ||
511 | headers | |
512 | : cmn-append ( ?? str,len -- ) | |
513 | \ Check if there is a current frame to append to | |
514 | current-frame$ @ 0= if | |
515 | ??cr | |
516 | ." Missing cmn-xxx[ caused cmn-append with '" type | |
517 | ." ' argument to fail"r"n" | |
518 | abort | |
519 | then | |
520 | [ifdef] cmn-reentrant? | |
521 | fmt-head dup @ >r off fmt-tail dup @ >r off | |
522 | [else] | |
523 | fmt-head off fmt-tail off | |
524 | [then] | |
525 | push-decimal | |
526 | (fmt-parse) | |
527 | (fmt-exec) | |
528 | pop-base | |
529 | [ifdef] cmn-reentrant? r> fmt-tail ! r> fmt-head ! [then] | |
530 | ; | |
531 | ||
532 | previous also cmn-messaging definitions | |
533 | ||
534 | headerless | |
535 | : cmn-[ ( msg-category -- ) | |
536 | ||
537 | \ Allocate buffer for a new message text string | |
538 | max-message-len /cmn-message + alloc-mem ( category message-addr) | |
539 | ||
540 | \ Clear the buffer headers with zeroes | |
541 | dup /cmn-message erase ( category message-addr) | |
542 | ||
543 | \ Compile buffer length at the beginning into cmn>messsage>maxlen field | |
544 | max-message-len over >cmn-message>maxlen w! ( category message-addr) | |
545 | ||
546 | \ Allocate pointer data structure for a new message frame | |
547 | /cmn-frame alloc-mem >r ( category message-addr ) ( r: frame-addr) | |
548 | ||
549 | \ Clear the pointer data structure with zeroes | |
550 | r@ /cmn-frame erase ( category message-addr ) | |
551 | ||
552 | \ Set >cmn-message field; | |
553 | \ Store the pointer to the message text string buffer into >cmn-message field | |
554 | \ of the message frame pointer data structure | |
555 | r@ >cmn-message ! ( category ) | |
556 | ||
557 | \ Compile the current message category into >cmn-category field | |
558 | \ of the message frame pointer data structure | |
559 | r@ >cmn-category c! ( ) | |
560 | ||
561 | \ Set >cmn-phandle field | |
562 | \ Store phandle into current >cmn-phandle field | |
563 | \ of the message frame pointer data structure | |
564 | ?phandle r@ >cmn-phandle ! ( ) | |
565 | ||
566 | \ Set >cmn-parent field | |
567 | \ Store the pointer to the parent frame into >cmn-parent field | |
568 | \ of the message frame pointer data structure | |
569 | current-frame$ @ r@ >cmn-parent ! | |
570 | ||
571 | \ Set >cmn-peer field | |
572 | 0 r@ >cmn-peer ! | |
573 | current-frame$ @ if r@ add-new-child then | |
574 | ||
575 | \ Store the pointer to the current message frame pointer | |
576 | \ data structure into current-frame$ | |
577 | r> current-frame$ ! ( ) ( r: ) | |
578 | ||
579 | \ The 'lose' is patched to cmn-end, later in this file | |
580 | \ we dont want or need to use a defer!! | |
581 | push-checkpt ?dup if | |
582 | " ...(text may have been truncated due to an exception)"r"n" lose | |
583 | throw | |
584 | then | |
585 | ||
586 | ; | |
587 | ||
588 | \ Prints the content of the message between cmn-xxx[ and ]cmn-end | |
589 | : .message-content ( frame-addr -- ) | |
590 | >cmn-message @ >cmn-message>lstr long-count type | |
591 | ; | |
592 | ||
593 | \ Prints device path followed by colon | |
594 | : .devpath ( frame-addr -- ) | |
595 | >cmn-phandle @ ?dup if ( phandle) | |
596 | phandle>devname type | |
597 | ascii : emit space | |
598 | then | |
599 | ; | |
600 | ||
601 | \ Selects individual format based on message category | |
602 | : (print-message) ( frame-addr -- ) | |
603 | >r | |
604 | ||
605 | r@ >cmn-category c@ case | |
606 | ||
607 | cmn-fatal of | |
608 | ??cr | |
609 | ." FATAL: " | |
610 | r@ .devpath | |
611 | r@ .message-content | |
612 | endof | |
613 | ||
614 | cmn-error of | |
615 | ??cr | |
616 | ." ERROR: " | |
617 | r@ .devpath | |
618 | r@ .message-content | |
619 | endof | |
620 | ||
621 | cmn-warning of | |
622 | ??cr | |
623 | ." WARNING: " | |
624 | r@ .devpath | |
625 | r@ .message-content | |
626 | endof | |
627 | ||
628 | cmn-note of | |
629 | ??cr | |
630 | ." NOTICE: " | |
631 | r@ .message-content | |
632 | endof | |
633 | ||
634 | cmn-type of | |
635 | r@ .message-content | |
636 | endof | |
637 | ||
638 | cmn-msg of | |
639 | r@ .devpath | |
640 | r@ .message-content | |
641 | endof | |
642 | ||
643 | endcase | |
644 | ||
645 | r> drop | |
646 | ; | |
647 | ||
648 | \ Release messaging frame and message buffer after message was printed | |
649 | ||
650 | : release-frame ( frame-addr -- ) | |
651 | ||
652 | \ Release message buffer first | |
653 | dup >cmn-message @ ( frame-addr message-addr) | |
654 | dup >cmn-message>maxlen w@ /cmn-message + ( frame-addr message-addr message-maxlen ) | |
655 | free-mem ( frame-addr) | |
656 | ||
657 | \ Then release message frame | |
658 | /cmn-frame free-mem ( ) | |
659 | ; | |
660 | ||
661 | \ Print message based on type and verbosity level | |
662 | ||
663 | : print-message ( frame -- ) | |
664 | fw-verbosity diagnostic-mode? or over >cmn-category c@ and if (print-message) else drop then | |
665 | ; | |
666 | ||
667 | \ Common messaging frame printing code | |
668 | ||
669 | : print-messaging-tree ( frame-addr -- ) recursive | |
670 | begin ?dup while ( frame-addr ) | |
671 | dup print-message ( frame-addr ) | |
672 | dup >cmn-child @ ( frame-addr child-addr) | |
673 | print-messaging-tree ( frame-addr) | |
674 | dup >cmn-peer @ ( frame-addr peer-addr) | |
675 | swap release-frame ( peer-addr) | |
676 | repeat ( ) | |
677 | ; | |
678 | ||
679 | \ ]cmn-end should always fetch address from current >cmn-parent | |
680 | \ field and store it into current-frame$ | |
681 | ||
682 | : cmn-end ( str,len -- ) | |
683 | cmn-append ( ) | |
684 | true current-frame$ @ >cmn-completion c! \ Message completed | |
685 | current-frame$ dup @ ( current-frame$ current-frame-addr ) | |
686 | >cmn-parent @ ( current-frame$ parent-frame-addr ) | |
687 | ?dup if ( current-frame$ parent-frame-addr ) | |
688 | swap ! exit ( ) | |
689 | then ( current-frame$ ) | |
690 | dup @ ( current-frame$ root-frame-addr ) | |
691 | platform-cmn-end-hook ( current-frame$ ) | |
692 | print-messaging-tree ( current-frame$ ) | |
693 | 0 swap ! ( ) | |
694 | platform-cmn-end-hook2 ( ) | |
695 | ; | |
696 | \ Fixup the forward reference in cmn-[ | |
697 | patch cmn-end lose cmn-[ | |
698 | ||
699 | ||
700 | previous definitions also cmn-messaging | |
701 | headers | |
702 | ||
703 | : ]cmn-end ( str,len -- ) cmn-append " "r"n" cmn-end pop-checkpt ; | |
704 | ||
705 | : cmn-fatal[ ( -- ) platform-fatal-hook true is system-fatal-state? cmn-fatal cmn-[ ; | |
706 | : cmn-error[ ( -- ) platform-error-hook true is system-error-state? cmn-error cmn-[ ; | |
707 | : cmn-warn[ ( -- ) platform-warning-hook cmn-warning cmn-[ ; | |
708 | : cmn-note[ ( -- ) platform-note-hook cmn-note cmn-[ ; | |
709 | : cmn-msg[ ( -- ) cmn-msg cmn-[ ; | |
710 | : cmn-type[ ( -- ) cmn-type cmn-[ ; | |
711 | ||
712 | headerless | |
713 | \ Close and print all messaging frames currently opened | |
714 | : flush-cmn-messages ( -- ) | |
715 | begin current-frame$ @ while " " ]cmn-end repeat | |
716 | ; | |
717 | ||
718 | headers | |
719 | \ Need name here because it is now calling cmn-append | |
720 | ||
721 | previous definitions | |
722 | ||
723 | also magic-properties definitions | |
724 | ||
725 | \ Name now automatically cmn-appends the name of the node | |
726 | \ to the current cmn-messaging frame which must be started | |
727 | \ with cmn-msg[. Used for OBP probing output. Executes type | |
728 | \ if there is no active messaging frame. | |
729 | ||
730 | : name ( value-str name-str -- value-str name-str ) | |
731 | [ also cmn-messaging ] | |
732 | diagnostic-mode? if | |
733 | 2over decode-string current-frame$ @ if | |
734 | " %s " cmn-append | |
735 | else | |
736 | type space | |
737 | then | |
738 | 2drop | |
739 | then | |
740 | [ previous ] | |
741 | ; | |
742 | ||
743 | previous definitions | |
744 | ||
745 | headerless |