wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

fmtquote.c (5588B)


      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
     11  * ANY 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 "plan9.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--){
     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 	fl = f->flags;
    124 	w = 0;
    125 	if(fl & FmtWidth)
    126 		w = f->width;
    127 	if(f->runes){
    128 		if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
    129 			return -1;
    130 	}else{
    131 		if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
    132 			return -1;
    133 	}
    134 	t = (char*)f->to;
    135 	s = (char*)f->stop;
    136 	rt = (Rune*)f->to;
    137 	rs = (Rune*)f->stop;
    138 	if(f->runes)
    139 		FMTRCHAR(f, rt, rs, '\'');
    140 	else
    141 		FMTRUNE(f, t, s, '\'');
    142 	for(nc = q->nrunesin; nc > 0; nc--){
    143 		if(sin){
    144 			r = *(uchar*)m;
    145 			if(r < Runeself)
    146 				m++;
    147 			else if((me - m) >= UTFmax || fullrune(m, me-m))
    148 				m += chartorune(&r, m);
    149 			else
    150 				break;
    151 		}else{
    152 			if(rm >= rme)
    153 				break;
    154 			r = *(uchar*)rm++;
    155 		}
    156 		if(f->runes){
    157 			FMTRCHAR(f, rt, rs, r);
    158 			if(r == '\'')
    159 				FMTRCHAR(f, rt, rs, r);
    160 		}else{
    161 			FMTRUNE(f, t, s, r);
    162 			if(r == '\'')
    163 				FMTRUNE(f, t, s, r);
    164 		}
    165 	}
    166 
    167 	if(f->runes){
    168 		FMTRCHAR(f, rt, rs, '\'');
    169 		USED(rs);
    170 		f->nfmt += rt - (Rune *)f->to;
    171 		f->to = rt;
    172 		if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
    173 			return -1;
    174 	}else{
    175 		FMTRUNE(f, t, s, '\'');
    176 		USED(s);
    177 		f->nfmt += t - (char *)f->to;
    178 		f->to = t;
    179 		if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
    180 			return -1;
    181 	}
    182 	return 0;
    183 }
    184 
    185 int
    186 __quotestrfmt(int runesin, Fmt *f)
    187 {
    188 	int nin, outlen;
    189 	Rune *r;
    190 	char *s;
    191 	Quoteinfo q;
    192 
    193 	nin = -1;
    194 	if(f->flags&FmtPrec)
    195 		nin = f->prec;
    196 	if(runesin){
    197 		r = va_arg(f->args, Rune *);
    198 		s = nil;
    199 	}else{
    200 		s = va_arg(f->args, char *);
    201 		r = nil;
    202 	}
    203 	if(!s && !r)
    204 		return __fmtcpy(f, (void*)"<nil>", 5, 5);
    205 
    206 	if(f->flush)
    207 		outlen = 0x7FFFFFFF;	/* if we can flush, no output limit */
    208 	else if(f->runes)
    209 		outlen = (Rune*)f->stop - (Rune*)f->to;
    210 	else
    211 		outlen = (char*)f->stop - (char*)f->to;
    212 
    213 	__quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
    214 /*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */
    215 
    216 	if(runesin){
    217 		if(!q.quoted)
    218 			return __fmtrcpy(f, r, q.nrunesin);
    219 		return qstrfmt(nil, r, &q, f);
    220 	}
    221 
    222 	if(!q.quoted)
    223 		return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
    224 	return qstrfmt(s, nil, &q, f);
    225 }
    226 
    227 int
    228 quotestrfmt(Fmt *f)
    229 {
    230 	return __quotestrfmt(0, f);
    231 }
    232 
    233 int
    234 quoterunestrfmt(Fmt *f)
    235 {
    236 	return __quotestrfmt(1, f);
    237 }
    238 
    239 void
    240 quotefmtinstall(void)
    241 {
    242 	fmtinstall('q', quotestrfmt);
    243 	fmtinstall('Q', quoterunestrfmt);
    244 }
    245 
    246 int
    247 __needsquotes(char *s, int *quotelenp)
    248 {
    249 	Quoteinfo q;
    250 
    251 	__quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
    252 	*quotelenp = q.nbytesout;
    253 
    254 	return q.quoted;
    255 }
    256 
    257 int
    258 __runeneedsquotes(Rune *r, int *quotelenp)
    259 {
    260 	Quoteinfo q;
    261 
    262 	__quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
    263 	*quotelenp = q.nrunesout;
    264 
    265 	return q.quoted;
    266 }