#include #include #define MAXSTR 300 #define B32MASK 0x7fffffff /* strip the long int sign bit */ /* Format string options: "%-0w.p,l{dux}" - left justified (else right) 0 left zero fill w field width , comma separate 1000's l long a base 36 */ char _spr_sepchar = ','; /* 1000's seperator character */ /* Write a tring to the console. */ cputs(s) char *s; { while (*s) lconout(*s++); } /* Replacements for the overly large Lattice ones. */ cprintf(f) char *f; { char buf[MAXSTR],*p; _spr(buf,&f); cputs(buf); } printf(f) char *f; { char buf[MAXSTR],*p; _spr(buf,&f); p= buf; while (*p) bdos(2,*p++); } sprintf(s,f) char *s,*f; { _spr(s,&f); } /* Formatted string processor for printf() etc. Will only work on a Lattice long data model. Gross. Plagiarized from Leor Zolman's STDLIB2 for BDS C 1.42. Brain Damage Software still lives on ... This is gross, as it uses funny pointers instead of a structure. Oh well. Also, it is dependent on a char being the same size as an int on the stack. */ _spr(line,fmt) char *line, **fmt; { char c, base, *sptr, *format, **s; char ljflag, zfflag, sepflag; int width, *args; int sizearg,islong; long num; char sign; unsigned li; /* index into line, above */ char sb[MAXSTR]; char wb[32]; /* room for largest possible digit string */ unsigned si; /* index to sb[] */ unsigned i,j,l; long *longarg; char **charstararg; format = (char *)*fmt++; args = (int *)fmt; li= 0; /* total output line length */ while (c = *format++) { if (c == '%') { si= 0; /* output buffer index */ ljflag= zfflag= sepflag= 0; /* no options yet */ if (*format == '-') { /* left-justify */ format++; ljflag++; } if (*format == '0') zfflag++; /* test for zero-fill */ width = (isdigit(*format)) ? _gv2(&format) : 0; c= *format++; /* get format char */ if (c == ',') { /* en-comma-ization */ c= *format++; /* re-get format char */ sepflag= 1; } longarg= (long *)args; /* preset ptrs */ charstararg= (char **)args; /* to various arg types */ islong= 0; /* assume short arg */ if (c == 'l') { /* if long, */ c= *format++; /* skip the L, */ sizearg= sizeof(long); /* for bumping pointer */ longarg= (long *)args; /* force confusing typing */ num= *longarg; /* get the value, */ islong= 1; } else { sizearg= sizeof(int); num= 0L + *args; } sign= '\0'; /* not negative */ switch(toupper(c)) { case 'D': if (num < 0L) { /* for negative numbers */ sign= '-'; /* flag it */ --width; num= 0L - num; /* and flip it */ } /* fall through */ case 'U': base = 10; goto val; case 'X': base = 16; goto val; case 'O': base = 8; goto val; case 'A': base = 36; goto val; /* _uspr() builds the plain digit string in wb, the Work Buffer. If using comma formatting, then separators are added before the string is moved to sb, the String Buffer. */ /* Since Lattice 2.15 doesn't have an 'unsigned long' type, we have cannot have long numbers < 0; or else infinite recursion in uspr results. Flag truncated long ints with a leading "*". */ val: if (islong) { if (num & ~B32MASK) sign= '*'; num &= B32MASK; } else num &= 0xffffL; _uspr(wb,&si,num,base); if ((si > 3) && sepflag) { l = si % 3; if (l == 0) l= 3; /* si= raw string length wb= raw digit string (ie. "12345") sb= working string (ie. "12,345") l= 100's digits counter, MOD 3 i= index into sb[] j= index into wb[] */ for (i= j= 0; j < si;) { sb[i++]= wb[j++]; if ((--l == 0) && (j < si)) sb[i++]= _spr_sepchar; if (l <= 0) l= 3; } si= i; /* see pad: */ } else for (i= 0; i < si; i++) sb[i]= wb[i]; width -= i; /* compensate for actual width */ if (islong) args= (int *) ++longarg; else ++args; goto pad; /* A char on the stack is the same size as an int. */ case 'C': sb[si++]= *(char *)args; ++args; width--; goto pad; case 'S': sptr = *(char **)args; args= (int *) ++charstararg; while (*sptr) { sb[si++]= *sptr++; width--; } /* Pad this out to the specified width, if any. Insert the leading sign character. */ pad: sb[si]= '\0'; /* terminate it */ if (! ljflag) { while (width-- > 0) { line[li++]= (zfflag ? '0' : ' '); } } if (sign) line[li++]= sign; /* possible sign char */ for (i= 0; sb[i];) /* then the text */ line[li++]= sb[i++]; if (ljflag) while (width-- > 0) line[li++]= ' '; break; default: line[li++]= c; break; } } else line[li++]= c; /* else not % */ } line[li]= '\0'; } /* Internal routine used by "_spr" to perform ascii- to-decimal conversion and update an associated pointer: */ int _gv2(sptr) char **sptr; { int n; n = 0; while (isdigit(**sptr)) n = 10 * n + *(*sptr)++ - '0'; return(n); } static char itoctbl[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; _uspr(buff, buffi, n, base) char buff[]; unsigned *buffi; long n; unsigned base; { unsigned length; if ((n < base) && (n >= 0L)) { buff[*buffi]= itoctbl[n]; if (*buffi < MAXSTR) ++(*buffi); buff[*buffi]= '\0'; return(1); } length = _uspr(buff, buffi, (long)(n / base), base); _uspr(buff, buffi, (long)(n % base), base); return (length + 1); }