xref: /plan9/sys/src/cmd/cpp/tokens.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <stdio.h>
43e12c5d1SDavid du Colombier #include "cpp.h"
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier static char wbuf[2*OBS];
73e12c5d1SDavid du Colombier static char *wbp = wbuf;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier /*
103e12c5d1SDavid du Colombier  * 1 for tokens that don't need whitespace when they get inserted
113e12c5d1SDavid du Colombier  * by macro expansion
123e12c5d1SDavid du Colombier  */
13*7dd7cddfSDavid du Colombier static char wstab[] = {
143e12c5d1SDavid du Colombier 	0,	/* END */
153e12c5d1SDavid du Colombier 	0,	/* UNCLASS */
163e12c5d1SDavid du Colombier 	0,	/* NAME */
173e12c5d1SDavid du Colombier 	0,	/* NUMBER */
183e12c5d1SDavid du Colombier 	0,	/* STRING */
193e12c5d1SDavid du Colombier 	0,	/* CCON */
203e12c5d1SDavid du Colombier 	1,	/* NL */
213e12c5d1SDavid du Colombier 	0,	/* WS */
223e12c5d1SDavid du Colombier 	0,	/* DSHARP */
233e12c5d1SDavid du Colombier 	0,	/* EQ */
243e12c5d1SDavid du Colombier 	0,	/* NEQ */
253e12c5d1SDavid du Colombier 	0,	/* LEQ */
263e12c5d1SDavid du Colombier 	0,	/* GEQ */
273e12c5d1SDavid du Colombier 	0,	/* LSH */
283e12c5d1SDavid du Colombier 	0,	/* RSH */
293e12c5d1SDavid du Colombier 	0,	/* LAND */
303e12c5d1SDavid du Colombier 	0,	/* LOR */
313e12c5d1SDavid du Colombier 	0,	/* PPLUS */
323e12c5d1SDavid du Colombier 	0,	/* MMINUS */
333e12c5d1SDavid du Colombier 	0,	/* ARROW */
343e12c5d1SDavid du Colombier 	1,	/* SBRA */
353e12c5d1SDavid du Colombier 	1,	/* SKET */
363e12c5d1SDavid du Colombier 	1,	/* LP */
373e12c5d1SDavid du Colombier 	1,	/* RP */
383e12c5d1SDavid du Colombier 	0,	/* DOT */
393e12c5d1SDavid du Colombier 	0,	/* AND */
403e12c5d1SDavid du Colombier 	0,	/* STAR */
413e12c5d1SDavid du Colombier 	0,	/* PLUS */
423e12c5d1SDavid du Colombier 	0,	/* MINUS */
433e12c5d1SDavid du Colombier 	0,	/* TILDE */
443e12c5d1SDavid du Colombier 	0,	/* NOT */
453e12c5d1SDavid du Colombier 	0,	/* SLASH */
463e12c5d1SDavid du Colombier 	0,	/* PCT */
473e12c5d1SDavid du Colombier 	0,	/* LT */
483e12c5d1SDavid du Colombier 	0,	/* GT */
493e12c5d1SDavid du Colombier 	0,	/* CIRC */
503e12c5d1SDavid du Colombier 	0,	/* OR */
513e12c5d1SDavid du Colombier 	0,	/* QUEST */
523e12c5d1SDavid du Colombier 	0,	/* COLON */
533e12c5d1SDavid du Colombier 	0,	/* ASGN */
543e12c5d1SDavid du Colombier 	1,	/* COMMA */
553e12c5d1SDavid du Colombier 	0,	/* SHARP */
563e12c5d1SDavid du Colombier 	1,	/* SEMIC */
573e12c5d1SDavid du Colombier 	1,	/* CBRA */
583e12c5d1SDavid du Colombier 	1,	/* CKET */
593e12c5d1SDavid du Colombier 	0,	/* ASPLUS */
603e12c5d1SDavid du Colombier  	0,	/* ASMINUS */
613e12c5d1SDavid du Colombier  	0,	/* ASSTAR */
623e12c5d1SDavid du Colombier  	0,	/* ASSLASH */
633e12c5d1SDavid du Colombier  	0,	/* ASPCT */
643e12c5d1SDavid du Colombier  	0,	/* ASCIRC */
653e12c5d1SDavid du Colombier  	0,	/* ASLSH */
663e12c5d1SDavid du Colombier 	0,	/* ASRSH */
673e12c5d1SDavid du Colombier  	0,	/* ASOR */
683e12c5d1SDavid du Colombier  	0,	/* ASAND */
693e12c5d1SDavid du Colombier 	0,	/* ELLIPS */
703e12c5d1SDavid du Colombier 	0,	/* DSHARP1 */
713e12c5d1SDavid du Colombier 	0,	/* NAME1 */
723e12c5d1SDavid du Colombier 	0,	/* DEFINED */
733e12c5d1SDavid du Colombier 	0,	/* UMINUS */
743e12c5d1SDavid du Colombier };
753e12c5d1SDavid du Colombier 
763e12c5d1SDavid du Colombier void
maketokenrow(int size,Tokenrow * trp)773e12c5d1SDavid du Colombier maketokenrow(int size, Tokenrow *trp)
783e12c5d1SDavid du Colombier {
793e12c5d1SDavid du Colombier 	trp->max = size;
80219b2ee8SDavid du Colombier 	if (size>0)
813e12c5d1SDavid du Colombier 		trp->bp = (Token *)domalloc(size*sizeof(Token));
82219b2ee8SDavid du Colombier 	else
83219b2ee8SDavid du Colombier 		trp->bp = NULL;
843e12c5d1SDavid du Colombier 	trp->tp = trp->bp;
853e12c5d1SDavid du Colombier 	trp->lp = trp->bp;
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier 
883e12c5d1SDavid du Colombier Token *
growtokenrow(Tokenrow * trp)893e12c5d1SDavid du Colombier growtokenrow(Tokenrow *trp)
903e12c5d1SDavid du Colombier {
913e12c5d1SDavid du Colombier 	int ncur = trp->tp - trp->bp;
923e12c5d1SDavid du Colombier 	int nlast = trp->lp - trp->bp;
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	trp->max = 3*trp->max/2 + 1;
953e12c5d1SDavid du Colombier 	trp->bp = (Token *)realloc(trp->bp, trp->max*sizeof(Token));
963e12c5d1SDavid du Colombier 	trp->lp = &trp->bp[nlast];
973e12c5d1SDavid du Colombier 	trp->tp = &trp->bp[ncur];
983e12c5d1SDavid du Colombier 	return trp->lp;
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier /*
1023e12c5d1SDavid du Colombier  * Compare a row of tokens, ignoring the content of WS; return !=0 if different
1033e12c5d1SDavid du Colombier  */
1043e12c5d1SDavid du Colombier int
comparetokens(Tokenrow * tr1,Tokenrow * tr2)1053e12c5d1SDavid du Colombier comparetokens(Tokenrow *tr1, Tokenrow *tr2)
1063e12c5d1SDavid du Colombier {
1073e12c5d1SDavid du Colombier 	Token *tp1, *tp2;
1083e12c5d1SDavid du Colombier 
1093e12c5d1SDavid du Colombier 	tp1 = tr1->tp;
1103e12c5d1SDavid du Colombier 	tp2 = tr2->tp;
1113e12c5d1SDavid du Colombier 	if (tr1->lp-tp1 != tr2->lp-tp2)
1123e12c5d1SDavid du Colombier 		return 1;
1133e12c5d1SDavid du Colombier 	for (; tp1<tr1->lp ; tp1++, tp2++) {
1143e12c5d1SDavid du Colombier 		if (tp1->type != tp2->type
1153e12c5d1SDavid du Colombier 		 || (tp1->wslen==0) != (tp2->wslen==0)
1163e12c5d1SDavid du Colombier 		 || tp1->len != tp2->len
1173e12c5d1SDavid du Colombier 		 || strncmp((char*)tp1->t, (char*)tp2->t, tp1->len)!=0)
1183e12c5d1SDavid du Colombier 			return 1;
1193e12c5d1SDavid du Colombier 	}
1203e12c5d1SDavid du Colombier 	return 0;
1213e12c5d1SDavid du Colombier }
1223e12c5d1SDavid du Colombier 
1233e12c5d1SDavid du Colombier /*
1243e12c5d1SDavid du Colombier  * replace ntok tokens starting at dtr->tp with the contents of str.
1253e12c5d1SDavid du Colombier  * tp ends up pointing just beyond the replacement.
1263e12c5d1SDavid du Colombier  * Canonical whitespace is assured on each side.
1273e12c5d1SDavid du Colombier  */
1283e12c5d1SDavid du Colombier void
insertrow(Tokenrow * dtr,int ntok,Tokenrow * str)1293e12c5d1SDavid du Colombier insertrow(Tokenrow *dtr, int ntok, Tokenrow *str)
1303e12c5d1SDavid du Colombier {
1313e12c5d1SDavid du Colombier 	int nrtok = rowlen(str);
1323e12c5d1SDavid du Colombier 
1333e12c5d1SDavid du Colombier 	dtr->tp += ntok;
1343e12c5d1SDavid du Colombier 	adjustrow(dtr, nrtok-ntok);
1353e12c5d1SDavid du Colombier 	dtr->tp -= ntok;
1363e12c5d1SDavid du Colombier 	movetokenrow(dtr, str);
1373e12c5d1SDavid du Colombier 	makespace(dtr);
1383e12c5d1SDavid du Colombier 	dtr->tp += nrtok;
1393e12c5d1SDavid du Colombier 	makespace(dtr);
1403e12c5d1SDavid du Colombier }
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier /*
1433e12c5d1SDavid du Colombier  * make sure there is WS before trp->tp, if tokens might merge in the output
1443e12c5d1SDavid du Colombier  */
1453e12c5d1SDavid du Colombier void
makespace(Tokenrow * trp)1463e12c5d1SDavid du Colombier makespace(Tokenrow *trp)
1473e12c5d1SDavid du Colombier {
1483e12c5d1SDavid du Colombier 	uchar *tt;
1493e12c5d1SDavid du Colombier 	Token *tp = trp->tp;
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	if (tp >= trp->lp)
1523e12c5d1SDavid du Colombier 		return;
1533e12c5d1SDavid du Colombier 	if (tp->wslen) {
1543e12c5d1SDavid du Colombier 		if (tp->flag&XPWS
1553e12c5d1SDavid du Colombier 		 && (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])) {
1563e12c5d1SDavid du Colombier 			tp->wslen = 0;
1573e12c5d1SDavid du Colombier 			return;
1583e12c5d1SDavid du Colombier 		}
1593e12c5d1SDavid du Colombier 		tp->t[-1] = ' ';
1603e12c5d1SDavid du Colombier 		return;
1613e12c5d1SDavid du Colombier 	}
1623e12c5d1SDavid du Colombier 	if (wstab[tp->type] || trp->tp>trp->bp && wstab[(tp-1)->type])
1633e12c5d1SDavid du Colombier 		return;
1643e12c5d1SDavid du Colombier 	tt = newstring(tp->t, tp->len, 1);
1653e12c5d1SDavid du Colombier 	*tt++ = ' ';
1663e12c5d1SDavid du Colombier 	tp->t = tt;
1673e12c5d1SDavid du Colombier 	tp->wslen = 1;
1683e12c5d1SDavid du Colombier 	tp->flag |= XPWS;
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier /*
1723e12c5d1SDavid du Colombier  * Copy an entire tokenrow into another, at tp.
1733e12c5d1SDavid du Colombier  * It is assumed that there is enough space.
1743e12c5d1SDavid du Colombier  *  Not strictly conforming.
1753e12c5d1SDavid du Colombier  */
1763e12c5d1SDavid du Colombier void
movetokenrow(Tokenrow * dtr,Tokenrow * str)1773e12c5d1SDavid du Colombier movetokenrow(Tokenrow *dtr, Tokenrow *str)
1783e12c5d1SDavid du Colombier {
1793e12c5d1SDavid du Colombier 	int nby;
1803e12c5d1SDavid du Colombier 
1813e12c5d1SDavid du Colombier 	/* nby = sizeof(Token) * (str->lp - str->bp); */
1823e12c5d1SDavid du Colombier 	nby = (char *)str->lp - (char *)str->bp;
1833e12c5d1SDavid du Colombier 	memmove(dtr->tp, str->bp, nby);
1843e12c5d1SDavid du Colombier }
1853e12c5d1SDavid du Colombier 
1863e12c5d1SDavid du Colombier /*
1873e12c5d1SDavid du Colombier  * Move the tokens in a row, starting at tr->tp, rightward by nt tokens;
1883e12c5d1SDavid du Colombier  * nt may be negative (left move).
1893e12c5d1SDavid du Colombier  * The row may need to be grown.
1903e12c5d1SDavid du Colombier  * Non-strictly conforming because of the (char *), but easily fixed
1913e12c5d1SDavid du Colombier  */
1923e12c5d1SDavid du Colombier void
adjustrow(Tokenrow * trp,int nt)1933e12c5d1SDavid du Colombier adjustrow(Tokenrow *trp, int nt)
1943e12c5d1SDavid du Colombier {
1953e12c5d1SDavid du Colombier 	int nby, size;
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	if (nt==0)
1983e12c5d1SDavid du Colombier 		return;
1993e12c5d1SDavid du Colombier 	size = (trp->lp - trp->bp) + nt;
2003e12c5d1SDavid du Colombier 	while (size > trp->max)
2013e12c5d1SDavid du Colombier 		growtokenrow(trp);
2023e12c5d1SDavid du Colombier 	/* nby = sizeof(Token) * (trp->lp - trp->tp); */
2033e12c5d1SDavid du Colombier 	nby = (char *)trp->lp - (char *)trp->tp;
2043e12c5d1SDavid du Colombier 	if (nby)
2053e12c5d1SDavid du Colombier 		memmove(trp->tp+nt, trp->tp, nby);
2063e12c5d1SDavid du Colombier 	trp->lp += nt;
2073e12c5d1SDavid du Colombier }
2083e12c5d1SDavid du Colombier 
2093e12c5d1SDavid du Colombier /*
2103e12c5d1SDavid du Colombier  * Copy a row of tokens into the destination holder, allocating
2113e12c5d1SDavid du Colombier  * the space for the contents.  Return the destination.
2123e12c5d1SDavid du Colombier  */
2133e12c5d1SDavid du Colombier Tokenrow *
copytokenrow(Tokenrow * dtr,Tokenrow * str)2143e12c5d1SDavid du Colombier copytokenrow(Tokenrow *dtr, Tokenrow *str)
2153e12c5d1SDavid du Colombier {
2163e12c5d1SDavid du Colombier 	int len = rowlen(str);
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	maketokenrow(len, dtr);
2193e12c5d1SDavid du Colombier 	movetokenrow(dtr, str);
2203e12c5d1SDavid du Colombier 	dtr->lp += len;
2213e12c5d1SDavid du Colombier 	return dtr;
2223e12c5d1SDavid du Colombier }
2233e12c5d1SDavid du Colombier 
2243e12c5d1SDavid du Colombier /*
2253e12c5d1SDavid du Colombier  * Produce a copy of a row of tokens.  Start at trp->tp.
2263e12c5d1SDavid du Colombier  * The value strings are copied as well.  The first token
2273e12c5d1SDavid du Colombier  * has WS available.
2283e12c5d1SDavid du Colombier  */
2293e12c5d1SDavid du Colombier Tokenrow *
normtokenrow(Tokenrow * trp)2303e12c5d1SDavid du Colombier normtokenrow(Tokenrow *trp)
2313e12c5d1SDavid du Colombier {
2323e12c5d1SDavid du Colombier 	Token *tp;
2333e12c5d1SDavid du Colombier 	Tokenrow *ntrp = new(Tokenrow);
2343e12c5d1SDavid du Colombier 	int len;
2353e12c5d1SDavid du Colombier 
2363e12c5d1SDavid du Colombier 	len = trp->lp - trp->tp;
2373e12c5d1SDavid du Colombier 	if (len<=0)
2383e12c5d1SDavid du Colombier 		len = 1;
2393e12c5d1SDavid du Colombier 	maketokenrow(len, ntrp);
2403e12c5d1SDavid du Colombier 	for (tp=trp->tp; tp < trp->lp; tp++) {
2413e12c5d1SDavid du Colombier 		*ntrp->lp = *tp;
2423e12c5d1SDavid du Colombier 		if (tp->len) {
2433e12c5d1SDavid du Colombier 			ntrp->lp->t = newstring(tp->t, tp->len, 1);
2443e12c5d1SDavid du Colombier 			*ntrp->lp->t++ = ' ';
2453e12c5d1SDavid du Colombier 			if (tp->wslen)
2463e12c5d1SDavid du Colombier 				ntrp->lp->wslen = 1;
2473e12c5d1SDavid du Colombier 		}
2483e12c5d1SDavid du Colombier 		ntrp->lp++;
2493e12c5d1SDavid du Colombier 	}
2503e12c5d1SDavid du Colombier 	if (ntrp->lp > ntrp->bp)
2513e12c5d1SDavid du Colombier 		ntrp->bp->wslen = 0;
2523e12c5d1SDavid du Colombier 	return ntrp;
2533e12c5d1SDavid du Colombier }
2543e12c5d1SDavid du Colombier 
2553e12c5d1SDavid du Colombier /*
2563e12c5d1SDavid du Colombier  * Debugging
2573e12c5d1SDavid du Colombier  */
2583e12c5d1SDavid du Colombier void
peektokens(Tokenrow * trp,char * str)2593e12c5d1SDavid du Colombier peektokens(Tokenrow *trp, char *str)
2603e12c5d1SDavid du Colombier {
2613e12c5d1SDavid du Colombier 	Token *tp;
2623e12c5d1SDavid du Colombier 	int c;
2633e12c5d1SDavid du Colombier 
2643e12c5d1SDavid du Colombier 	tp = trp->tp;
2653e12c5d1SDavid du Colombier 	flushout();
2663e12c5d1SDavid du Colombier 	if (str)
2673e12c5d1SDavid du Colombier 		fprintf(stderr, "%s ", str);
2683e12c5d1SDavid du Colombier 	if (tp<trp->bp || tp>trp->lp)
2693e12c5d1SDavid du Colombier 		fprintf(stderr, "(tp offset %d) ", tp-trp->bp);
2703e12c5d1SDavid du Colombier 	for (tp=trp->bp; tp<trp->lp && tp<trp->bp+32; tp++) {
2713e12c5d1SDavid du Colombier 		if (tp->type!=NL) {
2723e12c5d1SDavid du Colombier 			c = tp->t[tp->len];
2733e12c5d1SDavid du Colombier 			tp->t[tp->len] = 0;
2743e12c5d1SDavid du Colombier 			fprintf(stderr, "%s", tp->t, tp->len);
2753e12c5d1SDavid du Colombier 			tp->t[tp->len] = c;
2763e12c5d1SDavid du Colombier 		}
2773e12c5d1SDavid du Colombier 		if (tp->type==NAME) {
2783e12c5d1SDavid du Colombier 			fprintf(stderr, tp==trp->tp?"{*":"{");
2793e12c5d1SDavid du Colombier 			prhideset(tp->hideset);
2803e12c5d1SDavid du Colombier 			fprintf(stderr, "} ");
2813e12c5d1SDavid du Colombier 		} else
2823e12c5d1SDavid du Colombier 			fprintf(stderr, tp==trp->tp?"{%x*} ":"{%x} ", tp->type);
2833e12c5d1SDavid du Colombier 	}
2843e12c5d1SDavid du Colombier 	fprintf(stderr, "\n");
2853e12c5d1SDavid du Colombier 	fflush(stderr);
2863e12c5d1SDavid du Colombier }
2873e12c5d1SDavid du Colombier 
2883e12c5d1SDavid du Colombier void
puttokens(Tokenrow * trp)2893e12c5d1SDavid du Colombier puttokens(Tokenrow *trp)
2903e12c5d1SDavid du Colombier {
2913e12c5d1SDavid du Colombier 	Token *tp;
2923e12c5d1SDavid du Colombier 	int len;
2933e12c5d1SDavid du Colombier 	uchar *p;
2943e12c5d1SDavid du Colombier 
2953e12c5d1SDavid du Colombier 	if (verbose)
2963e12c5d1SDavid du Colombier 		peektokens(trp, "");
2973e12c5d1SDavid du Colombier 	tp = trp->bp;
2983e12c5d1SDavid du Colombier 	for (; tp<trp->lp; tp++) {
2993e12c5d1SDavid du Colombier 		len = tp->len+tp->wslen;
3003e12c5d1SDavid du Colombier 		p = tp->t-tp->wslen;
3013e12c5d1SDavid du Colombier 		while (tp<trp->lp-1 && p+len == (tp+1)->t - (tp+1)->wslen) {
3023e12c5d1SDavid du Colombier 			tp++;
3033e12c5d1SDavid du Colombier 			len += tp->wslen+tp->len;
3043e12c5d1SDavid du Colombier 		}
305bd389b36SDavid du Colombier 		if (Mflag==0) {
306219b2ee8SDavid du Colombier 			if (len>OBS/2) {		/* handle giant token */
307219b2ee8SDavid du Colombier 				if (wbp > wbuf)
308219b2ee8SDavid du Colombier 					write(1, wbuf, wbp-wbuf);
309219b2ee8SDavid du Colombier 				write(1, p, len);
310219b2ee8SDavid du Colombier 				wbp = wbuf;
311219b2ee8SDavid du Colombier 			} else {
3123e12c5d1SDavid du Colombier 				memcpy(wbp, p, len);
3133e12c5d1SDavid du Colombier 				wbp += len;
314bd389b36SDavid du Colombier 			}
315219b2ee8SDavid du Colombier 		}
3163e12c5d1SDavid du Colombier 		if (wbp >= &wbuf[OBS]) {
3173e12c5d1SDavid du Colombier 			write(1, wbuf, OBS);
3183e12c5d1SDavid du Colombier 			if (wbp > &wbuf[OBS])
3193e12c5d1SDavid du Colombier 				memcpy(wbuf, wbuf+OBS, wbp - &wbuf[OBS]);
3203e12c5d1SDavid du Colombier 			wbp -= OBS;
3213e12c5d1SDavid du Colombier 		}
3223e12c5d1SDavid du Colombier 	}
3233e12c5d1SDavid du Colombier 	trp->tp = tp;
3243e12c5d1SDavid du Colombier 	if (cursource->fd==0)
3253e12c5d1SDavid du Colombier 		flushout();
3263e12c5d1SDavid du Colombier }
3273e12c5d1SDavid du Colombier 
3283e12c5d1SDavid du Colombier void
flushout(void)3293e12c5d1SDavid du Colombier flushout(void)
3303e12c5d1SDavid du Colombier {
3313e12c5d1SDavid du Colombier 	if (wbp>wbuf) {
3323e12c5d1SDavid du Colombier 		write(1, wbuf, wbp-wbuf);
3333e12c5d1SDavid du Colombier 		wbp = wbuf;
3343e12c5d1SDavid du Colombier 	}
3353e12c5d1SDavid du Colombier }
3363e12c5d1SDavid du Colombier 
3373e12c5d1SDavid du Colombier /*
3383e12c5d1SDavid du Colombier  * turn a row into just a newline
3393e12c5d1SDavid du Colombier  */
3403e12c5d1SDavid du Colombier void
setempty(Tokenrow * trp)3413e12c5d1SDavid du Colombier setempty(Tokenrow *trp)
3423e12c5d1SDavid du Colombier {
3433e12c5d1SDavid du Colombier 	trp->tp = trp->bp;
3443e12c5d1SDavid du Colombier 	trp->lp = trp->bp+1;
3453e12c5d1SDavid du Colombier 	*trp->bp = nltoken;
3463e12c5d1SDavid du Colombier }
3473e12c5d1SDavid du Colombier 
3483e12c5d1SDavid du Colombier /*
3493e12c5d1SDavid du Colombier  * generate a number
3503e12c5d1SDavid du Colombier  */
3513e12c5d1SDavid du Colombier char *
outnum(char * p,int n)3523e12c5d1SDavid du Colombier outnum(char *p, int n)
3533e12c5d1SDavid du Colombier {
3543e12c5d1SDavid du Colombier 	if (n>=10)
3553e12c5d1SDavid du Colombier 		p = outnum(p, n/10);
3563e12c5d1SDavid du Colombier 	*p++ = n%10 + '0';
3573e12c5d1SDavid du Colombier 	return p;
3583e12c5d1SDavid du Colombier }
3593e12c5d1SDavid du Colombier 
3603e12c5d1SDavid du Colombier /*
3613e12c5d1SDavid du Colombier  * allocate and initialize a new string from s, of length l, at offset o
3623e12c5d1SDavid du Colombier  * Null terminated.
3633e12c5d1SDavid du Colombier  */
3643e12c5d1SDavid du Colombier uchar *
newstring(uchar * s,int l,int o)3653e12c5d1SDavid du Colombier newstring(uchar *s, int l, int o)
3663e12c5d1SDavid du Colombier {
3673e12c5d1SDavid du Colombier 	uchar *ns = (uchar *)domalloc(l+o+1);
3683e12c5d1SDavid du Colombier 
3693e12c5d1SDavid du Colombier 	ns[l+o] = '\0';
3703e12c5d1SDavid du Colombier 	return (uchar*)strncpy((char*)ns+o, (char*)s, l) - o;
3713e12c5d1SDavid du Colombier }
372