Home | History | Annotate | Line # | Download | only in libterminfo
tparm.c revision 1.10
      1  1.10      roy /* $NetBSD: tparm.c,v 1.10 2013/01/23 13:06:18 roy Exp $ */
      2   1.1      roy 
      3   1.1      roy /*
      4   1.5      roy  * Copyright (c) 2009, 2011 The NetBSD Foundation, Inc.
      5   1.1      roy  *
      6   1.1      roy  * This code is derived from software contributed to The NetBSD Foundation
      7   1.1      roy  * by Roy Marples.
      8   1.1      roy  *
      9   1.1      roy  * Redistribution and use in source and binary forms, with or without
     10   1.1      roy  * modification, are permitted provided that the following conditions
     11   1.1      roy  * are met:
     12   1.1      roy  * 1. Redistributions of source code must retain the above copyright
     13   1.1      roy  *    notice, this list of conditions and the following disclaimer.
     14   1.1      roy  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1      roy  *    notice, this list of conditions and the following disclaimer in the
     16   1.1      roy  *    documentation and/or other materials provided with the distribution.
     17   1.1      roy  *
     18   1.1      roy  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19   1.1      roy  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20   1.1      roy  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21   1.1      roy  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22   1.1      roy  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23   1.1      roy  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24   1.1      roy  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25   1.1      roy  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26   1.1      roy  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27   1.1      roy  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28   1.1      roy  */
     29   1.1      roy 
     30   1.1      roy #include <sys/cdefs.h>
     31  1.10      roy __RCSID("$NetBSD: tparm.c,v 1.10 2013/01/23 13:06:18 roy Exp $");
     32   1.8      roy #include <sys/param.h>
     33   1.1      roy 
     34   1.1      roy #include <assert.h>
     35   1.1      roy #include <ctype.h>
     36   1.1      roy #include <errno.h>
     37   1.1      roy #include <stdarg.h>
     38   1.1      roy #include <stdio.h>
     39   1.1      roy #include <stdlib.h>
     40   1.1      roy #include <string.h>
     41   1.1      roy #include <term_private.h>
     42   1.1      roy #include <term.h>
     43   1.1      roy 
     44   1.1      roy static TERMINAL *dumbterm; /* For non thread safe functions */
     45   1.1      roy 
     46   1.2      roy typedef struct {
     47   1.7      roy 	int nums[20];
     48   1.1      roy 	char *strings[20];
     49   1.1      roy 	size_t offset;
     50   1.1      roy } TPSTACK;
     51   1.1      roy 
     52   1.2      roy typedef struct {
     53   1.7      roy 	int num;
     54   1.1      roy 	char *string;
     55   1.1      roy } TPVAR;
     56   1.1      roy 
     57   1.1      roy static int
     58   1.7      roy push(int num, char *string, TPSTACK *stack)
     59   1.1      roy {
     60   1.9  msaitoh 	if (stack->offset >= sizeof(stack->nums)) {
     61   1.1      roy 		errno = E2BIG;
     62   1.1      roy 		return -1;
     63   1.1      roy 	}
     64   1.1      roy 	stack->nums[stack->offset] = num;
     65   1.1      roy 	stack->strings[stack->offset] = string;
     66   1.1      roy 	stack->offset++;
     67   1.1      roy 	return 0;
     68   1.1      roy }
     69   1.1      roy 
     70   1.1      roy static int
     71   1.7      roy pop(int *num, char **string, TPSTACK *stack)
     72   1.1      roy {
     73   1.1      roy 	if (stack->offset == 0) {
     74   1.5      roy 		if (num)
     75   1.5      roy 			*num = 0;
     76   1.5      roy 		if (string)
     77   1.5      roy 			*string = NULL;
     78   1.1      roy 		errno = E2BIG;
     79   1.1      roy 		return -1;
     80   1.1      roy 	}
     81   1.1      roy 	stack->offset--;
     82   1.1      roy 	if (num)
     83   1.1      roy 		*num = stack->nums[stack->offset];
     84   1.1      roy 	if (string)
     85   1.1      roy 		*string = stack->strings[stack->offset];
     86   1.1      roy 	return 0;
     87   1.1      roy }
     88   1.1      roy 
     89   1.1      roy static char *
     90   1.1      roy checkbuf(TERMINAL *term, size_t len)
     91   1.1      roy {
     92   1.1      roy 	char *buf;
     93   1.1      roy 
     94   1.1      roy 	if (term->_bufpos + len >= term->_buflen) {
     95   1.8      roy 		len = term->_buflen + MAX(len, BUFSIZ);
     96   1.1      roy 		buf = realloc(term->_buf, len);
     97   1.1      roy 		if (buf == NULL)
     98   1.8      roy 			return NULL;
     99   1.1      roy 		term->_buf = buf;
    100   1.1      roy 		term->_buflen = len;
    101   1.1      roy 	}
    102   1.1      roy 	return term->_buf;
    103   1.1      roy }
    104   1.1      roy 
    105   1.1      roy static size_t
    106   1.1      roy ochar(TERMINAL *term, int c)
    107   1.1      roy {
    108   1.1      roy 	if (c == 0)
    109   1.1      roy 		c = 0200;
    110   1.1      roy 	/* Check we have space and a terminator */
    111   1.1      roy 	if (checkbuf(term, 2) == NULL)
    112   1.1      roy 		return 0;
    113   1.1      roy 	term->_buf[term->_bufpos++] = (char)c;
    114   1.1      roy 	return 1;
    115   1.1      roy }
    116   1.1      roy 
    117   1.1      roy static size_t
    118   1.7      roy onum(TERMINAL *term, const char *fmt, int num, int len)
    119   1.1      roy {
    120   1.1      roy 	size_t l;
    121   1.1      roy 
    122   1.1      roy 	/* Assume we never have natural number longer than 64 chars */
    123   1.1      roy 	if (len < 64)
    124   1.1      roy 		len = 64;
    125   1.1      roy 	if (checkbuf(term, (size_t)len + 1) == NULL)
    126   1.1      roy 		return 0;
    127   1.1      roy 	l = sprintf(term->_buf + term->_bufpos, fmt, num);
    128   1.1      roy 	term->_bufpos += l;
    129   1.1      roy 	return l;
    130   1.1      roy }
    131   1.1      roy 
    132   1.1      roy static char *
    133   1.6      roy _ti_tiparm(TERMINAL *term, const char *str, va_list parms)
    134   1.1      roy {
    135   1.1      roy 	const char *sp;
    136   1.1      roy 	char c, fmt[64], *fp, *ostr;
    137   1.7      roy 	int val, val2;
    138   1.7      roy 	int dnums[26]; /* dynamic variables a-z, not preserved */
    139   1.1      roy 	size_t l, max;
    140   1.1      roy 	TPSTACK stack;
    141   1.1      roy 	TPVAR params[9];
    142   1.1      roy 	int done, dot, minus, width, precision, olen;
    143   1.1      roy 	int piss[9]; /* Parameter IS String - piss ;) */
    144   1.1      roy 
    145   1.1      roy 	if (str == NULL)
    146   1.1      roy 		return NULL;
    147   1.1      roy 
    148   1.1      roy 	/*
    149   1.1      roy 	  If not passed a terminal, malloc a dummy one.
    150   1.1      roy 	  This means we can preserve buffers and variables per terminal and
    151   1.1      roy 	  still work with non thread safe functions (which sadly are still the
    152   1.1      roy 	  norm and standard).
    153   1.1      roy 	*/
    154   1.7      roy 
    155   1.1      roy 	if (term == NULL) {
    156   1.1      roy 		if (dumbterm == NULL) {
    157   1.1      roy 			dumbterm = malloc(sizeof(*dumbterm));
    158   1.1      roy 			if (dumbterm == NULL)
    159   1.1      roy 				return NULL;
    160   1.1      roy 			dumbterm->_buflen = 0;
    161   1.1      roy 		}
    162   1.1      roy 		term = dumbterm;
    163   1.1      roy 	}
    164   1.1      roy 
    165   1.1      roy 	term->_bufpos = 0;
    166   1.1      roy 	/* Ensure we have an initial buffer */
    167   1.1      roy 	if (term->_buflen == 0) {
    168   1.1      roy 		term->_buf = malloc(BUFSIZ);
    169   1.1      roy 		if (term->_buf == NULL)
    170   1.1      roy 			return NULL;
    171   1.1      roy 		term->_buflen = BUFSIZ;
    172   1.1      roy 	}
    173   1.1      roy 
    174   1.1      roy 	/*
    175   1.1      roy 	  Make a first pass through the string so we can work out
    176   1.7      roy 	  which parameters are ints and which are char *.
    177   1.1      roy 	  Basically we only use char * if %p[1-9] is followed by %l or %s.
    178   1.1      roy 	*/
    179   1.1      roy 	memset(&piss, 0, sizeof(piss));
    180   1.1      roy 	max = 0;
    181   1.1      roy 	sp = str;
    182   1.1      roy 	while ((c = *sp++) != '\0') {
    183   1.1      roy 		if (c != '%')
    184   1.1      roy 			continue;
    185   1.1      roy 		c = *sp++;
    186   1.1      roy 		if (c == '\0')
    187   1.1      roy 			break;
    188   1.1      roy 		if (c != 'p')
    189   1.1      roy 			continue;
    190   1.1      roy 		c = *sp++;
    191   1.1      roy 		if (c < '1' || c > '9') {
    192   1.1      roy 			errno = EINVAL;
    193   1.5      roy 			continue;
    194   1.1      roy 		}
    195   1.1      roy 		l = c - '0';
    196   1.1      roy 		if (l > max)
    197   1.1      roy 			max = l;
    198   1.1      roy 		if (*sp != '%')
    199   1.1      roy 			continue;
    200   1.1      roy 		/* Skip formatting */
    201   1.1      roy 		sp++;
    202   1.1      roy 		while (*sp == '.' || *sp == '#' || *sp == ' ' || *sp == ':' ||
    203   1.1      roy 		    *sp == '-' || isdigit((unsigned char)*sp))
    204   1.1      roy 			sp++;
    205   1.1      roy 		if (*sp == 'l' || *sp == 's')
    206   1.1      roy 			piss[l - 1] = 1;
    207   1.1      roy 	}
    208   1.1      roy 
    209   1.1      roy 	/* Put our parameters into variables */
    210   1.1      roy 	memset(&params, 0, sizeof(params));
    211   1.1      roy 	for (l = 0; l < max; l++) {
    212   1.1      roy 		if (piss[l] == 0)
    213   1.6      roy 			params[l].num = va_arg(parms, int);
    214   1.1      roy 		else
    215   1.1      roy 			params[l].string = va_arg(parms, char *);
    216   1.1      roy 	}
    217   1.1      roy 
    218   1.1      roy 	term->_bufpos = 0;
    219   1.1      roy 	memset(&stack, 0, sizeof(stack));
    220   1.1      roy 	while ((c = *str++) != '\0') {
    221   1.1      roy 		if (c != '%' || (c = *str++) == '%') {
    222   1.1      roy 			if (c == '\0')
    223   1.1      roy 				break;
    224   1.1      roy 			if (ochar(term, c) == 0)
    225   1.1      roy 				return NULL;
    226   1.1      roy 			continue;
    227   1.1      roy 		}
    228   1.1      roy 
    229   1.1      roy 		/* Handle formatting. */
    230   1.1      roy 		fp = fmt;
    231   1.1      roy 		*fp++ = '%';
    232   1.1      roy 		done = dot = minus = width = precision = 0;
    233   1.1      roy 		val = 0;
    234   1.1      roy 		while (done == 0 && (size_t)(fp - fmt) < sizeof(fmt)) {
    235   1.1      roy 			switch (c) {
    236   1.1      roy 			case 'c': /* FALLTHROUGH */
    237   1.1      roy 			case 'd': /* FALLTHROUGH */
    238   1.1      roy 			case 'o': /* FALLTHROUGH */
    239   1.1      roy 			case 'x': /* FALLTHROUGH */
    240   1.1      roy 			case 'X': /* FALLTHROUGH */
    241   1.1      roy 			case 's':
    242   1.1      roy 				*fp++ = c;
    243   1.1      roy 				done = 1;
    244   1.1      roy 				break;
    245   1.1      roy 			case '#': /* FALLTHROUGH */
    246   1.1      roy 			case ' ':
    247   1.1      roy 				*fp++ = c;
    248   1.1      roy 				break;
    249   1.1      roy 			case '.':
    250   1.1      roy 				*fp++ = c;
    251   1.1      roy 				if (dot == 0) {
    252   1.1      roy 					dot = 1;
    253   1.1      roy 					width = val;
    254   1.1      roy 				} else
    255   1.1      roy 					done = 2;
    256   1.1      roy 				val = 0;
    257   1.1      roy 				break;
    258   1.1      roy 			case ':':
    259   1.1      roy 				minus = 1;
    260   1.1      roy 				break;
    261   1.1      roy 			case '-':
    262   1.1      roy 				if (minus)
    263   1.1      roy 					*fp++ = c;
    264   1.1      roy 				else
    265   1.1      roy 					done = 1;
    266   1.1      roy 				break;
    267   1.1      roy 			default:
    268   1.1      roy 				if (isdigit((unsigned char)c)) {
    269   1.1      roy 					val = (val * 10) + (c - '0');
    270   1.1      roy 					if (val > 10000)
    271   1.1      roy 						done = 2;
    272   1.1      roy 					else
    273   1.1      roy 						*fp++ = c;
    274   1.1      roy 				} else
    275   1.1      roy 					done = 1;
    276   1.1      roy 			}
    277   1.1      roy 			if (done == 0)
    278   1.1      roy 				c = *str++;
    279   1.1      roy 		}
    280   1.1      roy 		if (done == 2) {
    281   1.1      roy 			/* Found an error in the format */
    282   1.1      roy 			fp = fmt + 1;
    283   1.1      roy 			*fp = *str;
    284   1.1      roy 			olen = 0;
    285   1.1      roy 		} else {
    286   1.1      roy 			if (dot == 0)
    287   1.1      roy 				width = val;
    288   1.1      roy 			else
    289   1.1      roy 				precision = val;
    290   1.1      roy 			olen = (width > precision) ? width : precision;
    291   1.1      roy 		}
    292   1.1      roy 		*fp++ = '\0';
    293   1.1      roy 
    294   1.1      roy 		/* Handle commands */
    295   1.1      roy 		switch (c) {
    296   1.1      roy 		case 'c':
    297   1.5      roy 			pop(&val, NULL, &stack);
    298   1.1      roy 			if (ochar(term, (unsigned char)val) == 0)
    299   1.1      roy 				return NULL;
    300   1.1      roy 			break;
    301   1.1      roy 		case 's':
    302   1.5      roy 			pop(NULL, &ostr, &stack);
    303   1.1      roy 			if (ostr != NULL) {
    304   1.1      roy 				l = strlen(ostr);
    305   1.1      roy 				if (l < (size_t)olen)
    306   1.1      roy 					l = olen;
    307   1.1      roy 				if (checkbuf(term, (size_t)(l + 1)) == NULL)
    308   1.1      roy 					return NULL;
    309   1.1      roy 				l = sprintf(term->_buf + term->_bufpos,
    310   1.1      roy 				    fmt, ostr);
    311   1.1      roy 				term->_bufpos += l;
    312   1.1      roy 			}
    313   1.1      roy 			break;
    314   1.1      roy 		case 'l':
    315   1.5      roy 			pop(NULL, &ostr, &stack);
    316   1.1      roy 			if (ostr == NULL)
    317   1.1      roy 				l = 0;
    318   1.1      roy 			else
    319   1.1      roy 				l = strlen(ostr);
    320   1.7      roy 			if (onum(term, "%d", (int)l, 0) == 0)
    321   1.1      roy 				return NULL;
    322   1.1      roy 			break;
    323   1.1      roy 		case 'd': /* FALLTHROUGH */
    324   1.1      roy 		case 'o': /* FALLTHROUGH */
    325   1.1      roy 		case 'x': /* FALLTHROUGH */
    326   1.1      roy 		case 'X':
    327   1.5      roy 			pop(&val, NULL, &stack);
    328   1.1      roy 			if (onum(term, fmt, val, olen) == 0)
    329   1.1      roy 				return NULL;
    330   1.1      roy 			break;
    331   1.1      roy 		case 'p':
    332   1.5      roy 			if (*str < '1' || *str > '9')
    333   1.5      roy 				break;
    334   1.1      roy 			l = *str++ - '1';
    335   1.1      roy 			if (push(params[l].num, params[l].string, &stack))
    336   1.1      roy 				return NULL;
    337   1.1      roy 			break;
    338   1.1      roy 		case 'P':
    339   1.5      roy 			pop(&val, NULL, &stack);
    340   1.1      roy 			if (*str >= 'a' && *str <= 'z')
    341   1.1      roy 				dnums[*str - 'a'] = val;
    342   1.1      roy 			else if (*str >= 'A' && *str <= 'Z')
    343   1.1      roy 				term->_snums[*str - 'A'] = val;
    344   1.1      roy 			break;
    345   1.1      roy 		case 'g':
    346   1.1      roy 			if (*str >= 'a' && *str <= 'z') {
    347   1.1      roy 				if (push(dnums[*str - 'a'], NULL, &stack))
    348   1.1      roy 					return NULL;
    349   1.1      roy 			} else if (*str >= 'A' && *str <= 'Z') {
    350   1.1      roy 				if (push(term->_snums[*str - 'A'],
    351   1.1      roy 					NULL, &stack))
    352   1.1      roy 					return NULL;
    353   1.1      roy 			}
    354   1.1      roy 			break;
    355   1.1      roy 		case 'i':
    356   1.1      roy 			if (piss[0] == 0)
    357   1.1      roy 				params[0].num++;
    358   1.1      roy 			if (piss[1] == 0)
    359   1.1      roy 				params[1].num++;
    360   1.1      roy 			break;
    361   1.1      roy 		case '\'':
    362   1.7      roy 			if (push((int)(unsigned char)*str++, NULL, &stack))
    363   1.1      roy 				return NULL;
    364   1.1      roy 			while (*str != '\0' && *str != '\'')
    365   1.1      roy 				str++;
    366   1.1      roy 			if (*str == '\'')
    367   1.1      roy 				str++;
    368   1.1      roy 			break;
    369   1.1      roy 		case '{':
    370   1.1      roy 			val = 0;
    371   1.3      roy 			for (; isdigit((unsigned char)*str);  str++)
    372   1.1      roy 				val = (val * 10) + (*str - '0');
    373   1.1      roy 			if (push(val, NULL, &stack))
    374   1.1      roy 				return NULL;
    375   1.1      roy 			while (*str != '\0' && *str != '}')
    376   1.1      roy 				str++;
    377   1.1      roy 			if (*str == '}')
    378   1.1      roy 				str++;
    379   1.1      roy 			break;
    380   1.1      roy 		case '+': /* FALLTHROUGH */
    381   1.1      roy 		case '-': /* FALLTHROUGH */
    382   1.1      roy 		case '*': /* FALLTHROUGH */
    383   1.1      roy 		case '/': /* FALLTHROUGH */
    384   1.1      roy 		case 'm': /* FALLTHROUGH */
    385   1.1      roy 		case 'A': /* FALLTHROUGH */
    386   1.1      roy 		case 'O': /* FALLTHROUGH */
    387   1.1      roy 		case '&': /* FALLTHROUGH */
    388   1.1      roy 		case '|': /* FALLTHROUGH */
    389   1.1      roy 		case '^': /* FALLTHROUGH */
    390   1.1      roy 		case '=': /* FALLTHROUGH */
    391   1.1      roy 		case '<': /* FALLTHROUGH */
    392   1.1      roy 		case '>':
    393   1.5      roy 			pop(&val, NULL, &stack);
    394   1.5      roy 			pop(&val2, NULL, &stack);
    395   1.1      roy 			switch (c) {
    396   1.1      roy 			case '+':
    397   1.1      roy 				val = val + val2;
    398   1.1      roy 				break;
    399   1.1      roy 			case '-':
    400   1.1      roy 				val = val2 - val;
    401   1.1      roy 				break;
    402   1.1      roy 			case '*':
    403   1.1      roy 				val = val * val2;
    404   1.1      roy 				break;
    405   1.1      roy 			case '/':
    406   1.1      roy 				val = val ? val2 / val : 0;
    407   1.1      roy 				break;
    408   1.1      roy 			case 'm':
    409   1.1      roy 				val = val ? val2 % val : 0;
    410   1.1      roy 				break;
    411   1.1      roy 			case 'A':
    412   1.1      roy 				val = val && val2;
    413   1.1      roy 				break;
    414   1.1      roy 			case 'O':
    415   1.1      roy 				val = val || val2;
    416   1.1      roy 				break;
    417   1.1      roy 			case '&':
    418   1.1      roy 				val = val & val2;
    419   1.1      roy 				break;
    420   1.1      roy 			case '|':
    421   1.1      roy 				val = val | val2;
    422   1.1      roy 				break;
    423   1.1      roy 			case '^':
    424   1.1      roy 				val = val ^ val2;
    425   1.1      roy 				break;
    426   1.1      roy 			case '=':
    427   1.1      roy 				val = val == val2;
    428   1.1      roy 				break;
    429   1.1      roy 			case '<':
    430   1.1      roy 				val = val2 < val;
    431   1.1      roy 				break;
    432   1.1      roy 			case '>':
    433   1.1      roy 				val = val2 > val;
    434   1.1      roy 				break;
    435   1.1      roy 			}
    436   1.1      roy 			if (push(val, NULL, &stack))
    437   1.1      roy 				return NULL;
    438   1.1      roy 			break;
    439   1.1      roy 		case '!':
    440   1.1      roy 		case '~':
    441   1.5      roy 			pop(&val, NULL, &stack);
    442   1.1      roy 			switch (*str) {
    443   1.1      roy 			case '!':
    444   1.1      roy 				val = !val;
    445   1.1      roy 				break;
    446   1.1      roy 			case '~':
    447   1.1      roy 				val = ~val;
    448   1.1      roy 				break;
    449   1.1      roy 			}
    450   1.1      roy 			if (push(val, NULL, &stack))
    451   1.1      roy 				return NULL;
    452   1.1      roy 			break;
    453   1.1      roy 		case '?': /* if */
    454   1.1      roy 			break;
    455   1.1      roy 		case 't': /* then */
    456   1.5      roy 			pop(&val, NULL, &stack);
    457  1.10      roy 			if (val == 0) {
    458   1.1      roy 				l = 0;
    459   1.1      roy 				for (; *str != '\0'; str++) {
    460   1.1      roy 					if (*str != '%')
    461   1.1      roy 						continue;
    462   1.1      roy 					str++;
    463   1.1      roy 					if (*str == '?')
    464   1.1      roy 						l++;
    465   1.1      roy 					else if (*str == ';') {
    466   1.1      roy 						if (l > 0)
    467   1.1      roy 							l--;
    468  1.10      roy 						else {
    469  1.10      roy 							str++;
    470   1.1      roy 							break;
    471  1.10      roy 						}
    472  1.10      roy 					} else if (*str == 'e' && l == 0) {
    473  1.10      roy 						str++;
    474   1.1      roy 						break;
    475  1.10      roy 					}
    476   1.1      roy 				}
    477   1.1      roy 			}
    478   1.1      roy 			break;
    479   1.1      roy 		case 'e': /* else */
    480   1.1      roy 			l = 0;
    481   1.1      roy 			for (; *str != '\0'; str++) {
    482   1.1      roy 				if (*str != '%')
    483   1.1      roy 					continue;
    484   1.1      roy 				str++;
    485   1.1      roy 				if (*str == '?')
    486   1.1      roy 					l++;
    487   1.1      roy 				else if (*str == ';') {
    488   1.1      roy 					if (l > 0)
    489   1.1      roy 						l--;
    490  1.10      roy 					else {
    491  1.10      roy 						str++;
    492   1.1      roy 						break;
    493  1.10      roy 					}
    494   1.1      roy 				}
    495   1.1      roy 			}
    496   1.1      roy 			break;
    497   1.1      roy 		case ';': /* fi */
    498   1.1      roy 			break;
    499   1.1      roy 		}
    500   1.1      roy 	}
    501   1.1      roy 	term->_buf[term->_bufpos] = '\0';
    502   1.1      roy 	return term->_buf;
    503   1.1      roy }
    504   1.1      roy 
    505   1.1      roy char *
    506   1.6      roy ti_tiparm(TERMINAL *term, const char *str, ...)
    507   1.1      roy {
    508   1.1      roy 	va_list va;
    509   1.1      roy 	char *ret;
    510   1.1      roy 
    511   1.1      roy 	_DIAGASSERT(term != NULL);
    512   1.1      roy 	_DIAGASSERT(str != NULL);
    513   1.1      roy 
    514   1.1      roy 	va_start(va, str);
    515   1.6      roy 	ret = _ti_tiparm(term, str, va);
    516   1.1      roy 	va_end(va);
    517   1.1      roy 	return ret;
    518   1.1      roy }
    519   1.1      roy 
    520   1.1      roy char *
    521   1.6      roy tiparm(const char *str, ...)
    522   1.1      roy {
    523   1.1      roy 	va_list va;
    524   1.1      roy 	char *ret;
    525   1.1      roy 
    526   1.1      roy 	_DIAGASSERT(str != NULL);
    527   1.1      roy 
    528   1.1      roy 	va_start(va, str);
    529   1.6      roy         ret = _ti_tiparm(NULL, str, va);
    530   1.1      roy 	va_end(va);
    531   1.1      roy 	return ret;
    532   1.1      roy }
    533   1.1      roy 
    534   1.1      roy char *
    535   1.1      roy tparm(const char *str,
    536   1.6      roy     long lp1, long lp2, long lp3, long lp4, long lp5,
    537   1.6      roy     long lp6, long lp7, long lp8, long lp9)
    538   1.1      roy {
    539   1.6      roy 	int p1 = lp1, p2 = lp2, p3 = lp3, p4 = lp4, p5 = lp5;
    540   1.6      roy 	int p6 = lp6, p7 = lp7, p8 = lp8, p9 = lp9;
    541   1.7      roy 
    542   1.7      roy 	return tiparm(str, p1, p2, p3, p4, p5, p6, p7, p8, p9);
    543   1.1      roy }
    544