1: #include 2: #include 3: #include 4: 5: 6: /* 7: * If using long or floating point types, define __LONG and/or 8: * __FLOAT to enable support for them. 9: * 10: * Extra features in this version of mprnt.c: 11: * 12: * + flag for sign insertion 13: * leading zeros 14: * 15: * 16: * 17: * doprnt for PIC. Supports: 18: * 19: * %d decimal 20: * %u unsigned 21: * %o octal 22: * %x hex (lower case) 23: * %X hex (upper case) 24: * %s string 25: * %c character 26: * 27: * On the 14 bit PICS only: 28: * Field widths and precision are supported (precision is significant 29: * only for %s), including variable width, e.g. %*s 30: * 31: * Optionally (on 14 bitters) 32: * 33: * %ld long decimal 34: * %lx long hex (lower case) 35: * %lX long hex (upper case) 36: * %lo long octal 37: * 38: * Even more optionally: 39: * 40: * %f float (really double) - field width and precision supported 41: * %e float - scientific format 42: * 43: * $Id: newmprnt.c,v 1.8 2000/10/23 03:17:47 lucky Exp $ 44: * $Log: newmprnt.c,v $ 45: * Revision 1.8 2000/10/23 03:17:47 lucky 46: * Added a comment about compiling for long or float support 47: * 48: * Revision 1.7 1999/05/06 20:16:09 clyde 49: * Fixed problem where 1.02 was printed as 1. 2 50: * 51: * 52: */ 53: 54: #ifdef __FLOAT 55: #define __LONG 1 /* float requires long */ 56: #endif 57: 58: #ifdef __LONG 59: #define INT long 60: #else 61: #define INT short 62: #endif 63: 64: #define pputch(c) (retval++, where ? (void)(*where++=(c)):putch(c)) 65: const char * x; 66: 67: // definitions for "sign" 68: 69: #define LONG 0x80 // long integral type to be printed 70: #define MANSIGN 0x40 // sign must be printed 71: 72: #define PADZERO 0x10 // unused width is to be padded with 0s 73: 74: #define NOZEROPAD 0x04 // zero padding cannot be selected 75: #define ISFLOAT 0x02 // type is float and "." still to be printed 76: #define ISSIGNED 0x01 // number is signed, also... 77: #define ISNEG 0x01 // number is negative, "-" to be printed 78: 79: unsigned char 80: #ifdef _PIC16 81: sprintf(far char * where, const char * f, ...) 82: #else 83: sprintf(char * where, const char * f, ...) 84: #endif 85: { 86: char c; 87: va_list ap; 88: unsigned char sign; 89: unsigned char prec; 90: unsigned INT i; 91: unsigned char retval; 92: #ifdef __FLOAT 93: unsigned long frac; 94: unsigned long over; 95: unsigned char digs; 96: #endif 97: #ifndef _PIC12 98: signed char width; 99: #else 100: #define width sign 101: #endif 102: 103: retval = 0; 104: va_start(ap, f); 105: while(c = *f++) 106: if(c != '%') 107: pputch(c); 108: else { 109: prec = 255; 110: #ifndef _PIC12 111: width = 0; 112: #endif 113: sign = 0; 114: loop: 115: switch(c = *f++) { 116: 117: case 0: 118: if(where) 119: *where = 0; 120: return retval; 121: #ifndef _PIC12 122: case '*': 123: width = va_arg(ap, int); 124: goto loop; 125: case '+': 126: sign |= MANSIGN; 127: goto loop; 128: #if __LONG 129: case 'l': 130: sign |= LONG; 131: goto loop; 132: #endif 133: #endif 134: 135: 136: 137: case 'd': 138: sign++; // set ISSIGNED 139: goto decimal; 140: case 'x': 141: case 'X': 142: prec += 8; 143: case 'o': 144: prec -= 2; 145: case 'u': 146: decimal: 147: { 148: unsigned INT j; 149: 150: #if __LONG 151: if(sign & LONG) 152: i = va_arg(ap, unsigned INT); 153: else 154: #endif 155: i = va_arg(ap, int); 156: if(sign & ISSIGNED) { 157: if((INT)i < 0) { 158: i = -i; // and leave ISSIGNED SET 159: #ifndef _PIC12 160: width--; 161: #endif 162: } else { 163: sign &= ~ISSIGNED; // clear ISSIGED 164: #ifndef _PIC12 165: if(sign & MANSIGN) 166: width--; 167: #endif _PIC12 168: } 169: } else { 170: #if __LONG 171: if(!(sign & LONG)) 172: i = (unsigned short)i; 173: #endif 174: sign &= ~ISSIGNED; 175: } 176: prec -= 255-10; 177: putint: 178: c = (unsigned INT)i % prec; 179: *(unsigned INT *)&i /= prec; 180: j = 1; 181: while(j <= i) { 182: j *= prec; 183: #ifndef _PIC12 184: width--; 185: #endif 186: } 187: ///////////////////////////////////////////////////////////////////////////////////////// 188: #ifndef _PIC12 189: if(!(sign & PADZERO)) 190: while(--width > 0) 191: pputch(' '); 192: 193: if(sign & ISNEG) 194: pputch('-'); 195: else if(sign & MANSIGN) 196: pputch('+'); 197: if(sign & PADZERO) 198: while(--width > 0) 199: pputch('0'); 200: #else _PIC12 201: if(sign & ISSIGNED) 202: pputch('-'); 203: #endif _PIC12 204: ///////////////////////////////////////////////////////////////////////////////////////// 205: while(j /= prec) { 206: width = (i/j)%prec; 207: if(width > 9) 208: width += 'A'-'0'-10; 209: pputch(width+'0'); 210: } 211: if(c > 9) 212: c += 'A'-'0'-10; 213: pputch(c+'0'); 214: #if __FLOAT 215: if(sign & ISFLOAT) { 216: pputch('.'); 217: i = frac; 218: sign = PADZERO; // clear the request for a dot 219: width = digs; 220: prec = 10; 221: goto putint; 222: } 223: #endif 224: } 225: break; 226: #if __FLOAT 227: case 'f': 228: { 229: double f; 230: 231: f = va_arg(ap, double); 232: if(prec > 6) 233: prec = 6; 234: digs = prec; 235: sign &= 0xF0; 236: if(f < 0) { 237: sign |= ISSIGNED; 238: f = -f; 239: #ifndef _PIC12 240: width--; 241: #endif 242: } else { 243: #ifndef _PIC12 244: if(sign & MANSIGN) 245: width--; 246: #endif _PIC12 247: } 248: if(digs == 0) { 249: i = (unsigned long)(f+0.5); 250: prec = 10; 251: goto putint; /* put as integer - no dot */ 252: } 253: width -= digs+1; 254: i = (unsigned long)f; 255: f -= (double)i; 256: sign |= ISFLOAT; 257: over = 1; 258: do { 259: f *= 10.0; 260: over *= 10; 261: } 262: while(--prec); 263: f += 0.5; 264: frac = (unsigned long)f; 265: if(frac >= over) { 266: frac -= over; 267: i++; 268: } 269: prec = 10; 270: goto putint; 271: } 272: #endif 273: 274: 275: case 'c': 276: #ifndef _PIC12 277: while(width > 1) { 278: pputch(' '); 279: width--; 280: } 281: #endif 282: c = va_arg(ap, int); 283: pputch(c); 284: continue; 285: case 's': 286: { 287: 288: x = va_arg(ap, const char *); 289: #ifndef _PIC12 290: c = 0; 291: while(x[c]) 292: c++; 293: if(c < prec) 294: prec = c; 295: while(width > prec) { 296: pputch(' '); 297: width--; 298: } 299: while(prec--) { 300: c = *x++; 301: pputch(c); 302: } 303: #else 304: while(c = *x++) 305: pputch(c); 306: #endif 307: break; 308: } 309: 310: #ifndef _PIC12 311: case '.': 312: if(*f == '*') { 313: prec = va_arg(ap, int); 314: f++; 315: } else { 316: prec = *f++ - '0'; 317: c = *f; 318: if(c >= '0' && c <= '9') { 319: prec = prec*10 + c - '0'; 320: f++; 321: } 322: } 323: goto loop; 324: 325: case '0': 326: // if we haven't been through a non-zero digit yet 327: if(!(sign & NOZEROPAD)) { 328: sign |= PADZERO; // this is a leading 0 329: goto loop; 330: } 331: // otherwise, fall through 332: default: 333: if(c >= '0' && c <= '9') { 334: sign |= NOZEROPAD; // any zeros to come do not imply zeropad 335: width = width * 10 + c - '0'; 336: goto loop; 337: } 338: #else 339: default: 340: #endif 341: pputch(c); 342: continue; 343: 344: } 345: 346: } 347: if(where) 348: *where = 0; 349: return retval; 350: } 351: