Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Sep 1996 14:35:55 -0700 (PDT)
From:      Mark Diekhans <markd@Grizzly.COM>
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/1597: No support for positional parameters in *printf functions
Message-ID:  <199609102135.OAA09937@osprey.grizzly.com>
Resent-Message-ID: <199609102140.OAA16605@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         1597
>Category:       bin
>Synopsis:       No support for positional parameters in *printf functions
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 10 14:40:02 PDT 1996
>Last-Modified:
>Originator:     Mark Diekhans
>Organization:
== Mark Diekhans <markd@grizzly.com> ==
>Release:        FreeBSD 2.2-960801-SNAP i386
>Environment:

>Description:

   FreeBSD lacks support for XPG/3 style positional arguments in the *printf
family of functions (e.g. %2$s).  This functionality is available on most
modern Unix systems and in GNU libc.  Its fairly essential in developing
XPG/3 style localized software (FreeBSD has XPG/3 catopen, etc).


>How-To-Repeat:


>Fix:

The following patch to lib/libc/stdio implements positional arguments in
a manner consistent with other implementations.  Its done in a way that 
adds only a tiny amount of overhead when positional arguments are not used.
I also have a test program to go with this, but don't know where it belongs
in the tree.

*** printf.3.ORG	Sun Sep  8 13:56:14 1996
--- printf.3	Sun Sep  8 15:15:18 1996
***************
*** 176,181 ****
--- 176,191 ----
  the following appear in sequence:
  .Bl -bullet
  .It
+ An optional field, consisting of a decimal digit string followed by a
+ .Cm $ ,
+ specifying the next argument to access .
+ If this field is not provided, the argument following the last
+ argument accessed will be used.
+ Arguments are numbered starting at
+ .Cm 1 .
+ If unaccessed arguments in the format string are interspersed with ones that
+ are accessed the results will be indeterminate.
+ .It
  Zero or more of the following flags:
  .Bl -hyphen
  .It
***************
*** 394,399 ****
--- 404,411 ----
  A field width or precision, or both, may be indicated by
  an asterisk
  .Ql *
+ or an asterisk followed by one or more decimal digits and a
+ .Ql $
  instead of a
  digit string.
  In this case, an
***************
*** 402,407 ****
--- 414,421 ----
  A negative field width is treated as a left adjustment flag followed by a
  positive field width; a negative precision is treated as though it were
  missing.
+ If a single format directive mixes positional (nn$)
+ and non-positional arguments, the results are undefined.
  .Pp
  The conversion specifiers and their meanings are:
  .Bl -tag -width "diouxX"
*** vfprintf.c.ORG	Sat Sep  7 19:47:59 1996
--- vfprintf.c	Sun Sep  8 16:16:35 1996
***************
*** 75,80 ****
--- 75,82 ----
  static int	__sbprintf __P((FILE *, const char *, va_list));
  static char *	__ultoa __P((u_long, char *, int, int, char *));
  static char *	__uqtoa __P((u_quad_t, char *, int, int, char *));
+ static void	__find_arguments __P((const char *, va_list, void ***));
+ static void	__grow_type_table __P((int, unsigned char **, int *));
  
  /*
   * Flush out all the vectors defined by the given uio,
***************
*** 274,279 ****
--- 276,282 ----
  
  #endif /* FLOATING_POINT */
  
+ #define STATIC_ARG_TBL_SIZE 8           /* Size of static argument table. */
  
  /*
   * Flags used during conversion.
***************
*** 295,301 ****
  {
  	register char *fmt;	/* format string */
  	register int ch;	/* character from fmt */
! 	register int n;		/* handy integer (short term usage) */
  	register char *cp;	/* handy char pointer (short term usage) */
  	register struct __siov *iovp;/* for PRINT macro */
  	register int flags;	/* flags as above */
--- 298,304 ----
  {
  	register char *fmt;	/* format string */
  	register int ch;	/* character from fmt */
! 	register int n, n2;	/* handy integer (short term usage) */
  	register char *cp;	/* handy char pointer (short term usage) */
  	register struct __siov *iovp;/* for PRINT macro */
  	register int flags;	/* flags as above */
***************
*** 323,328 ****
--- 326,335 ----
  	struct __siov iov[NIOV];/* ... and individual io vectors */
  	char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
  	char ox[2];		/* space for 0x hex-prefix */
+         void **argtable;        /* args, built due to positional arg */
+         void *statargtable [STATIC_ARG_TBL_SIZE];
+         int nextarg;            /* 1-based argument index */
+         va_list orgap;          /* original argument pointer */
  
  	/*
  	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
***************
*** 365,382 ****
  	iovp = iov; \
  }
  
  	/*
  	 * To extend shorts properly, we need both signed and unsigned
  	 * argument extraction methods.
  	 */
  #define	SARG() \
! 	(flags&LONGINT ? va_arg(ap, long) : \
! 	    flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
! 	    (long)va_arg(ap, int))
  #define	UARG() \
! 	(flags&LONGINT ? va_arg(ap, u_long) : \
! 	    flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
! 	    (u_long)va_arg(ap, u_int))
  
  #ifdef _THREAD_SAFE
  	_thread_flockfile(fp,__FILE__,__LINE__);
--- 372,424 ----
  	iovp = iov; \
  }
  
+         /*
+          * Get the argument indexed by nextarg.   If the argument table is
+          * built, use it to get the argument.  If its not, get the next
+          * argument (and arguments must be gotten sequentially).
+          */
+ #define GETARG(type) \
+         ((argtable != NULL) ? *((type*)(argtable[nextarg++])) : \
+             (nextarg++, va_arg(ap, type)))
+ 
  	/*
  	 * To extend shorts properly, we need both signed and unsigned
  	 * argument extraction methods.
  	 */
  #define	SARG() \
! 	(flags&LONGINT ? GETARG(long) : \
! 	    flags&SHORTINT ? (long)(short)GETARG(int) : \
! 	    (long)GETARG(int))
  #define	UARG() \
! 	(flags&LONGINT ? GETARG(u_long) : \
! 	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
! 	    (u_long)GETARG(u_int))
! 
!         /*
!          * Get * arguments, including the form *nn$.  Preserve the nextarg
!          * that the argument can be gotten once the type is determined.
!          */
! #define GETASTER(val) \
!         n2 = 0; \
!         cp = fmt; \
!         while (is_digit(*cp)) { \
!                 n2 = 10 * n2 + to_digit(*cp); \
!                 cp++; \
!         } \
!         if (*cp == '$') { \
!             	int hold = nextarg; \
!                 if (argtable == NULL) { \
!                         argtable = statargtable; \
!                         __find_arguments (fmt0, orgap, &argtable); \
!                 } \
!                 nextarg = n2; \
!                 val = GETARG (int); \
!                 nextarg = hold; \
!                 fmt = ++cp; \
!         } else { \
! 		val = GETARG (int); \
!         }
!         
  
  #ifdef _THREAD_SAFE
  	_thread_flockfile(fp,__FILE__,__LINE__);
***************
*** 399,404 ****
--- 441,449 ----
  	}
  
  	fmt = (char *)fmt0;
+         argtable = NULL;
+         nextarg = 1;
+         orgap = ap;
  	uio.uio_iov = iovp = iov;
  	uio.uio_resid = 0;
  	uio.uio_iovcnt = 0;
***************
*** 445,451 ****
  			 *	-- ANSI X3J11
  			 * They don't exclude field widths read from args.
  			 */
! 			if ((width = va_arg(ap, int)) >= 0)
  				goto rflag;
  			width = -width;
  			/* FALLTHROUGH */
--- 490,497 ----
  			 *	-- ANSI X3J11
  			 * They don't exclude field widths read from args.
  			 */
! 			GETASTER (width);
! 			if (width >= 0)
  				goto rflag;
  			width = -width;
  			/* FALLTHROUGH */
***************
*** 457,463 ****
  			goto rflag;
  		case '.':
  			if ((ch = *fmt++) == '*') {
! 				n = va_arg(ap, int);
  				prec = n < 0 ? -1 : n;
  				goto rflag;
  			}
--- 503,509 ----
  			goto rflag;
  		case '.':
  			if ((ch = *fmt++) == '*') {
! 				GETASTER (n);
  				prec = n < 0 ? -1 : n;
  				goto rflag;
  			}
***************
*** 483,488 ****
--- 529,543 ----
  				n = 10 * n + to_digit(ch);
  				ch = *fmt++;
  			} while (is_digit(ch));
+ 			if (ch == '$') {
+ 				nextarg = n;
+                         	if (argtable == NULL) {
+                                 	argtable = statargtable;
+                                 	__find_arguments (fmt0, orgap,
+ 						&argtable);
+ 				}
+ 				goto rflag;
+                         }
  			width = n;
  			goto reswitch;
  #ifdef FLOATING_POINT
***************
*** 500,506 ****
  			flags |= QUADINT;
  			goto rflag;
  		case 'c':
! 			*(cp = buf) = va_arg(ap, int);
  			size = 1;
  			sign = '\0';
  			break;
--- 555,561 ----
  			flags |= QUADINT;
  			goto rflag;
  		case 'c':
! 			*(cp = buf) = GETARG(int);
  			size = 1;
  			sign = '\0';
  			break;
***************
*** 510,516 ****
  		case 'd':
  		case 'i':
  			if (flags & QUADINT) {
! 				uqval = va_arg(ap, quad_t);
  				if ((quad_t)uqval < 0) {
  					uqval = -uqval;
  					sign = '-';
--- 565,571 ----
  		case 'd':
  		case 'i':
  			if (flags & QUADINT) {
! 				uqval = GETARG(quad_t);
  				if ((quad_t)uqval < 0) {
  					uqval = -uqval;
  					sign = '-';
***************
*** 536,544 ****
  fp_begin:		if (prec == -1)
  				prec = DEFPREC;
  			if (flags & LONGDBL)
! 				_double = (double)va_arg(ap, long double);
  			else
! 				_double = va_arg(ap, double);
  			/* do this before tricky precision changes */
  			if (isinf(_double)) {
  				if (_double < 0)
--- 591,599 ----
  fp_begin:		if (prec == -1)
  				prec = DEFPREC;
  			if (flags & LONGDBL)
! 				_double = (double)GETARG(long double);
  			else
! 				_double = GETARG(double);
  			/* do this before tricky precision changes */
  			if (isinf(_double)) {
  				if (_double < 0)
***************
*** 588,607 ****
  #endif /* FLOATING_POINT */
  		case 'n':
  			if (flags & QUADINT)
! 				*va_arg(ap, quad_t *) = ret;
  			else if (flags & LONGINT)
! 				*va_arg(ap, long *) = ret;
  			else if (flags & SHORTINT)
! 				*va_arg(ap, short *) = ret;
  			else
! 				*va_arg(ap, int *) = ret;
  			continue;	/* no output */
  		case 'O':
  			flags |= LONGINT;
  			/*FALLTHROUGH*/
  		case 'o':
  			if (flags & QUADINT)
! 				uqval = va_arg(ap, u_quad_t);
  			else
  				ulval = UARG();
  			base = 8;
--- 643,662 ----
  #endif /* FLOATING_POINT */
  		case 'n':
  			if (flags & QUADINT)
! 				*GETARG(quad_t *) = ret;
  			else if (flags & LONGINT)
! 				*GETARG(long *) = ret;
  			else if (flags & SHORTINT)
! 				*GETARG(short *) = ret;
  			else
! 				*GETARG(int *) = ret;
  			continue;	/* no output */
  		case 'O':
  			flags |= LONGINT;
  			/*FALLTHROUGH*/
  		case 'o':
  			if (flags & QUADINT)
! 				uqval = GETARG(u_quad_t);
  			else
  				ulval = UARG();
  			base = 8;
***************
*** 614,627 ****
  			 * defined manner.''
  			 *	-- ANSI X3J11
  			 */
! 			ulval = (u_long)va_arg(ap, void *);
  			base = 16;
  			xdigs = "0123456789abcdef";
  			flags = (flags & ~QUADINT) | HEXPREFIX;
  			ch = 'x';
  			goto nosign;
  		case 's':
! 			if ((cp = va_arg(ap, char *)) == NULL)
  				cp = "(null)";
  			if (prec >= 0) {
  				/*
--- 669,682 ----
  			 * defined manner.''
  			 *	-- ANSI X3J11
  			 */
! 			ulval = (u_long)GETARG(void *);
  			base = 16;
  			xdigs = "0123456789abcdef";
  			flags = (flags & ~QUADINT) | HEXPREFIX;
  			ch = 'x';
  			goto nosign;
  		case 's':
! 			if ((cp = GETARG(char *)) == NULL)
  				cp = "(null)";
  			if (prec >= 0) {
  				/*
***************
*** 646,652 ****
  			/*FALLTHROUGH*/
  		case 'u':
  			if (flags & QUADINT)
! 				uqval = va_arg(ap, u_quad_t);
  			else
  				ulval = UARG();
  			base = 10;
--- 701,707 ----
  			/*FALLTHROUGH*/
  		case 'u':
  			if (flags & QUADINT)
! 				uqval = GETARG(u_quad_t);
  			else
  				ulval = UARG();
  			base = 10;
***************
*** 657,663 ****
  		case 'x':
  			xdigs = "0123456789abcdef";
  hex:			if (flags & QUADINT)
! 				uqval = va_arg(ap, u_quad_t);
  			else
  				ulval = UARG();
  			base = 16;
--- 712,718 ----
  		case 'x':
  			xdigs = "0123456789abcdef";
  hex:			if (flags & QUADINT)
! 				uqval = GETARG(u_quad_t);
  			else
  				ulval = UARG();
  			base = 16;
***************
*** 809,817 ****
--- 864,1195 ----
  #ifdef _THREAD_SAFE
  	_thread_funlockfile(fp);
  #endif
+         if ((argtable != NULL) && (argtable != statargtable))
+                 free (argtable);
  	return (ret);
  	/* NOTREACHED */
  }
+ 
+ /*
+  * Type ids for argument type table.
+  */
+ #define T_UNUSED	0
+ #define T_SHORT		1
+ #define T_U_SHORT	2
+ #define TP_SHORT	3
+ #define T_INT		4
+ #define T_U_INT		5
+ #define TP_INT		6
+ #define T_LONG		7
+ #define T_U_LONG	8
+ #define TP_LONG		9
+ #define T_QUAD		10
+ #define T_U_QUAD	11
+ #define TP_QUAD		12
+ #define T_DOUBLE	13
+ #define T_LONG_DOUBLE	14
+ #define TP_CHAR		15
+ #define TP_VOID		16
+ 
+ /*
+  * Find all arguments when a positional parameter is encountered.  Returns a
+  * table, indexed by argument number, of pointers to each arguments.  The
+  * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+  * It will be replaces with a malloc-ed on if it overflows.
+  */ 
+ static void
+ __find_arguments (fmt0, ap, argtable)
+ 	const char *fmt0;
+ 	va_list ap;
+ 	void ***argtable;
+ {
+ 	register char *fmt;	/* format string */
+ 	register int ch;	/* character from fmt */
+ 	register int n, n2;	/* handy integer (short term usage) */
+ 	register char *cp;	/* handy char pointer (short term usage) */
+ 	register int flags;	/* flags as above */
+ 	int width;		/* width from format (%8d), or 0 */
+ 	unsigned char *typetable; /* table of types */
+ 	unsigned char stattypetable [STATIC_ARG_TBL_SIZE];
+ 	int tablesize;		/* current size of type table */
+ 	int tablemax;		/* largest used index in table */
+ 	int nextarg;		/* 1-based argument index */
+ 
+ 	/*
+ 	 * Add an argument type to the table, expanding if necessary.
+ 	 */
+ #define ADDTYPE(type) \
+ 	((nextarg >= tablesize) ? \
+ 		__grow_type_table(nextarg, &typetable, &tablesize) : 0, \
+ 	typetable[nextarg++] = type, \
+ 	(nextarg > tablemax) ? tablemax = nextarg : 0)
+ 
+ #define	ADDSARG() \
+ 	((flags&LONGINT) ? ADDTYPE(T_LONG) : \
+ 		((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
+ 
+ #define	ADDUARG() \
+ 	((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
+ 		((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
+ 
+ 	/*
+ 	 * Add * arguments to the type array.
+ 	 */
+ #define ADDASTER() \
+ 	n2 = 0; \
+ 	cp = fmt; \
+ 	while (is_digit(*cp)) { \
+ 		n2 = 10 * n2 + to_digit(*cp); \
+ 		cp++; \
+ 	} \
+ 	if (*cp == '$') { \
+ 		int hold = nextarg; \
+ 		nextarg = n2; \
+ 		ADDTYPE (T_INT); \
+ 		nextarg = hold; \
+ 		fmt = ++cp; \
+ 	} else { \
+ 		ADDTYPE (T_INT); \
+ 	}
+ 	fmt = (char *)fmt0;
+ 	typetable = stattypetable;
+ 	tablesize = STATIC_ARG_TBL_SIZE;
+ 	tablemax = 0; 
+ 	nextarg = 1;
+ 	memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
+ 
+ 	/*
+ 	 * Scan the format for conversions (`%' character).
+ 	 */
+ 	for (;;) {
+ 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ 			/* void */;
+ 		if (ch == '\0')
+ 			goto done;
+ 		fmt++;		/* skip over '%' */
+ 
+ 		flags = 0;
+ 		width = 0;
+ 
+ rflag:		ch = *fmt++;
+ reswitch:	switch (ch) {
+ 		case ' ':
+ 		case '#':
+ 			goto rflag;
+ 		case '*':
+ 			ADDASTER ();
+ 			goto rflag;
+ 		case '-':
+ 		case '+':
+ 			goto rflag;
+ 		case '.':
+ 			if ((ch = *fmt++) == '*') {
+ 				ADDASTER ();
+ 				goto rflag;
+ 			}
+ 			while (is_digit(ch)) {
+ 				ch = *fmt++;
+ 			}
+ 			goto reswitch;
+ 		case '0':
+ 			goto rflag;
+ 		case '1': case '2': case '3': case '4':
+ 		case '5': case '6': case '7': case '8': case '9':
+ 			n = 0;
+ 			do {
+ 				n = 10 * n + to_digit(ch);
+ 				ch = *fmt++;
+ 			} while (is_digit(ch));
+ 			if (ch == '$') {
+ 				nextarg = n;
+ 				goto rflag;
+ 			}
+ 			width = n;
+ 			goto reswitch;
+ #ifdef FLOATING_POINT
+ 		case 'L':
+ 			flags |= LONGDBL;
+ 			goto rflag;
+ #endif
+ 		case 'h':
+ 			flags |= SHORTINT;
+ 			goto rflag;
+ 		case 'l':
+ 			flags |= LONGINT;
+ 			goto rflag;
+ 		case 'q':
+ 			flags |= QUADINT;
+ 			goto rflag;
+ 		case 'c':
+ 			ADDTYPE(T_INT);
+ 			break;
+ 		case 'D':
+ 			flags |= LONGINT;
+ 			/*FALLTHROUGH*/
+ 		case 'd':
+ 		case 'i':
+ 			if (flags & QUADINT) {
+ 				ADDTYPE(T_QUAD);
+ 			} else {
+ 				ADDSARG();
+ 			}
+ 			break;
+ #ifdef FLOATING_POINT
+ 		case 'e':
+ 		case 'E':
+ 		case 'f':
+ 		case 'g':
+ 		case 'G':
+ 			if (flags & LONGDBL)
+ 				ADDTYPE(T_LONG_DOUBLE);
+ 			else
+ 				ADDTYPE(T_DOUBLE);
+ 			break;
+ #endif /* FLOATING_POINT */
+ 		case 'n':
+ 			if (flags & QUADINT)
+ 				ADDTYPE(TP_QUAD);
+ 			else if (flags & LONGINT)
+ 				ADDTYPE(TP_LONG);
+ 			else if (flags & SHORTINT)
+ 				ADDTYPE(TP_SHORT);
+ 			else
+ 				ADDTYPE(TP_INT);
+ 			continue;	/* no output */
+ 		case 'O':
+ 			flags |= LONGINT;
+ 			/*FALLTHROUGH*/
+ 		case 'o':
+ 			if (flags & QUADINT)
+ 				ADDTYPE(T_U_QUAD);
+ 			else
+ 				ADDUARG();
+ 			break;
+ 		case 'p':
+ 			ADDTYPE(TP_VOID);
+ 			break;
+ 		case 's':
+ 			ADDTYPE(TP_CHAR);
+ 			break;
+ 		case 'U':
+ 			flags |= LONGINT;
+ 			/*FALLTHROUGH*/
+ 		case 'u':
+ 			if (flags & QUADINT)
+ 				ADDTYPE(T_U_QUAD);
+ 			else
+ 				ADDUARG();
+ 			break;
+ 		case 'X':
+ 		case 'x':
+ 			if (flags & QUADINT)
+ 				ADDTYPE(T_U_QUAD);
+ 			else
+ 				ADDUARG();
+ 			break;
+ 		default:	/* "%?" prints ?, unless ? is NUL */
+ 			if (ch == '\0')
+ 				goto done;
+ 			break;
+ 		}
+ 	}
+ done:
+ 	/*
+ 	 * Build the argument table.
+ 	 */
+ 	if (tablemax >= STATIC_ARG_TBL_SIZE) {
+ 		*argtable = (void **)
+ 		    malloc (sizeof (void *) * (tablemax + 1));
+ 	}
+ 
+ 	(*argtable) [0] = NULL;
+ 	for (n = 1; n <= tablemax; n++) {
+ 		(*argtable) [n] = ap;
+ 		switch (typetable [n]) {
+ 		    case T_UNUSED:
+ 			(void) va_arg (ap, int);
+ 			break;
+ 		    case T_SHORT:
+ 			(void) va_arg (ap, int);
+ 			break;
+ 		    case T_U_SHORT:
+ 			(void) va_arg (ap, int);
+ 			break;
+ 		    case TP_SHORT:
+ 			(void) va_arg (ap, short *);
+ 			break;
+ 		    case T_INT:
+ 			(void) va_arg (ap, int);
+ 			break;
+ 		    case T_U_INT:
+ 			(void) va_arg (ap, unsigned int);
+ 			break;
+ 		    case TP_INT:
+ 			(void) va_arg (ap, int *);
+ 			break;
+ 		    case T_LONG:
+ 			(void) va_arg (ap, long);
+ 			break;
+ 		    case T_U_LONG:
+ 			(void) va_arg (ap, unsigned long);
+ 			break;
+ 		    case TP_LONG:
+ 			(void) va_arg (ap, long *);
+ 			break;
+ 		    case T_QUAD:
+ 			(void) va_arg (ap, quad_t);
+ 			break;
+ 		    case T_U_QUAD:
+ 			(void) va_arg (ap, u_quad_t);
+ 			break;
+ 		    case TP_QUAD:
+ 			(void) va_arg (ap, quad_t *);
+ 			break;
+ 		    case T_DOUBLE:
+ 			(void) va_arg (ap, double);
+ 			break;
+ 		    case T_LONG_DOUBLE:
+ 			(void) va_arg (ap, long double);
+ 			break;
+ 		    case TP_CHAR:
+ 			(void) va_arg (ap, char *);
+ 			break;
+ 		    case TP_VOID:
+ 			(void) va_arg (ap, void *);
+ 			break;
+ 		}
+ 	}
+ 
+ 	if ((typetable != NULL) && (typetable != stattypetable))
+ 		free (typetable);
+ }
+ 
+ /*
+  * Increase the size of the type table.
+  */
+ static void
+ __grow_type_table (nextarg, typetable, tablesize)
+ 	int nextarg;
+ 	unsigned char **typetable;
+ 	int *tablesize;
+ {
+ 	unsigned char *oldtable = *typetable;
+ 	int newsize = *tablesize * 2;
+ 
+ 	if (*tablesize == STATIC_ARG_TBL_SIZE) {
+ 		*typetable = (unsigned char *)
+ 		    malloc (sizeof (unsigned char) * newsize);
+ 		bcopy (oldtable, *typetable, *tablesize);
+ 	} else {
+ 		*typetable = (unsigned char *)
+ 		    realloc (typetable, sizeof (unsigned char) * newsize);
+ 
+ 	}
+ 	memset (&typetable [*tablesize], T_UNUSED, (newsize - *tablesize));
+ 
+ 	*tablesize = newsize;
+ }
+ 
  
  #ifdef FLOATING_POINT
  
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199609102135.OAA09937>