]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/fmt/fmtquote.c
sdiahci, sdodin: avoid calling kproc() while holding ilock()
[plan9front.git] / sys / src / ape / lib / fmt / fmtquote.c
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 }