OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [boehm-gc/] [cord/] [cordprnt.c] - Blame information for rev 721

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 721 jeremybenn
/*
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 = 0;
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 = (char)va_arg(args, int);
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;
259
                    int max_size = 0;
260
                    int res;
261
#                   ifdef __va_copy
262
                      __va_copy(vsprintf_args, args);
263
#                   else
264
#                     if defined(__GNUC__) && !defined(__DJGPP__) /* and probably in other cases */
265
                        va_copy(vsprintf_args, args);
266
#                     else
267
                        vsprintf_args = args;
268
#                     endif
269
#                   endif
270
                    if (width == VARIABLE) width = va_arg(args, int);
271
                    if (prec == VARIABLE) prec = va_arg(args, int);
272
                    if (width != NONE) max_size = width;
273
                    if (prec != NONE && prec > max_size) max_size = prec;
274
                    max_size += CONV_RESULT_LEN;
275
                    if (max_size >= CORD_BUFSZ) {
276
                        buf = GC_MALLOC_ATOMIC(max_size + 1);
277
                    } else {
278
                        if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
279
                            < max_size) {
280
                            CORD_ec_flush_buf(result);
281
                        }
282
                        buf = result[0].ec_bufptr;
283
                    }
284
                    switch(current) {
285
                        case 'd':
286
                        case 'i':
287
                        case 'o':
288
                        case 'u':
289
                        case 'x':
290
                        case 'X':
291
                        case 'c':
292
                            if (long_arg <= 0) {
293
                              (void) va_arg(args, int);
294
                            } else if (long_arg > 0) {
295
                              (void) va_arg(args, long);
296
                            }
297
                            break;
298
                        case 's':
299
                        case 'p':
300
                            (void) va_arg(args, char *);
301
                            break;
302
                        case 'f':
303
                        case 'e':
304
                        case 'E':
305
                        case 'g':
306
                        case 'G':
307
                            (void) va_arg(args, double);
308
                            break;
309
                        default:
310
                            return(-1);
311
                    }
312
                    res = vsprintf(buf, conv_spec, vsprintf_args);
313
                    len = (size_t)res;
314
                    if ((char *)(GC_word)res == buf) {
315
                        /* old style vsprintf */
316
                        len = strlen(buf);
317
                    } else if (res < 0) {
318
                        return(-1);
319
                    }
320
                    if (buf != result[0].ec_bufptr) {
321
                        register char c;
322
 
323
                        while ((c = *buf++)) {
324
                            CORD_ec_append(result, c);
325
                        }
326
                    } else {
327
                        result[0].ec_bufptr = buf + len;
328
                    }
329
                }
330
              done:;
331
            }
332
        } else {
333
            CORD_ec_append(result, current);
334
        }
335
    }
336
    count = ec_len(result);
337
    *out = CORD_balance(CORD_ec_to_cord(result));
338
    return(count);
339
}
340
 
341
int CORD_sprintf(CORD * out, CORD format, ...)
342
{
343
    va_list args;
344
    int result;
345
 
346
    va_start(args, format);
347
    result = CORD_vsprintf(out, format, args);
348
    va_end(args);
349
    return(result);
350
}
351
 
352
int CORD_fprintf(FILE * f, CORD format, ...)
353
{
354
    va_list args;
355
    int result;
356
    CORD out;
357
 
358
    va_start(args, format);
359
    result = CORD_vsprintf(&out, format, args);
360
    va_end(args);
361
    if (result > 0) CORD_put(out, f);
362
    return(result);
363
}
364
 
365
int CORD_vfprintf(FILE * f, CORD format, va_list args)
366
{
367
    int result;
368
    CORD out;
369
 
370
    result = CORD_vsprintf(&out, format, args);
371
    if (result > 0) CORD_put(out, f);
372
    return(result);
373
}
374
 
375
int CORD_printf(CORD format, ...)
376
{
377
    va_list args;
378
    int result;
379
    CORD out;
380
 
381
    va_start(args, format);
382
    result = CORD_vsprintf(&out, format, args);
383
    va_end(args);
384
    if (result > 0) CORD_put(out, stdout);
385
    return(result);
386
}
387
 
388
int CORD_vprintf(CORD format, va_list args)
389
{
390
    int result;
391
    CORD out;
392
 
393
    result = CORD_vsprintf(&out, format, args);
394
    if (result > 0) CORD_put(out, stdout);
395
    return(result);
396
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.