Annotation of OpenXM_contrib2/asir2000/gc/cord/cordprnt.c, Revision 1.1
1.1 ! noro 1: /*
! 2: * Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
! 3: *
! 4: * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
! 5: * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
! 6: *
! 7: * Permission is hereby granted to use or copy this program
! 8: * for any purpose, provided the above notices are retained on all copies.
! 9: * Permission to modify the code and to distribute modified code is granted,
! 10: * provided the above notices are retained, and a notice that the code was
! 11: * modified is included with the above copyright notice.
! 12: */
! 13: /* An sprintf implementation that understands cords. This is probably */
! 14: /* not terribly portable. It assumes an ANSI stdarg.h. It further */
! 15: /* assumes that I can make copies of va_list variables, and read */
! 16: /* arguments repeatedly by applyting va_arg to the copies. This */
! 17: /* could be avoided at some performance cost. */
! 18: /* We also assume that unsigned and signed integers of various kinds */
! 19: /* have the same sizes, and can be cast back and forth. */
! 20: /* We assume that void * and char * have the same size. */
! 21: /* All this cruft is needed because we want to rely on the underlying */
! 22: /* sprintf implementation whenever possible. */
! 23: /* Boehm, September 21, 1995 6:00 pm PDT */
! 24:
! 25: #include "cord.h"
! 26: #include "ec.h"
! 27: #include <stdio.h>
! 28: #include <stdarg.h>
! 29: #include <string.h>
! 30: #include "gc.h"
! 31:
! 32: #define CONV_SPEC_LEN 50 /* Maximum length of a single */
! 33: /* conversion specification. */
! 34: #define CONV_RESULT_LEN 50 /* Maximum length of any */
! 35: /* conversion with default */
! 36: /* width and prec. */
! 37:
! 38:
! 39: static int ec_len(CORD_ec x)
! 40: {
! 41: return(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
! 42: }
! 43:
! 44: /* Possible nonumeric precision values. */
! 45: # define NONE -1
! 46: # define VARIABLE -2
! 47: /* Copy the conversion specification from CORD_pos into the buffer buf */
! 48: /* Return negative on error. */
! 49: /* Source initially points one past the leading %. */
! 50: /* It is left pointing at the conversion type. */
! 51: /* Assign field width and precision to *width and *prec. */
! 52: /* If width or prec is *, VARIABLE is assigned. */
! 53: /* Set *left to 1 if left adjustment flag is present. */
! 54: /* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to */
! 55: /* -1 if 'h' is present. */
! 56: static int extract_conv_spec(CORD_pos source, char *buf,
! 57: int * width, int *prec, int *left, int * long_arg)
! 58: {
! 59: register int result = 0;
! 60: register int current_number = 0;
! 61: register int saw_period = 0;
! 62: register int saw_number;
! 63: register int chars_so_far = 0;
! 64: register char current;
! 65:
! 66: *width = NONE;
! 67: buf[chars_so_far++] = '%';
! 68: while(CORD_pos_valid(source)) {
! 69: if (chars_so_far >= CONV_SPEC_LEN) return(-1);
! 70: current = CORD_pos_fetch(source);
! 71: buf[chars_so_far++] = current;
! 72: switch(current) {
! 73: case '*':
! 74: saw_number = 1;
! 75: current_number = VARIABLE;
! 76: break;
! 77: case '0':
! 78: if (!saw_number) {
! 79: /* Zero fill flag; ignore */
! 80: break;
! 81: } /* otherwise fall through: */
! 82: case '1':
! 83: case '2':
! 84: case '3':
! 85: case '4':
! 86: case '5':
! 87: case '6':
! 88: case '7':
! 89: case '8':
! 90: case '9':
! 91: saw_number = 1;
! 92: current_number *= 10;
! 93: current_number += current - '0';
! 94: break;
! 95: case '.':
! 96: saw_period = 1;
! 97: if(saw_number) {
! 98: *width = current_number;
! 99: saw_number = 0;
! 100: }
! 101: current_number = 0;
! 102: break;
! 103: case 'l':
! 104: case 'L':
! 105: *long_arg = 1;
! 106: current_number = 0;
! 107: break;
! 108: case 'h':
! 109: *long_arg = -1;
! 110: current_number = 0;
! 111: break;
! 112: case ' ':
! 113: case '+':
! 114: case '#':
! 115: current_number = 0;
! 116: break;
! 117: case '-':
! 118: *left = 1;
! 119: current_number = 0;
! 120: break;
! 121: case 'd':
! 122: case 'i':
! 123: case 'o':
! 124: case 'u':
! 125: case 'x':
! 126: case 'X':
! 127: case 'f':
! 128: case 'e':
! 129: case 'E':
! 130: case 'g':
! 131: case 'G':
! 132: case 'c':
! 133: case 'C':
! 134: case 's':
! 135: case 'S':
! 136: case 'p':
! 137: case 'n':
! 138: case 'r':
! 139: goto done;
! 140: default:
! 141: return(-1);
! 142: }
! 143: CORD_next(source);
! 144: }
! 145: return(-1);
! 146: done:
! 147: if (saw_number) {
! 148: if (saw_period) {
! 149: *prec = current_number;
! 150: } else {
! 151: *prec = NONE;
! 152: *width = current_number;
! 153: }
! 154: } else {
! 155: *prec = NONE;
! 156: }
! 157: buf[chars_so_far] = '\0';
! 158: return(result);
! 159: }
! 160:
! 161: int CORD_vsprintf(CORD * out, CORD format, va_list args)
! 162: {
! 163: CORD_ec result;
! 164: register int count;
! 165: register char current;
! 166: CORD_pos pos;
! 167: char conv_spec[CONV_SPEC_LEN + 1];
! 168:
! 169: CORD_ec_init(result);
! 170: for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) {
! 171: current = CORD_pos_fetch(pos);
! 172: if (current == '%') {
! 173: CORD_next(pos);
! 174: if (!CORD_pos_valid(pos)) return(-1);
! 175: current = CORD_pos_fetch(pos);
! 176: if (current == '%') {
! 177: CORD_ec_append(result, current);
! 178: } else {
! 179: int width, prec;
! 180: int left_adj = 0;
! 181: int long_arg = 0;
! 182: CORD arg;
! 183: size_t len;
! 184:
! 185: if (extract_conv_spec(pos, conv_spec,
! 186: &width, &prec,
! 187: &left_adj, &long_arg) < 0) {
! 188: return(-1);
! 189: }
! 190: current = CORD_pos_fetch(pos);
! 191: switch(current) {
! 192: case 'n':
! 193: /* Assign length to next arg */
! 194: if (long_arg == 0) {
! 195: int * pos_ptr;
! 196: pos_ptr = va_arg(args, int *);
! 197: *pos_ptr = ec_len(result);
! 198: } else if (long_arg > 0) {
! 199: long * pos_ptr;
! 200: pos_ptr = va_arg(args, long *);
! 201: *pos_ptr = ec_len(result);
! 202: } else {
! 203: short * pos_ptr;
! 204: pos_ptr = va_arg(args, short *);
! 205: *pos_ptr = ec_len(result);
! 206: }
! 207: goto done;
! 208: case 'r':
! 209: /* Append cord and any padding */
! 210: if (width == VARIABLE) width = va_arg(args, int);
! 211: if (prec == VARIABLE) prec = va_arg(args, int);
! 212: arg = va_arg(args, CORD);
! 213: len = CORD_len(arg);
! 214: if (prec != NONE && len > prec) {
! 215: if (prec < 0) return(-1);
! 216: arg = CORD_substr(arg, 0, prec);
! 217: len = prec;
! 218: }
! 219: if (width != NONE && len < width) {
! 220: char * blanks = GC_MALLOC_ATOMIC(width-len+1);
! 221:
! 222: memset(blanks, ' ', width-len);
! 223: blanks[width-len] = '\0';
! 224: if (left_adj) {
! 225: arg = CORD_cat(arg, blanks);
! 226: } else {
! 227: arg = CORD_cat(blanks, arg);
! 228: }
! 229: }
! 230: CORD_ec_append_cord(result, arg);
! 231: goto done;
! 232: case 'c':
! 233: if (width == NONE && prec == NONE) {
! 234: register char c;
! 235:
! 236: c = va_arg(args, char);
! 237: CORD_ec_append(result, c);
! 238: goto done;
! 239: }
! 240: break;
! 241: case 's':
! 242: if (width == NONE && prec == NONE) {
! 243: char * str = va_arg(args, char *);
! 244: register char c;
! 245:
! 246: while (c = *str++) {
! 247: CORD_ec_append(result, c);
! 248: }
! 249: goto done;
! 250: }
! 251: break;
! 252: default:
! 253: break;
! 254: }
! 255: /* Use standard sprintf to perform conversion */
! 256: {
! 257: register char * buf;
! 258: va_list vsprintf_args = args;
! 259: /* The above does not appear to be sanctioned */
! 260: /* by the ANSI C standard. */
! 261: int max_size = 0;
! 262: int res;
! 263:
! 264: if (width == VARIABLE) width = va_arg(args, int);
! 265: if (prec == VARIABLE) prec = va_arg(args, int);
! 266: if (width != NONE) max_size = width;
! 267: if (prec != NONE && prec > max_size) max_size = prec;
! 268: max_size += CONV_RESULT_LEN;
! 269: if (max_size >= CORD_BUFSZ) {
! 270: buf = GC_MALLOC_ATOMIC(max_size + 1);
! 271: } else {
! 272: if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
! 273: < max_size) {
! 274: CORD_ec_flush_buf(result);
! 275: }
! 276: buf = result[0].ec_bufptr;
! 277: }
! 278: switch(current) {
! 279: case 'd':
! 280: case 'i':
! 281: case 'o':
! 282: case 'u':
! 283: case 'x':
! 284: case 'X':
! 285: case 'c':
! 286: if (long_arg <= 0) {
! 287: (void) va_arg(args, int);
! 288: } else if (long_arg > 0) {
! 289: (void) va_arg(args, long);
! 290: }
! 291: break;
! 292: case 's':
! 293: case 'p':
! 294: (void) va_arg(args, char *);
! 295: break;
! 296: case 'f':
! 297: case 'e':
! 298: case 'E':
! 299: case 'g':
! 300: case 'G':
! 301: (void) va_arg(args, double);
! 302: break;
! 303: default:
! 304: return(-1);
! 305: }
! 306: res = vsprintf(buf, conv_spec, vsprintf_args);
! 307: len = (size_t)res;
! 308: if ((char *)(GC_word)res == buf) {
! 309: /* old style vsprintf */
! 310: len = strlen(buf);
! 311: } else if (res < 0) {
! 312: return(-1);
! 313: }
! 314: if (buf != result[0].ec_bufptr) {
! 315: register char c;
! 316:
! 317: while (c = *buf++) {
! 318: CORD_ec_append(result, c);
! 319: }
! 320: } else {
! 321: result[0].ec_bufptr = buf + len;
! 322: }
! 323: }
! 324: done:;
! 325: }
! 326: } else {
! 327: CORD_ec_append(result, current);
! 328: }
! 329: }
! 330: count = ec_len(result);
! 331: *out = CORD_balance(CORD_ec_to_cord(result));
! 332: return(count);
! 333: }
! 334:
! 335: int CORD_sprintf(CORD * out, CORD format, ...)
! 336: {
! 337: va_list args;
! 338: int result;
! 339:
! 340: va_start(args, format);
! 341: result = CORD_vsprintf(out, format, args);
! 342: va_end(args);
! 343: return(result);
! 344: }
! 345:
! 346: int CORD_fprintf(FILE * f, CORD format, ...)
! 347: {
! 348: va_list args;
! 349: int result;
! 350: CORD out;
! 351:
! 352: va_start(args, format);
! 353: result = CORD_vsprintf(&out, format, args);
! 354: va_end(args);
! 355: if (result > 0) CORD_put(out, f);
! 356: return(result);
! 357: }
! 358:
! 359: int CORD_vfprintf(FILE * f, CORD format, va_list args)
! 360: {
! 361: int result;
! 362: CORD out;
! 363:
! 364: result = CORD_vsprintf(&out, format, args);
! 365: if (result > 0) CORD_put(out, f);
! 366: return(result);
! 367: }
! 368:
! 369: int CORD_printf(CORD format, ...)
! 370: {
! 371: va_list args;
! 372: int result;
! 373: CORD out;
! 374:
! 375: va_start(args, format);
! 376: result = CORD_vsprintf(&out, format, args);
! 377: va_end(args);
! 378: if (result > 0) CORD_put(out, stdout);
! 379: return(result);
! 380: }
! 381:
! 382: int CORD_vprintf(CORD format, va_list args)
! 383: {
! 384: int result;
! 385: CORD out;
! 386:
! 387: result = CORD_vsprintf(&out, format, args);
! 388: if (result > 0) CORD_put(out, stdout);
! 389: return(result);
! 390: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>