xref: /inferno-os/libkern/fmtquote.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /*
2*37da2899SCharles.Forsyth  * The authors of this software are Rob Pike and Ken Thompson.
3*37da2899SCharles.Forsyth  *              Copyright (c) 2002 by Lucent Technologies.
4*37da2899SCharles.Forsyth  * Permission to use, copy, modify, and distribute this software for any
5*37da2899SCharles.Forsyth  * purpose without fee is hereby granted, provided that this entire notice
6*37da2899SCharles.Forsyth  * is included in all copies of any software which is or includes a copy
7*37da2899SCharles.Forsyth  * or modification of this software and in all copies of the supporting
8*37da2899SCharles.Forsyth  * documentation for such software.
9*37da2899SCharles.Forsyth  * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
10*37da2899SCharles.Forsyth  * WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
11*37da2899SCharles.Forsyth  * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
12*37da2899SCharles.Forsyth  * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
13*37da2899SCharles.Forsyth  */
14*37da2899SCharles.Forsyth #include "lib9.h"
15*37da2899SCharles.Forsyth #include "fmtdef.h"
16*37da2899SCharles.Forsyth 
17*37da2899SCharles.Forsyth /*
18*37da2899SCharles.Forsyth  * How many bytes of output UTF will be produced by quoting (if necessary) this string?
19*37da2899SCharles.Forsyth  * How many runes? How much of the input will be consumed?
20*37da2899SCharles.Forsyth  * The parameter q is filled in by _quotesetup.
21*37da2899SCharles.Forsyth  * The string may be UTF or Runes (s or r).
22*37da2899SCharles.Forsyth  * Return count does not include NUL.
23*37da2899SCharles.Forsyth  * Terminate the scan at the first of:
24*37da2899SCharles.Forsyth  *	NUL in input
25*37da2899SCharles.Forsyth  *	count exceeded in input
26*37da2899SCharles.Forsyth  *	count exceeded on output
27*37da2899SCharles.Forsyth  * *ninp is set to number of input bytes accepted.
28*37da2899SCharles.Forsyth  * nin may be <0 initially, to avoid checking input by count.
29*37da2899SCharles.Forsyth  */
30*37da2899SCharles.Forsyth void
_quotesetup(char * s,Rune * r,int nin,int nout,Quoteinfo * q,int sharp,int runesout)31*37da2899SCharles.Forsyth _quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
32*37da2899SCharles.Forsyth {
33*37da2899SCharles.Forsyth 	int w;
34*37da2899SCharles.Forsyth 	Rune c;
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth 	q->quoted = 0;
37*37da2899SCharles.Forsyth 	q->nbytesout = 0;
38*37da2899SCharles.Forsyth 	q->nrunesout = 0;
39*37da2899SCharles.Forsyth 	q->nbytesin = 0;
40*37da2899SCharles.Forsyth 	q->nrunesin = 0;
41*37da2899SCharles.Forsyth 	if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
42*37da2899SCharles.Forsyth 		if(nout < 2)
43*37da2899SCharles.Forsyth 			return;
44*37da2899SCharles.Forsyth 		q->quoted = 1;
45*37da2899SCharles.Forsyth 		q->nbytesout = 2;
46*37da2899SCharles.Forsyth 		q->nrunesout = 2;
47*37da2899SCharles.Forsyth 	}
48*37da2899SCharles.Forsyth 	for(; nin!=0; nin-=w){
49*37da2899SCharles.Forsyth 		if(s)
50*37da2899SCharles.Forsyth 			w = chartorune(&c, s);
51*37da2899SCharles.Forsyth 		else{
52*37da2899SCharles.Forsyth 			c = *r;
53*37da2899SCharles.Forsyth 			w = runelen(c);
54*37da2899SCharles.Forsyth 		}
55*37da2899SCharles.Forsyth 
56*37da2899SCharles.Forsyth 		if(c == '\0')
57*37da2899SCharles.Forsyth 			break;
58*37da2899SCharles.Forsyth 		if(runesout){
59*37da2899SCharles.Forsyth 			if(q->nrunesout+1 > nout)
60*37da2899SCharles.Forsyth 				break;
61*37da2899SCharles.Forsyth 		}else{
62*37da2899SCharles.Forsyth 			if(q->nbytesout+w > nout)
63*37da2899SCharles.Forsyth 				break;
64*37da2899SCharles.Forsyth 		}
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth 		if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){
67*37da2899SCharles.Forsyth 			if(!q->quoted){
68*37da2899SCharles.Forsyth 				if(runesout){
69*37da2899SCharles.Forsyth 					if(1+q->nrunesout+1+1 > nout)	/* no room for quotes */
70*37da2899SCharles.Forsyth 						break;
71*37da2899SCharles.Forsyth 				}else{
72*37da2899SCharles.Forsyth 					if(1+q->nbytesout+w+1 > nout)	/* no room for quotes */
73*37da2899SCharles.Forsyth 						break;
74*37da2899SCharles.Forsyth 				}
75*37da2899SCharles.Forsyth 				q->nrunesout += 2;	/* include quotes */
76*37da2899SCharles.Forsyth 				q->nbytesout += 2;	/* include quotes */
77*37da2899SCharles.Forsyth 				q->quoted = 1;
78*37da2899SCharles.Forsyth 			}
79*37da2899SCharles.Forsyth 			if(c == '\'')	{
80*37da2899SCharles.Forsyth 				if(runesout){
81*37da2899SCharles.Forsyth 					if(1+q->nrunesout+1 > nout)	/* no room for quotes */
82*37da2899SCharles.Forsyth 						break;
83*37da2899SCharles.Forsyth 				}else{
84*37da2899SCharles.Forsyth 					if(1+q->nbytesout+w > nout)	/* no room for quotes */
85*37da2899SCharles.Forsyth 						break;
86*37da2899SCharles.Forsyth 				}
87*37da2899SCharles.Forsyth 				q->nbytesout++;
88*37da2899SCharles.Forsyth 				q->nrunesout++;	/* quotes reproduce as two characters */
89*37da2899SCharles.Forsyth 			}
90*37da2899SCharles.Forsyth 		}
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth 		/* advance input */
93*37da2899SCharles.Forsyth 		if(s)
94*37da2899SCharles.Forsyth 			s += w;
95*37da2899SCharles.Forsyth 		else
96*37da2899SCharles.Forsyth 			r++;
97*37da2899SCharles.Forsyth 		q->nbytesin += w;
98*37da2899SCharles.Forsyth 		q->nrunesin++;
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth 		/* advance output */
101*37da2899SCharles.Forsyth 		q->nbytesout += w;
102*37da2899SCharles.Forsyth 		q->nrunesout++;
103*37da2899SCharles.Forsyth 	}
104*37da2899SCharles.Forsyth }
105*37da2899SCharles.Forsyth 
106*37da2899SCharles.Forsyth static int
qstrfmt(char * sin,Rune * rin,Quoteinfo * q,Fmt * f)107*37da2899SCharles.Forsyth qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
108*37da2899SCharles.Forsyth {
109*37da2899SCharles.Forsyth 	Rune r, *rm, *rme;
110*37da2899SCharles.Forsyth 	char *t, *s, *m, *me;
111*37da2899SCharles.Forsyth 	Rune *rt, *rs;
112*37da2899SCharles.Forsyth 	ulong fl;
113*37da2899SCharles.Forsyth 	int nc, w;
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth 	m = sin;
116*37da2899SCharles.Forsyth 	me = m + q->nbytesin;
117*37da2899SCharles.Forsyth 	rm = rin;
118*37da2899SCharles.Forsyth 	rme = rm + q->nrunesin;
119*37da2899SCharles.Forsyth 
120*37da2899SCharles.Forsyth 	w = f->width;
121*37da2899SCharles.Forsyth 	fl = f->flags;
122*37da2899SCharles.Forsyth 	if(f->runes){
123*37da2899SCharles.Forsyth 		if(!(fl & FmtLeft) && _rfmtpad(f, w - q->nrunesout) < 0)
124*37da2899SCharles.Forsyth 			return -1;
125*37da2899SCharles.Forsyth 	}else{
126*37da2899SCharles.Forsyth 		if(!(fl & FmtLeft) && _fmtpad(f, w - q->nbytesout) < 0)
127*37da2899SCharles.Forsyth 			return -1;
128*37da2899SCharles.Forsyth 	}
129*37da2899SCharles.Forsyth 	t = f->to;
130*37da2899SCharles.Forsyth 	s = f->stop;
131*37da2899SCharles.Forsyth 	rt = f->to;
132*37da2899SCharles.Forsyth 	rs = f->stop;
133*37da2899SCharles.Forsyth 	if(f->runes)
134*37da2899SCharles.Forsyth 		FMTRCHAR(f, rt, rs, '\'');
135*37da2899SCharles.Forsyth 	else
136*37da2899SCharles.Forsyth 		FMTRUNE(f, t, s, '\'');
137*37da2899SCharles.Forsyth 	for(nc = q->nrunesin; nc > 0; nc--){
138*37da2899SCharles.Forsyth 		if(sin){
139*37da2899SCharles.Forsyth 			r = *(uchar*)m;
140*37da2899SCharles.Forsyth 			if(r < Runeself)
141*37da2899SCharles.Forsyth 				m++;
142*37da2899SCharles.Forsyth 			else if((me - m) >= UTFmax || fullrune(m, me-m))
143*37da2899SCharles.Forsyth 				m += chartorune(&r, m);
144*37da2899SCharles.Forsyth 			else
145*37da2899SCharles.Forsyth 				break;
146*37da2899SCharles.Forsyth 		}else{
147*37da2899SCharles.Forsyth 			if(rm >= rme)
148*37da2899SCharles.Forsyth 				break;
149*37da2899SCharles.Forsyth 			r = *rm++;
150*37da2899SCharles.Forsyth 		}
151*37da2899SCharles.Forsyth 		if(f->runes){
152*37da2899SCharles.Forsyth 			FMTRCHAR(f, rt, rs, r);
153*37da2899SCharles.Forsyth 			if(r == '\'')
154*37da2899SCharles.Forsyth 				FMTRCHAR(f, rt, rs, r);
155*37da2899SCharles.Forsyth 		}else{
156*37da2899SCharles.Forsyth 			FMTRUNE(f, t, s, r);
157*37da2899SCharles.Forsyth 			if(r == '\'')
158*37da2899SCharles.Forsyth 				FMTRUNE(f, t, s, r);
159*37da2899SCharles.Forsyth 		}
160*37da2899SCharles.Forsyth 	}
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth 	if(f->runes){
163*37da2899SCharles.Forsyth 		FMTRCHAR(f, rt, rs, '\'');
164*37da2899SCharles.Forsyth 		USED(rs);
165*37da2899SCharles.Forsyth 		f->nfmt += rt - (Rune *)f->to;
166*37da2899SCharles.Forsyth 		f->to = rt;
167*37da2899SCharles.Forsyth 		if(fl & FmtLeft && _rfmtpad(f, w - q->nrunesout) < 0)
168*37da2899SCharles.Forsyth 			return -1;
169*37da2899SCharles.Forsyth 	}else{
170*37da2899SCharles.Forsyth 		FMTRUNE(f, t, s, '\'');
171*37da2899SCharles.Forsyth 		USED(s);
172*37da2899SCharles.Forsyth 		f->nfmt += t - (char *)f->to;
173*37da2899SCharles.Forsyth 		f->to = t;
174*37da2899SCharles.Forsyth 		if(fl & FmtLeft && _fmtpad(f, w - q->nbytesout) < 0)
175*37da2899SCharles.Forsyth 			return -1;
176*37da2899SCharles.Forsyth 	}
177*37da2899SCharles.Forsyth 	return 0;
178*37da2899SCharles.Forsyth }
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth int
_quotestrfmt(int runesin,Fmt * f)181*37da2899SCharles.Forsyth _quotestrfmt(int runesin, Fmt *f)
182*37da2899SCharles.Forsyth {
183*37da2899SCharles.Forsyth 	int outlen;
184*37da2899SCharles.Forsyth 	Rune *r;
185*37da2899SCharles.Forsyth 	char *s;
186*37da2899SCharles.Forsyth 	Quoteinfo q;
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 	f->flags &= ~FmtPrec;	/* ignored for %q %Q, so disable for %s %S in easy case */
189*37da2899SCharles.Forsyth 	if(runesin){
190*37da2899SCharles.Forsyth 		r = va_arg(f->args, Rune *);
191*37da2899SCharles.Forsyth 		s = nil;
192*37da2899SCharles.Forsyth 	}else{
193*37da2899SCharles.Forsyth 		s = va_arg(f->args, char *);
194*37da2899SCharles.Forsyth 		r = nil;
195*37da2899SCharles.Forsyth 	}
196*37da2899SCharles.Forsyth 	if(!s && !r)
197*37da2899SCharles.Forsyth 		return _fmtcpy(f, "<nil>", 5, 5);
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth 	if(f->flush)
200*37da2899SCharles.Forsyth 		outlen = 0x7FFFFFFF;	/* if we can flush, no output limit */
201*37da2899SCharles.Forsyth 	else if(f->runes)
202*37da2899SCharles.Forsyth 		outlen = (Rune*)f->stop - (Rune*)f->to;
203*37da2899SCharles.Forsyth 	else
204*37da2899SCharles.Forsyth 		outlen = (char*)f->stop - (char*)f->to;
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth 	_quotesetup(s, r, -1, outlen, &q, f->flags&FmtSharp, f->runes);
207*37da2899SCharles.Forsyth //print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout);
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth 	if(runesin){
210*37da2899SCharles.Forsyth 		if(!q.quoted)
211*37da2899SCharles.Forsyth 			return _fmtrcpy(f, r, q.nrunesin);
212*37da2899SCharles.Forsyth 		return qstrfmt(nil, r, &q, f);
213*37da2899SCharles.Forsyth 	}
214*37da2899SCharles.Forsyth 
215*37da2899SCharles.Forsyth 	if(!q.quoted)
216*37da2899SCharles.Forsyth 		return _fmtcpy(f, s, q.nrunesin, q.nbytesin);
217*37da2899SCharles.Forsyth 	return qstrfmt(s, nil, &q, f);
218*37da2899SCharles.Forsyth }
219*37da2899SCharles.Forsyth 
220*37da2899SCharles.Forsyth int
quotestrfmt(Fmt * f)221*37da2899SCharles.Forsyth quotestrfmt(Fmt *f)
222*37da2899SCharles.Forsyth {
223*37da2899SCharles.Forsyth 	return _quotestrfmt(0, f);
224*37da2899SCharles.Forsyth }
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth int
quoterunestrfmt(Fmt * f)227*37da2899SCharles.Forsyth quoterunestrfmt(Fmt *f)
228*37da2899SCharles.Forsyth {
229*37da2899SCharles.Forsyth 	return _quotestrfmt(1, f);
230*37da2899SCharles.Forsyth }
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth void
quotefmtinstall(void)233*37da2899SCharles.Forsyth quotefmtinstall(void)
234*37da2899SCharles.Forsyth {
235*37da2899SCharles.Forsyth 	fmtinstall('q', quotestrfmt);
236*37da2899SCharles.Forsyth 	fmtinstall('Q', quoterunestrfmt);
237*37da2899SCharles.Forsyth }
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth int
_needsquotes(char * s,int * quotelenp)240*37da2899SCharles.Forsyth _needsquotes(char *s, int *quotelenp)
241*37da2899SCharles.Forsyth {
242*37da2899SCharles.Forsyth 	Quoteinfo q;
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth 	_quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
245*37da2899SCharles.Forsyth 	*quotelenp = q.nbytesout;
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth 	return q.quoted;
248*37da2899SCharles.Forsyth }
249*37da2899SCharles.Forsyth 
250*37da2899SCharles.Forsyth int
_runeneedsquotes(Rune * r,int * quotelenp)251*37da2899SCharles.Forsyth _runeneedsquotes(Rune *r, int *quotelenp)
252*37da2899SCharles.Forsyth {
253*37da2899SCharles.Forsyth 	Quoteinfo q;
254*37da2899SCharles.Forsyth 
255*37da2899SCharles.Forsyth 	_quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
256*37da2899SCharles.Forsyth 	*quotelenp = q.nrunesout;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 	return q.quoted;
259*37da2899SCharles.Forsyth }
260