[BACK]Return to cordprnt.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / gc / cord

Annotation of OpenXM_contrib/gc/cord/cordprnt.c, Revision 1.1.1.1

1.1       maekawa     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>