1 | /*-------------------------------------*/ |
---|
2 | /* frmstr.c */ |
---|
3 | /* Last change : 14.10.94 */ |
---|
4 | /*-------------------------------------*/ |
---|
5 | /* |
---|
6 | * $Id$ |
---|
7 | */ |
---|
8 | |
---|
9 | #include "frmstr.h" |
---|
10 | /*-------------------------------------*/ |
---|
11 | /* How to treat the rest. |
---|
12 | */ |
---|
13 | #define FOR_CONSOLE 1 |
---|
14 | #define DO_LONG 1 |
---|
15 | |
---|
16 | /* To Store a byte. |
---|
17 | */ |
---|
18 | #ifdef _STORE_BYTE |
---|
19 | # define STORE_BYTE(a, b) (store_byte(a, b)) |
---|
20 | long store_byte(void); |
---|
21 | #else |
---|
22 | # define STORE_BYTE(a, b) (* (a) = (b)) |
---|
23 | #endif |
---|
24 | /* Some decalrations. |
---|
25 | */ |
---|
26 | static void geta(ArgType *, int); |
---|
27 | static const char * gnum(const char *, ArgType * ); |
---|
28 | static char * i_compute(unsigned val, int, char *); |
---|
29 | #ifdef DO_LONG |
---|
30 | static char * l_compute(long, int, char *); |
---|
31 | #endif |
---|
32 | static ArgType * nextarg; |
---|
33 | /* And macros. |
---|
34 | */ |
---|
35 | #define wsize(par) ((sizeof par) / sizeof(ArgType)) |
---|
36 | #define signbit(par) (1L<<(sizeof par * 8 - 1)) |
---|
37 | |
---|
38 | int format_string(const char * fmt, ArgType * args, char * buffer) |
---|
39 | { |
---|
40 | char * s; |
---|
41 | # ifdef DO_LONG |
---|
42 | long l; |
---|
43 | int lflag; |
---|
44 | # else |
---|
45 | # define lflag 0 |
---|
46 | # endif |
---|
47 | # ifdef DO_FLOAT |
---|
48 | double dbl; |
---|
49 | # endif |
---|
50 | ArgType inte; |
---|
51 | ArgType_U uint; |
---|
52 | ArgType width, ndigit; |
---|
53 | int i, j, c, rjust, ndfnd, zfill; |
---|
54 | const char * oldfmt; |
---|
55 | char * s1, buf[64]; |
---|
56 | |
---|
57 | nextarg = args; |
---|
58 | while (c = * fmt ++) { |
---|
59 | if (c != '%') { |
---|
60 | # ifdef FOR_CONSOLE |
---|
61 | if (c == '\n') STORE_BYTE(buffer ++, '\r'); |
---|
62 | # endif |
---|
63 | STORE_BYTE(buffer ++, c); |
---|
64 | continue; |
---|
65 | } |
---|
66 | # ifdef DO_LONG |
---|
67 | lflag = 0 ; |
---|
68 | # endif |
---|
69 | j = 10 ; |
---|
70 | rjust = 0; |
---|
71 | if (* fmt == '-') { |
---|
72 | fmt ++; |
---|
73 | rjust ++; |
---|
74 | } |
---|
75 | zfill = ' '; |
---|
76 | if (* fmt == '0') { |
---|
77 | fmt ++; |
---|
78 | zfill = '0'; |
---|
79 | } |
---|
80 | fmt = gnum(fmt, & width); |
---|
81 | ndigit = 0; ndfnd = 0; |
---|
82 | if (* fmt == '.') { |
---|
83 | fmt ++; oldfmt = fmt; |
---|
84 | fmt = gnum(fmt, & ndigit); |
---|
85 | ndfnd = (int)(fmt != oldfmt); |
---|
86 | } |
---|
87 | s = s1 = buf; |
---|
88 | # ifdef DO_LONG |
---|
89 | if (* fmt == 'l' || * fmt == 'L') { |
---|
90 | fmt ++; lflag ++; |
---|
91 | } |
---|
92 | # endif |
---|
93 | switch (c = * fmt ++) { |
---|
94 | default: |
---|
95 | # ifdef FOR_CONSOLE |
---|
96 | if (c == '\n') STORE_BYTE(buffer ++, '\r'); |
---|
97 | # endif |
---|
98 | STORE_BYTE(buffer ++, c); |
---|
99 | continue; |
---|
100 | case 's': |
---|
101 | geta((ArgType *) & s1, wsize(s1)); |
---|
102 | s = s1; |
---|
103 | do { |
---|
104 | if (s == 0) break; |
---|
105 | if (* s == 0) |
---|
106 | break; |
---|
107 | s ++; |
---|
108 | } while (-- ndigit); |
---|
109 | break; |
---|
110 | case 'b': |
---|
111 | j = 2; |
---|
112 | case 'u': |
---|
113 | getu: |
---|
114 | |
---|
115 | if (! lflag) { |
---|
116 | geta(& inte, wsize(inte)); |
---|
117 | goto i_unsignd; |
---|
118 | } |
---|
119 | # ifdef DO_LONG |
---|
120 | case 'U': |
---|
121 | getlu: |
---|
122 | |
---|
123 | geta((ArgType *) & l, wsize(l)); |
---|
124 | goto l_unsignd; |
---|
125 | case 'B': |
---|
126 | j = 2 ; |
---|
127 | goto getlu; |
---|
128 | case 'X': |
---|
129 | j = 16; |
---|
130 | goto getlu; |
---|
131 | case 'O': |
---|
132 | j = 8; |
---|
133 | goto getlu ; |
---|
134 | case 'D': |
---|
135 | l_signed: |
---|
136 | |
---|
137 | geta((ArgType *) & l, wsize(l)); |
---|
138 | if (l < 0) { |
---|
139 | STORE_BYTE(s ++, '-'); |
---|
140 | l = -l; |
---|
141 | } |
---|
142 | goto do_l; |
---|
143 | |
---|
144 | l_unsignd: |
---|
145 | |
---|
146 | if (l && ndigit) |
---|
147 | STORE_BYTE(s ++, '0'); |
---|
148 | |
---|
149 | do_l: |
---|
150 | |
---|
151 | s = l_compute(l, j, s); |
---|
152 | break; |
---|
153 | # endif |
---|
154 | case 'x': |
---|
155 | j = 16; |
---|
156 | goto getu; |
---|
157 | case 'o': |
---|
158 | j = 8; |
---|
159 | goto getu; |
---|
160 | case 'd': |
---|
161 | if (lflag) goto l_signed; |
---|
162 | geta(& inte, wsize(inte)); |
---|
163 | if (inte < 0) { |
---|
164 | STORE_BYTE(s ++, '-'); |
---|
165 | inte = - inte; |
---|
166 | } |
---|
167 | goto do_i; |
---|
168 | |
---|
169 | i_unsignd: |
---|
170 | |
---|
171 | if (inte && ndigit) |
---|
172 | STORE_BYTE(s ++, '0'); |
---|
173 | |
---|
174 | do_i: |
---|
175 | |
---|
176 | s = i_compute(inte, j, s); |
---|
177 | break; |
---|
178 | case 'c': |
---|
179 | geta ((ArgType *) & uint, wsize(uint)); |
---|
180 | for (i = sizeof uint - 1; i >= 0; i --) { |
---|
181 | if (STORE_BYTE(s, uint % 256)) s ++; |
---|
182 | uint /= 256 ; |
---|
183 | } |
---|
184 | break; |
---|
185 | # ifdef DO_FLOAT |
---|
186 | case 'e': |
---|
187 | geta((ArgType *) & dbl, wsize(dbl)); |
---|
188 | s = _pscien(dbl, s, ndigit, ndfnd); |
---|
189 | break; |
---|
190 | case 'f': |
---|
191 | geta((ArgType *) &dbl,wsize(dbl)); |
---|
192 | s = _pfloat(dbl, s, ndigit, ndfnd); |
---|
193 | break; |
---|
194 | # endif |
---|
195 | case 'r': |
---|
196 | geta((ArgType *) & nextarg, wsize(nextarg)); |
---|
197 | geta((ArgType *) & oldfmt, wsize(fmt)); |
---|
198 | fmt = oldfmt; |
---|
199 | continue; |
---|
200 | } |
---|
201 | j = s - s1; |
---|
202 | if ((c = width - j) > 0) { |
---|
203 | if (rjust == 0) { |
---|
204 | do STORE_BYTE(buffer ++, zfill); |
---|
205 | while (-- c); |
---|
206 | } |
---|
207 | } |
---|
208 | while (-- j >= 0) |
---|
209 | STORE_BYTE(buffer ++, * s1 ++); |
---|
210 | while (-- c >= 0) |
---|
211 | STORE_BYTE(buffer ++, zfill); |
---|
212 | } |
---|
213 | STORE_BYTE(buffer, 0); |
---|
214 | return 0; |
---|
215 | } |
---|
216 | static void geta(ArgType * p, int size) |
---|
217 | { |
---|
218 | if ((ArgType *) & p - (ArgType *) & size > 0) { |
---|
219 | p += size; |
---|
220 | while (size --) { |
---|
221 | * -- p = * nextarg --; |
---|
222 | } |
---|
223 | } |
---|
224 | else { |
---|
225 | while (size --) { |
---|
226 | * p ++ = * nextarg ++ ; |
---|
227 | } |
---|
228 | } |
---|
229 | } |
---|
230 | static const char * gnum(const char * f, ArgType * ip) |
---|
231 | { |
---|
232 | ArgType i; |
---|
233 | int c; |
---|
234 | |
---|
235 | if (* f == '*') { |
---|
236 | geta(ip, wsize(i)) ; |
---|
237 | f ++; |
---|
238 | } |
---|
239 | else { |
---|
240 | i = 0; |
---|
241 | while ((c = * f - '0') >= 0 && c <= 9) { |
---|
242 | i = i * 10 + c; |
---|
243 | f ++; |
---|
244 | } |
---|
245 | * ip = i; |
---|
246 | } |
---|
247 | return f; |
---|
248 | } |
---|
249 | static char * i_compute(unsigned int val, int base, char * s) |
---|
250 | { |
---|
251 | int c; |
---|
252 | |
---|
253 | c = val % base; |
---|
254 | val /= base; |
---|
255 | if (val) |
---|
256 | s = i_compute(val, base, s); |
---|
257 | STORE_BYTE(s ++, c>9 ? c-10+'a' : c+'0'); |
---|
258 | return s; |
---|
259 | } |
---|
260 | #ifdef DO_LONG |
---|
261 | static char *l_compute(long l1,int d, char * s) |
---|
262 | { |
---|
263 | int c; |
---|
264 | long l2; |
---|
265 | |
---|
266 | if (l1 < 0) { |
---|
267 | c = l1 & 1; |
---|
268 | l2 = ((l1>>1) & ~signbit(l1)); |
---|
269 | l1 = l2 / (d>>1); |
---|
270 | c += (l2%(d>>1))<<1; |
---|
271 | } |
---|
272 | else { |
---|
273 | c = l1 % d; |
---|
274 | l1 = l1 / d; |
---|
275 | } |
---|
276 | if (l1) |
---|
277 | s = l_compute(l1, d, s); |
---|
278 | STORE_BYTE(s ++, c>9 ? c-10+'A' : c+'0'); |
---|
279 | return s; |
---|
280 | } |
---|
281 | #endif |
---|
282 | #ifdef _STORE_BYTE |
---|
283 | long store_byte(char * cp, long c) |
---|
284 | { |
---|
285 | long shift, reg, * ptr; |
---|
286 | |
---|
287 | shift = ((long) cp & 3) * 8; |
---|
288 | ptr = (long *) ((long) cp & ~3); |
---|
289 | reg = * ptr; |
---|
290 | reg &= ~(0xff << shift); |
---|
291 | reg |= c << shift; |
---|
292 | * ptr = reg; |
---|
293 | |
---|
294 | return c; |
---|
295 | } |
---|
296 | #endif |
---|
297 | |
---|
298 | #define SPC 01 |
---|
299 | #define STP 02 |
---|
300 | |
---|
301 | #define NULL 0 |
---|
302 | #define EOF 0 |
---|
303 | #define SHORT 0 |
---|
304 | #define REGULAR 1 |
---|
305 | #define LONG 2 |
---|
306 | #define INT 0 |
---|
307 | #define FLOAT 1 |
---|
308 | |
---|
309 | static int new_c(void); |
---|
310 | static void unnew_c(char); |
---|
311 | static int _innum(int ** ptr, int type, int len, int size, int * eofptr); |
---|
312 | static int _instr(char * ptr, int type, int len, int * eofptr); |
---|
313 | static const char * _getccl(const char *); |
---|
314 | static int vme_isupper(char); |
---|
315 | static int vme_tolower(char); |
---|
316 | static int vme_isdigit(char); |
---|
317 | |
---|
318 | static char _sctab[128] = { |
---|
319 | 0,0,0,0,0,0,0,0, |
---|
320 | 0,SPC,SPC,0,0,0,0,0, |
---|
321 | 0,0,0,0,0,0,0,0, |
---|
322 | 0,0,0,0,0,0,0,0, |
---|
323 | SPC,0,0,0,0,0,0,0, |
---|
324 | 0,0,0,0,0,0,0,0, |
---|
325 | 0,0,0,0,0,0,0,0, |
---|
326 | 0,0,0,0,0,0,0,0, |
---|
327 | }; |
---|
328 | static const char * line; |
---|
329 | static char * linep; |
---|
330 | |
---|
331 | int unformat_string(const char * fmt, int ** argp, const char * buffer) |
---|
332 | { |
---|
333 | int ch; |
---|
334 | int nmatch, len, ch1; |
---|
335 | int ** ptr, fileended, size; |
---|
336 | |
---|
337 | line = buffer; |
---|
338 | linep = (char*)line; |
---|
339 | |
---|
340 | nmatch = 0; |
---|
341 | fileended = 0; |
---|
342 | for (;;) switch (ch = * fmt ++) { |
---|
343 | case '\0': |
---|
344 | return (nmatch); |
---|
345 | case '%': |
---|
346 | if ((ch = * fmt ++) == '%') |
---|
347 | goto def; |
---|
348 | ptr = 0; |
---|
349 | if (ch != '*') |
---|
350 | ptr = argp ++; |
---|
351 | else |
---|
352 | ch = * fmt ++; |
---|
353 | len = 0; |
---|
354 | size = REGULAR; |
---|
355 | while (vme_isdigit(ch)) { |
---|
356 | len = len*10 + ch - '0'; |
---|
357 | ch = * fmt ++; |
---|
358 | } |
---|
359 | if (len == 0) |
---|
360 | len = 30000; |
---|
361 | if (ch == 'l') { |
---|
362 | ch = * fmt ++; |
---|
363 | size = LONG; |
---|
364 | } |
---|
365 | else if (ch == 'h') { |
---|
366 | size = SHORT; |
---|
367 | ch = * fmt ++; |
---|
368 | } |
---|
369 | else if (ch=='[') |
---|
370 | fmt = _getccl(fmt); |
---|
371 | if (vme_isupper(ch)) { |
---|
372 | ch = vme_tolower(ch); |
---|
373 | size = LONG; |
---|
374 | } |
---|
375 | if (ch == '\0') |
---|
376 | return -1; |
---|
377 | if (_innum(ptr, ch, len, size, & fileended) && ptr) |
---|
378 | nmatch ++; |
---|
379 | if (fileended) |
---|
380 | return nmatch? nmatch: -1; |
---|
381 | break; |
---|
382 | case ' ': |
---|
383 | case '\n': |
---|
384 | case '\t': |
---|
385 | while ((ch1 = new_c())==' ' || ch1=='\t' || ch1=='\n') |
---|
386 | ; |
---|
387 | if (ch1 != EOF) |
---|
388 | unnew_c(ch1); |
---|
389 | break; |
---|
390 | default: |
---|
391 | |
---|
392 | def: |
---|
393 | |
---|
394 | ch1 = new_c(); |
---|
395 | if (ch1 != ch) { |
---|
396 | if (ch1==EOF) |
---|
397 | return -1 ; |
---|
398 | unnew_c(ch1); |
---|
399 | return nmatch; |
---|
400 | } |
---|
401 | } |
---|
402 | } |
---|
403 | static int new_c() |
---|
404 | { |
---|
405 | char c; |
---|
406 | |
---|
407 | if (linep) { |
---|
408 | c = * linep ++; |
---|
409 | return c; |
---|
410 | } |
---|
411 | else { |
---|
412 | return 0; |
---|
413 | } |
---|
414 | } |
---|
415 | static void unnew_c(char ch) |
---|
416 | { |
---|
417 | if (linep > line) |
---|
418 | * (-- linep) = ch; |
---|
419 | } |
---|
420 | static int _innum(int ** ptr, int type, int len, int size, int * eofptr) |
---|
421 | { |
---|
422 | # ifdef DO_FLOAT |
---|
423 | extern double atof(); |
---|
424 | # endif |
---|
425 | char * np; |
---|
426 | char numbuf[64]; |
---|
427 | int c, base; |
---|
428 | int expseen, scale, negflg, c1, ndigit; |
---|
429 | long lcval; |
---|
430 | |
---|
431 | if (type=='c' || type=='s' || type=='[') |
---|
432 | return _instr(ptr? * (char **) ptr: (char *) NULL, type, len, eofptr); |
---|
433 | lcval = 0; |
---|
434 | ndigit = 0; |
---|
435 | scale = INT; |
---|
436 | if (type=='e'||type=='f') |
---|
437 | scale = FLOAT; |
---|
438 | base = 10; |
---|
439 | if (type=='o') |
---|
440 | base = 8; |
---|
441 | else if (type=='x') |
---|
442 | base = 16; |
---|
443 | np = numbuf; |
---|
444 | expseen = 0; |
---|
445 | negflg = 0; |
---|
446 | while ((c = new_c())==' ' || c=='\t' || c=='\n'); |
---|
447 | if (c=='-') { |
---|
448 | negflg ++; |
---|
449 | * np ++ = c; |
---|
450 | c = new_c(); |
---|
451 | len --; |
---|
452 | } |
---|
453 | else if (c=='+') { |
---|
454 | len --; |
---|
455 | c = new_c(); |
---|
456 | } |
---|
457 | for ( ; -- len >= 0; * np ++ = c, c = new_c()) { |
---|
458 | if (vme_isdigit(c) |
---|
459 | || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { |
---|
460 | ndigit ++; |
---|
461 | if (base==8) |
---|
462 | lcval <<=3; |
---|
463 | else if (base==10) |
---|
464 | lcval = ((lcval<<2) + lcval)<<1; |
---|
465 | else |
---|
466 | lcval <<= 4; |
---|
467 | c1 = c; |
---|
468 | if ('0'<=c && c<='9') |
---|
469 | c -= '0'; |
---|
470 | else if ('a'<=c && c<='f') |
---|
471 | c -= 'a'-10; |
---|
472 | else |
---|
473 | c -= 'A'-10; |
---|
474 | lcval += c; |
---|
475 | c = c1; |
---|
476 | continue; |
---|
477 | } |
---|
478 | else if (c=='.') { |
---|
479 | if (base!=10 || scale==INT) |
---|
480 | break; |
---|
481 | ndigit ++; |
---|
482 | continue; |
---|
483 | } |
---|
484 | else if ((c=='e'||c=='E') && expseen==0) { |
---|
485 | if (base!=10 || scale==INT || ndigit==0) |
---|
486 | break; |
---|
487 | expseen ++; |
---|
488 | * np ++ = c; |
---|
489 | c = new_c(); |
---|
490 | if (c!='+'&&c!='-'&&('0'>c||c>'9')) |
---|
491 | break; |
---|
492 | } |
---|
493 | else |
---|
494 | break; |
---|
495 | } |
---|
496 | if (negflg) |
---|
497 | lcval = -lcval; |
---|
498 | if (c != EOF) { |
---|
499 | unnew_c(c); |
---|
500 | * eofptr = 0; |
---|
501 | } |
---|
502 | else |
---|
503 | * eofptr = 1; |
---|
504 | if (ptr==NULL || np==numbuf) |
---|
505 | return 0; |
---|
506 | * np ++ = 0; |
---|
507 | switch ((scale<<4) | size) { |
---|
508 | # ifdef DO_FLOAT |
---|
509 | |
---|
510 | case (FLOAT<<4) | SHORT: |
---|
511 | case (FLOAT<<4) | REGULAR: |
---|
512 | ** (float **) ptr = atof(numbuf); |
---|
513 | break; |
---|
514 | |
---|
515 | case (FLOAT<<4) | LONG: |
---|
516 | ** (double **) ptr = atof(numbuf); |
---|
517 | break; |
---|
518 | # endif |
---|
519 | case (INT<<4) | SHORT: |
---|
520 | ** (short **) ptr = lcval; |
---|
521 | break; |
---|
522 | |
---|
523 | case (INT<<4) | REGULAR: |
---|
524 | ** (int **) ptr = lcval; |
---|
525 | break; |
---|
526 | |
---|
527 | case (INT<<4) | LONG: |
---|
528 | ** (long **) ptr = lcval; |
---|
529 | break; |
---|
530 | } |
---|
531 | return 1; |
---|
532 | } |
---|
533 | static int _instr(char * ptr, int type, int len, int * eofptr) |
---|
534 | { |
---|
535 | int ch; |
---|
536 | char * optr; |
---|
537 | int ignstp; |
---|
538 | |
---|
539 | * eofptr = 0; |
---|
540 | optr = ptr; |
---|
541 | if (type=='c' && len==30000) |
---|
542 | len = 1; |
---|
543 | ignstp = 0; |
---|
544 | if (type=='s') |
---|
545 | ignstp = SPC; |
---|
546 | while (_sctab[ch = new_c()] & ignstp) |
---|
547 | if (ch==EOF) |
---|
548 | break; |
---|
549 | ignstp = SPC; |
---|
550 | if (type=='c') |
---|
551 | ignstp = 0; |
---|
552 | else if (type=='[') |
---|
553 | ignstp = STP; |
---|
554 | while (ch!=EOF && (_sctab[ch]&ignstp)==0) { |
---|
555 | if (ptr) |
---|
556 | * ptr ++ = ch; |
---|
557 | if (-- len <= 0) |
---|
558 | break; |
---|
559 | ch = new_c(); |
---|
560 | } |
---|
561 | if (ch != EOF) { |
---|
562 | if (len > 0) |
---|
563 | unnew_c(ch); |
---|
564 | * eofptr = 0; |
---|
565 | } |
---|
566 | else |
---|
567 | * eofptr = 1; |
---|
568 | if (ptr && ptr!=optr) { |
---|
569 | if (type!='c') |
---|
570 | * ptr ++ = '\0'; |
---|
571 | return 1; |
---|
572 | } |
---|
573 | return 0; |
---|
574 | } |
---|
575 | static const char * _getccl(const char * s) |
---|
576 | { |
---|
577 | int c, t; |
---|
578 | |
---|
579 | t = 0; |
---|
580 | if (* s == '^') { |
---|
581 | t ++; |
---|
582 | s ++; |
---|
583 | } |
---|
584 | for (c = 0; c < 128; c++) |
---|
585 | if (t) |
---|
586 | _sctab[c] &= ~STP; |
---|
587 | else |
---|
588 | _sctab[c] |= STP; |
---|
589 | while (((c = * s ++)&0177) != ']') { |
---|
590 | if (t) |
---|
591 | _sctab[c++] |= STP; |
---|
592 | else |
---|
593 | _sctab[c++] &= ~STP; |
---|
594 | if (c==0) |
---|
595 | return -- s; |
---|
596 | } |
---|
597 | return s; |
---|
598 | } |
---|
599 | static int vme_isupper(char ch) |
---|
600 | { |
---|
601 | if( ch >= 'A' & ch <= 'Z') |
---|
602 | return 1; |
---|
603 | else |
---|
604 | return 0; |
---|
605 | } |
---|
606 | static int vme_tolower(char ch) |
---|
607 | { |
---|
608 | return 'a' + 'A' - ch; |
---|
609 | } |
---|
610 | static vme_isdigit(char ch) |
---|
611 | { |
---|
612 | if (ch >= '0' & ch <= '9') |
---|
613 | return 1; |
---|
614 | else |
---|
615 | return 0; |
---|
616 | } |
---|
617 | /*-------------*/ |
---|
618 | /* End of file */ |
---|
619 | /*-------------*/ |
---|
620 | |
---|