/*-------------------------------------*/ /* frmstr.c */ /* Last change : 14.10.94 */ /*-------------------------------------*/ /* * $Id$ */ #include "frmstr.h" /*-------------------------------------*/ /* How to treat the rest. */ #define FOR_CONSOLE 1 #define DO_LONG 1 /* To Store a byte. */ #ifdef _STORE_BYTE # define STORE_BYTE(a, b) (store_byte(a, b)) long store_byte(void); #else # define STORE_BYTE(a, b) (* (a) = (b)) #endif /* Some decalrations. */ static void geta(ArgType *, int); static const char * gnum(const char *, ArgType * ); static char * i_compute(unsigned val, int, char *); #ifdef DO_LONG static char * l_compute(long, int, char *); #endif static ArgType * nextarg; /* And macros. */ #define wsize(par) ((sizeof par) / sizeof(ArgType)) #define signbit(par) (1L<<(sizeof par * 8 - 1)) int format_string(const char * fmt, ArgType * args, char * buffer) { char * s; # ifdef DO_LONG long l; int lflag; # else # define lflag 0 # endif # ifdef DO_FLOAT double dbl; # endif ArgType inte; ArgType_U uint; ArgType width, ndigit; int i, j, c, rjust, ndfnd, zfill; const char * oldfmt; char * s1, buf[64]; nextarg = args; while (c = * fmt ++) { if (c != '%') { # ifdef FOR_CONSOLE if (c == '\n') STORE_BYTE(buffer ++, '\r'); # endif STORE_BYTE(buffer ++, c); continue; } # ifdef DO_LONG lflag = 0 ; # endif j = 10 ; rjust = 0; if (* fmt == '-') { fmt ++; rjust ++; } zfill = ' '; if (* fmt == '0') { fmt ++; zfill = '0'; } fmt = gnum(fmt, & width); ndigit = 0; ndfnd = 0; if (* fmt == '.') { fmt ++; oldfmt = fmt; fmt = gnum(fmt, & ndigit); ndfnd = (int)(fmt != oldfmt); } s = s1 = buf; # ifdef DO_LONG if (* fmt == 'l' || * fmt == 'L') { fmt ++; lflag ++; } # endif switch (c = * fmt ++) { default: # ifdef FOR_CONSOLE if (c == '\n') STORE_BYTE(buffer ++, '\r'); # endif STORE_BYTE(buffer ++, c); continue; case 's': geta((ArgType *) & s1, wsize(s1)); s = s1; do { if (s == 0) break; if (* s == 0) break; s ++; } while (-- ndigit); break; case 'b': j = 2; case 'u': getu: if (! lflag) { geta(& inte, wsize(inte)); goto i_unsignd; } # ifdef DO_LONG case 'U': getlu: geta((ArgType *) & l, wsize(l)); goto l_unsignd; case 'B': j = 2 ; goto getlu; case 'X': j = 16; goto getlu; case 'O': j = 8; goto getlu ; case 'D': l_signed: geta((ArgType *) & l, wsize(l)); if (l < 0) { STORE_BYTE(s ++, '-'); l = -l; } goto do_l; l_unsignd: if (l && ndigit) STORE_BYTE(s ++, '0'); do_l: s = l_compute(l, j, s); break; # endif case 'x': j = 16; goto getu; case 'o': j = 8; goto getu; case 'd': if (lflag) goto l_signed; geta(& inte, wsize(inte)); if (inte < 0) { STORE_BYTE(s ++, '-'); inte = - inte; } goto do_i; i_unsignd: if (inte && ndigit) STORE_BYTE(s ++, '0'); do_i: s = i_compute(inte, j, s); break; case 'c': geta ((ArgType *) & uint, wsize(uint)); for (i = sizeof uint - 1; i >= 0; i --) { if (STORE_BYTE(s, uint % 256)) s ++; uint /= 256 ; } break; # ifdef DO_FLOAT case 'e': geta((ArgType *) & dbl, wsize(dbl)); s = _pscien(dbl, s, ndigit, ndfnd); break; case 'f': geta((ArgType *) &dbl,wsize(dbl)); s = _pfloat(dbl, s, ndigit, ndfnd); break; # endif case 'r': geta((ArgType *) & nextarg, wsize(nextarg)); geta((ArgType *) & oldfmt, wsize(fmt)); fmt = oldfmt; continue; } j = s - s1; if ((c = width - j) > 0) { if (rjust == 0) { do STORE_BYTE(buffer ++, zfill); while (-- c); } } while (-- j >= 0) STORE_BYTE(buffer ++, * s1 ++); while (-- c >= 0) STORE_BYTE(buffer ++, zfill); } STORE_BYTE(buffer, 0); return 0; } static void geta(ArgType * p, int size) { if ((ArgType *) & p - (ArgType *) & size > 0) { p += size; while (size --) { * -- p = * nextarg --; } } else { while (size --) { * p ++ = * nextarg ++ ; } } } static const char * gnum(const char * f, ArgType * ip) { ArgType i; int c; if (* f == '*') { geta(ip, wsize(i)) ; f ++; } else { i = 0; while ((c = * f - '0') >= 0 && c <= 9) { i = i * 10 + c; f ++; } * ip = i; } return f; } static char * i_compute(unsigned int val, int base, char * s) { int c; c = val % base; val /= base; if (val) s = i_compute(val, base, s); STORE_BYTE(s ++, c>9 ? c-10+'a' : c+'0'); return s; } #ifdef DO_LONG static char *l_compute(long l1,int d, char * s) { int c; long l2; if (l1 < 0) { c = l1 & 1; l2 = ((l1>>1) & ~signbit(l1)); l1 = l2 / (d>>1); c += (l2%(d>>1))<<1; } else { c = l1 % d; l1 = l1 / d; } if (l1) s = l_compute(l1, d, s); STORE_BYTE(s ++, c>9 ? c-10+'A' : c+'0'); return s; } #endif #ifdef _STORE_BYTE long store_byte(char * cp, long c) { long shift, reg, * ptr; shift = ((long) cp & 3) * 8; ptr = (long *) ((long) cp & ~3); reg = * ptr; reg &= ~(0xff << shift); reg |= c << shift; * ptr = reg; return c; } #endif #define SPC 01 #define STP 02 #define NULL 0 #define EOF 0 #define SHORT 0 #define REGULAR 1 #define LONG 2 #define INT 0 #define FLOAT 1 static int new_c(void); static void unnew_c(char); static int _innum(int ** ptr, int type, int len, int size, int * eofptr); static int _instr(char * ptr, int type, int len, int * eofptr); static const char * _getccl(const char *); static int vme_isupper(char); static int vme_tolower(char); static int vme_isdigit(char); static char _sctab[128] = { 0,0,0,0,0,0,0,0, 0,SPC,SPC,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, SPC,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0, }; static const char * line; static char * linep; int unformat_string(const char * fmt, int ** argp, const char * buffer) { int ch; int nmatch, len, ch1; int ** ptr, fileended, size; line = buffer; linep = (char*)line; nmatch = 0; fileended = 0; for (;;) switch (ch = * fmt ++) { case '\0': return (nmatch); case '%': if ((ch = * fmt ++) == '%') goto def; ptr = 0; if (ch != '*') ptr = argp ++; else ch = * fmt ++; len = 0; size = REGULAR; while (vme_isdigit(ch)) { len = len*10 + ch - '0'; ch = * fmt ++; } if (len == 0) len = 30000; if (ch == 'l') { ch = * fmt ++; size = LONG; } else if (ch == 'h') { size = SHORT; ch = * fmt ++; } else if (ch=='[') fmt = _getccl(fmt); if (vme_isupper(ch)) { ch = vme_tolower(ch); size = LONG; } if (ch == '\0') return -1; if (_innum(ptr, ch, len, size, & fileended) && ptr) nmatch ++; if (fileended) return nmatch? nmatch: -1; break; case ' ': case '\n': case '\t': while ((ch1 = new_c())==' ' || ch1=='\t' || ch1=='\n') ; if (ch1 != EOF) unnew_c(ch1); break; default: def: ch1 = new_c(); if (ch1 != ch) { if (ch1==EOF) return -1 ; unnew_c(ch1); return nmatch; } } } static int new_c() { char c; if (linep) { c = * linep ++; return c; } else { return 0; } } static void unnew_c(char ch) { if (linep > line) * (-- linep) = ch; } static int _innum(int ** ptr, int type, int len, int size, int * eofptr) { # ifdef DO_FLOAT extern double atof(); # endif char * np; char numbuf[64]; int c, base; int expseen, scale, negflg, c1, ndigit; long lcval; if (type=='c' || type=='s' || type=='[') return _instr(ptr? * (char **) ptr: (char *) NULL, type, len, eofptr); lcval = 0; ndigit = 0; scale = INT; if (type=='e'||type=='f') scale = FLOAT; base = 10; if (type=='o') base = 8; else if (type=='x') base = 16; np = numbuf; expseen = 0; negflg = 0; while ((c = new_c())==' ' || c=='\t' || c=='\n'); if (c=='-') { negflg ++; * np ++ = c; c = new_c(); len --; } else if (c=='+') { len --; c = new_c(); } for ( ; -- len >= 0; * np ++ = c, c = new_c()) { if (vme_isdigit(c) || base==16 && ('a'<=c && c<='f' || 'A'<=c && c<='F')) { ndigit ++; if (base==8) lcval <<=3; else if (base==10) lcval = ((lcval<<2) + lcval)<<1; else lcval <<= 4; c1 = c; if ('0'<=c && c<='9') c -= '0'; else if ('a'<=c && c<='f') c -= 'a'-10; else c -= 'A'-10; lcval += c; c = c1; continue; } else if (c=='.') { if (base!=10 || scale==INT) break; ndigit ++; continue; } else if ((c=='e'||c=='E') && expseen==0) { if (base!=10 || scale==INT || ndigit==0) break; expseen ++; * np ++ = c; c = new_c(); if (c!='+'&&c!='-'&&('0'>c||c>'9')) break; } else break; } if (negflg) lcval = -lcval; if (c != EOF) { unnew_c(c); * eofptr = 0; } else * eofptr = 1; if (ptr==NULL || np==numbuf) return 0; * np ++ = 0; switch ((scale<<4) | size) { # ifdef DO_FLOAT case (FLOAT<<4) | SHORT: case (FLOAT<<4) | REGULAR: ** (float **) ptr = atof(numbuf); break; case (FLOAT<<4) | LONG: ** (double **) ptr = atof(numbuf); break; # endif case (INT<<4) | SHORT: ** (short **) ptr = lcval; break; case (INT<<4) | REGULAR: ** (int **) ptr = lcval; break; case (INT<<4) | LONG: ** (long **) ptr = lcval; break; } return 1; } static int _instr(char * ptr, int type, int len, int * eofptr) { int ch; char * optr; int ignstp; * eofptr = 0; optr = ptr; if (type=='c' && len==30000) len = 1; ignstp = 0; if (type=='s') ignstp = SPC; while (_sctab[ch = new_c()] & ignstp) if (ch==EOF) break; ignstp = SPC; if (type=='c') ignstp = 0; else if (type=='[') ignstp = STP; while (ch!=EOF && (_sctab[ch]&ignstp)==0) { if (ptr) * ptr ++ = ch; if (-- len <= 0) break; ch = new_c(); } if (ch != EOF) { if (len > 0) unnew_c(ch); * eofptr = 0; } else * eofptr = 1; if (ptr && ptr!=optr) { if (type!='c') * ptr ++ = '\0'; return 1; } return 0; } static const char * _getccl(const char * s) { int c, t; t = 0; if (* s == '^') { t ++; s ++; } for (c = 0; c < 128; c++) if (t) _sctab[c] &= ~STP; else _sctab[c] |= STP; while (((c = * s ++)&0177) != ']') { if (t) _sctab[c++] |= STP; else _sctab[c++] &= ~STP; if (c==0) return -- s; } return s; } static int vme_isupper(char ch) { if( ch >= 'A' & ch <= 'Z') return 1; else return 0; } static int vme_tolower(char ch) { return 'a' + 'A' - ch; } static vme_isdigit(char ch) { if (ch >= '0' & ch <= '9') return 1; else return 0; } /*-------------*/ /* End of file */ /*-------------*/