Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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