gcc/boehm-gc/cord/cordprnt.c
Jeff Sturm 30c3de1ffb Import GC 6.3alpha1.
* BCC_MAKEFILE: Merge with GC 6.3alpha1 release.
	* ChangeLog: Likewise.
	* Makefile.am: Likewise.
	* Makefile.direct: Likewise.
	* Makefile.dj: Likewise.
	* allchblk.c: Likewise.
	* alloc.c: Likewise.
	* backgraph.c: Likewise.
	* configure.host: Likewise.
	* configure.in: Likewise.
	* dbg_mlc.c: Likewise.
	* dyn_load.c: Likewise.
	* finalize.c: Likewise.
	* gc_cpp.cc: Likewise.
	* gc_dlopen.c: Likewise.
	* gcj_mlc.c: Likewise.
	* if_mach.c: Likewise.
	* mach_dep.c: Likewise.
	* malloc.c: Likewise.
	* mallocx.c: Likewise.
	* mark.c: Likewise.
	* mark_rts.c: Likewise.
	* misc.c: Likewise.
	* os_dep.c: Likewise.
	* ptr_chck.c: Likewise.
	* reclaim.c: Likewise.
	* solaris_pthreads.c: Likewise.
	* solaris_threads.c: Likewise.
	* sparc_mach_dep.S: Likewise.
	* threadlibs.c: Likewise.
	* typd_mlc.c: Likewise.
	* version.h: Likewise.
	* win32_threads.c: Likewise.
	* Mac_files/MacOS_Test_config.h: Likewise.
	* Mac_files/MacOS_config.h: Likewise.
	* cord/cordbscs.c: Likewise.
	* cord/cordprnt.c: Likewise.
	* cord/de_win.c: Likewise.
	* doc/README: Likewise.
	* doc/README.MacOSX: Likewise.
	* doc/README.changes: Likewise.
	* doc/README.environment: Likewise.
	* doc/README.ews4800: Likewise.
	* doc/README.linux: Likewise.
	* doc/README.macros: Likewise.
	* doc/README.win32: Likewise.
	* doc/debugging.html: Likewise.
	* doc/gcdescr.html: Likewise.
	* doc/tree.html: Likewise.
	* include/Makefile.in: Likewise.
	* include/gc.h: Likewise.
	* include/gc_cpp.h: Likewise.
	* include/gc_local_alloc.h: Likewise.
	* include/gc_mark.h: Likewise.
	* include/gc_pthread_redirects.h: Likewise.
	* include/gc_typed.h: Likewise.
	* include/new_gc_alloc.h: Likewise.
	* include/private/dbg_mlc.h: Likewise.
	* include/private/gc_hdrs.h: Likewise.
	* include/private/gc_locks.h: Likewise.
	* include/private/gc_pmark.h: Likewise.
	* include/private/gc_priv.h: Likewise.
	* include/private/gcconfig.h: Likewise.
	* include/private/solaris_threads.h: Likewise.
	* include/private/specific.h: Likewise.
	* tests/test.c: Likewise.
	* tests/test_cpp.cc: Likewise.

	* configure: Rebuild.
	* Makefile.in: Rebuild.

	* mips_sgi_mach_dep.s: Add.

	* alpha_mach_dep.s: Remove.
	* irix_threads.c: Remove.
	* linux_threads.c: Remove.
	* mips_sgi_mach_dep.S: Remove.
	* missing: Remove.
	* powerpc_macosx_mach_dep.s: Remove.
	* doc/Makefile.am: Remove.
	* doc/Makefile.in: Remove.

From-SVN: r69880
2003-07-28 04:18:23 +00:00

397 lines
11 KiB
C

/*
* Copyright (c) 1993-1994 by Xerox Corporation. All rights reserved.
*
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
*
* Permission is hereby granted to use or copy this program
* for any purpose, provided the above notices are retained on all copies.
* Permission to modify the code and to distribute modified code is granted,
* provided the above notices are retained, and a notice that the code was
* modified is included with the above copyright notice.
*/
/* An sprintf implementation that understands cords. This is probably */
/* not terribly portable. It assumes an ANSI stdarg.h. It further */
/* assumes that I can make copies of va_list variables, and read */
/* arguments repeatedly by applyting va_arg to the copies. This */
/* could be avoided at some performance cost. */
/* We also assume that unsigned and signed integers of various kinds */
/* have the same sizes, and can be cast back and forth. */
/* We assume that void * and char * have the same size. */
/* All this cruft is needed because we want to rely on the underlying */
/* sprintf implementation whenever possible. */
/* Boehm, September 21, 1995 6:00 pm PDT */
#include "cord.h"
#include "ec.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "gc.h"
#define CONV_SPEC_LEN 50 /* Maximum length of a single */
/* conversion specification. */
#define CONV_RESULT_LEN 50 /* Maximum length of any */
/* conversion with default */
/* width and prec. */
static int ec_len(CORD_ec x)
{
return(CORD_len(x[0].ec_cord) + (x[0].ec_bufptr - x[0].ec_buf));
}
/* Possible nonumeric precision values. */
# define NONE -1
# define VARIABLE -2
/* Copy the conversion specification from CORD_pos into the buffer buf */
/* Return negative on error. */
/* Source initially points one past the leading %. */
/* It is left pointing at the conversion type. */
/* Assign field width and precision to *width and *prec. */
/* If width or prec is *, VARIABLE is assigned. */
/* Set *left to 1 if left adjustment flag is present. */
/* Set *long_arg to 1 if long flag ('l' or 'L') is present, or to */
/* -1 if 'h' is present. */
static int extract_conv_spec(CORD_pos source, char *buf,
int * width, int *prec, int *left, int * long_arg)
{
register int result = 0;
register int current_number = 0;
register int saw_period = 0;
register int saw_number;
register int chars_so_far = 0;
register char current;
*width = NONE;
buf[chars_so_far++] = '%';
while(CORD_pos_valid(source)) {
if (chars_so_far >= CONV_SPEC_LEN) return(-1);
current = CORD_pos_fetch(source);
buf[chars_so_far++] = current;
switch(current) {
case '*':
saw_number = 1;
current_number = VARIABLE;
break;
case '0':
if (!saw_number) {
/* Zero fill flag; ignore */
break;
} /* otherwise fall through: */
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
saw_number = 1;
current_number *= 10;
current_number += current - '0';
break;
case '.':
saw_period = 1;
if(saw_number) {
*width = current_number;
saw_number = 0;
}
current_number = 0;
break;
case 'l':
case 'L':
*long_arg = 1;
current_number = 0;
break;
case 'h':
*long_arg = -1;
current_number = 0;
break;
case ' ':
case '+':
case '#':
current_number = 0;
break;
case '-':
*left = 1;
current_number = 0;
break;
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
case 'c':
case 'C':
case 's':
case 'S':
case 'p':
case 'n':
case 'r':
goto done;
default:
return(-1);
}
CORD_next(source);
}
return(-1);
done:
if (saw_number) {
if (saw_period) {
*prec = current_number;
} else {
*prec = NONE;
*width = current_number;
}
} else {
*prec = NONE;
}
buf[chars_so_far] = '\0';
return(result);
}
int CORD_vsprintf(CORD * out, CORD format, va_list args)
{
CORD_ec result;
register int count;
register char current;
CORD_pos pos;
char conv_spec[CONV_SPEC_LEN + 1];
CORD_ec_init(result);
for (CORD_set_pos(pos, format, 0); CORD_pos_valid(pos); CORD_next(pos)) {
current = CORD_pos_fetch(pos);
if (current == '%') {
CORD_next(pos);
if (!CORD_pos_valid(pos)) return(-1);
current = CORD_pos_fetch(pos);
if (current == '%') {
CORD_ec_append(result, current);
} else {
int width, prec;
int left_adj = 0;
int long_arg = 0;
CORD arg;
size_t len;
if (extract_conv_spec(pos, conv_spec,
&width, &prec,
&left_adj, &long_arg) < 0) {
return(-1);
}
current = CORD_pos_fetch(pos);
switch(current) {
case 'n':
/* Assign length to next arg */
if (long_arg == 0) {
int * pos_ptr;
pos_ptr = va_arg(args, int *);
*pos_ptr = ec_len(result);
} else if (long_arg > 0) {
long * pos_ptr;
pos_ptr = va_arg(args, long *);
*pos_ptr = ec_len(result);
} else {
short * pos_ptr;
pos_ptr = va_arg(args, short *);
*pos_ptr = ec_len(result);
}
goto done;
case 'r':
/* Append cord and any padding */
if (width == VARIABLE) width = va_arg(args, int);
if (prec == VARIABLE) prec = va_arg(args, int);
arg = va_arg(args, CORD);
len = CORD_len(arg);
if (prec != NONE && len > prec) {
if (prec < 0) return(-1);
arg = CORD_substr(arg, 0, prec);
len = prec;
}
if (width != NONE && len < width) {
char * blanks = GC_MALLOC_ATOMIC(width-len+1);
memset(blanks, ' ', width-len);
blanks[width-len] = '\0';
if (left_adj) {
arg = CORD_cat(arg, blanks);
} else {
arg = CORD_cat(blanks, arg);
}
}
CORD_ec_append_cord(result, arg);
goto done;
case 'c':
if (width == NONE && prec == NONE) {
register char c;
c = (char)va_arg(args, int);
CORD_ec_append(result, c);
goto done;
}
break;
case 's':
if (width == NONE && prec == NONE) {
char * str = va_arg(args, char *);
register char c;
while (c = *str++) {
CORD_ec_append(result, c);
}
goto done;
}
break;
default:
break;
}
/* Use standard sprintf to perform conversion */
{
register char * buf;
va_list vsprintf_args;
int max_size = 0;
int res;
# ifdef __va_copy
__va_copy(vsprintf_args, args);
# else
# if defined(__GNUC__) /* and probably in other cases */
va_copy(vsprintf_args, args);
# else
vsprintf_args = args;
# endif
# endif
if (width == VARIABLE) width = va_arg(args, int);
if (prec == VARIABLE) prec = va_arg(args, int);
if (width != NONE) max_size = width;
if (prec != NONE && prec > max_size) max_size = prec;
max_size += CONV_RESULT_LEN;
if (max_size >= CORD_BUFSZ) {
buf = GC_MALLOC_ATOMIC(max_size + 1);
} else {
if (CORD_BUFSZ - (result[0].ec_bufptr-result[0].ec_buf)
< max_size) {
CORD_ec_flush_buf(result);
}
buf = result[0].ec_bufptr;
}
switch(current) {
case 'd':
case 'i':
case 'o':
case 'u':
case 'x':
case 'X':
case 'c':
if (long_arg <= 0) {
(void) va_arg(args, int);
} else if (long_arg > 0) {
(void) va_arg(args, long);
}
break;
case 's':
case 'p':
(void) va_arg(args, char *);
break;
case 'f':
case 'e':
case 'E':
case 'g':
case 'G':
(void) va_arg(args, double);
break;
default:
return(-1);
}
res = vsprintf(buf, conv_spec, vsprintf_args);
len = (size_t)res;
if ((char *)(GC_word)res == buf) {
/* old style vsprintf */
len = strlen(buf);
} else if (res < 0) {
return(-1);
}
if (buf != result[0].ec_bufptr) {
register char c;
while (c = *buf++) {
CORD_ec_append(result, c);
}
} else {
result[0].ec_bufptr = buf + len;
}
}
done:;
}
} else {
CORD_ec_append(result, current);
}
}
count = ec_len(result);
*out = CORD_balance(CORD_ec_to_cord(result));
return(count);
}
int CORD_sprintf(CORD * out, CORD format, ...)
{
va_list args;
int result;
va_start(args, format);
result = CORD_vsprintf(out, format, args);
va_end(args);
return(result);
}
int CORD_fprintf(FILE * f, CORD format, ...)
{
va_list args;
int result;
CORD out;
va_start(args, format);
result = CORD_vsprintf(&out, format, args);
va_end(args);
if (result > 0) CORD_put(out, f);
return(result);
}
int CORD_vfprintf(FILE * f, CORD format, va_list args)
{
int result;
CORD out;
result = CORD_vsprintf(&out, format, args);
if (result > 0) CORD_put(out, f);
return(result);
}
int CORD_printf(CORD format, ...)
{
va_list args;
int result;
CORD out;
va_start(args, format);
result = CORD_vsprintf(&out, format, args);
va_end(args);
if (result > 0) CORD_put(out, stdout);
return(result);
}
int CORD_vprintf(CORD format, va_list args)
{
int result;
CORD out;
result = CORD_vsprintf(&out, format, args);
if (result > 0) CORD_put(out, stdout);
return(result);
}