[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     ! 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>