fmtquote.c - 9base - revived minimalist port of Plan 9 userland to Unix
 (HTM) git clone git://git.suckless.org/9base
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       fmtquote.c (5023B)
       ---
            1 /* Copyright (c) 2002-2006 Lucent Technologies; see LICENSE */
            2 #include <stdarg.h>
            3 #include <string.h>
            4 #include "plan9.h"
            5 #include "fmt.h"
            6 #include "fmtdef.h"
            7 
            8 /*
            9  * How many bytes of output UTF will be produced by quoting (if necessary) this string?
           10  * How many runes? How much of the input will be consumed?
           11  * The parameter q is filled in by __quotesetup.
           12  * The string may be UTF or Runes (s or r).
           13  * Return count does not include NUL.
           14  * Terminate the scan at the first of:
           15  *        NUL in input
           16  *        count exceeded in input
           17  *        count exceeded on output
           18  * *ninp is set to number of input bytes accepted.
           19  * nin may be <0 initially, to avoid checking input by count.
           20  */
           21 void
           22 __quotesetup(char *s, Rune *r, int nin, int nout, Quoteinfo *q, int sharp, int runesout)
           23 {
           24         int w;
           25         Rune c;
           26 
           27         q->quoted = 0;
           28         q->nbytesout = 0;
           29         q->nrunesout = 0;
           30         q->nbytesin = 0;
           31         q->nrunesin = 0;
           32         if(sharp || nin==0 || (s && *s=='\0') || (r && *r=='\0')){
           33                 if(nout < 2)
           34                         return;
           35                 q->quoted = 1;
           36                 q->nbytesout = 2;
           37                 q->nrunesout = 2;
           38         }
           39         for(; nin!=0; nin--){
           40                 if(s)
           41                         w = chartorune(&c, s);
           42                 else{
           43                         c = *r;
           44                         w = runelen(c);
           45                 }
           46 
           47                 if(c == '\0')
           48                         break;
           49                 if(runesout){
           50                         if(q->nrunesout+1 > nout)
           51                                 break;
           52                 }else{
           53                         if(q->nbytesout+w > nout)
           54                                 break;
           55                 }
           56 
           57                 if((c <= L' ') || (c == L'\'') || (fmtdoquote!=nil && fmtdoquote(c))){
           58                         if(!q->quoted){
           59                                 if(runesout){
           60                                         if(1+q->nrunesout+1+1 > nout)        /* no room for quotes */
           61                                                 break;
           62                                 }else{
           63                                         if(1+q->nbytesout+w+1 > nout)        /* no room for quotes */
           64                                                 break;
           65                                 }
           66                                 q->nrunesout += 2;        /* include quotes */
           67                                 q->nbytesout += 2;        /* include quotes */
           68                                 q->quoted = 1;
           69                         }
           70                         if(c == '\'')        {
           71                                 if(runesout){
           72                                         if(1+q->nrunesout+1 > nout)        /* no room for quotes */
           73                                                 break;
           74                                 }else{
           75                                         if(1+q->nbytesout+w > nout)        /* no room for quotes */
           76                                                 break;
           77                                 }
           78                                 q->nbytesout++;
           79                                 q->nrunesout++;        /* quotes reproduce as two characters */
           80                         }
           81                 }
           82 
           83                 /* advance input */
           84                 if(s)
           85                         s += w;
           86                 else
           87                         r++;
           88                 q->nbytesin += w;
           89                 q->nrunesin++;
           90 
           91                 /* advance output */
           92                 q->nbytesout += w;
           93                 q->nrunesout++;
           94 
           95 #ifndef PLAN9PORT
           96                 /* ANSI requires precision in bytes, not Runes. */
           97                 nin-= w-1;        /* and then n-- in the loop */
           98 #endif
           99         }
          100 }
          101 
          102 static int
          103 qstrfmt(char *sin, Rune *rin, Quoteinfo *q, Fmt *f)
          104 {
          105         Rune r, *rm, *rme;
          106         char *t, *s, *m, *me;
          107         Rune *rt, *rs;
          108         ulong fl;
          109         int nc, w;
          110 
          111         m = sin;
          112         me = m + q->nbytesin;
          113         rm = rin;
          114         rme = rm + q->nrunesin;
          115 
          116         fl = f->flags;
          117         w = 0;
          118         if(fl & FmtWidth)
          119                 w = f->width;
          120         if(f->runes){
          121                 if(!(fl & FmtLeft) && __rfmtpad(f, w - q->nrunesout) < 0)
          122                         return -1;
          123         }else{
          124                 if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
          125                         return -1;
          126         }
          127         t = (char*)f->to;
          128         s = (char*)f->stop;
          129         rt = (Rune*)f->to;
          130         rs = (Rune*)f->stop;
          131         if(f->runes)
          132                 FMTRCHAR(f, rt, rs, '\'');
          133         else
          134                 FMTRUNE(f, t, s, '\'');
          135         for(nc = q->nrunesin; nc > 0; nc--){
          136                 if(sin){
          137                         r = *(uchar*)m;
          138                         if(r < Runeself)
          139                                 m++;
          140                         else if((me - m) >= UTFmax || fullrune(m, me-m))
          141                                 m += chartorune(&r, m);
          142                         else
          143                                 break;
          144                 }else{
          145                         if(rm >= rme)
          146                                 break;
          147                         r = *(uchar*)rm++;
          148                 }
          149                 if(f->runes){
          150                         FMTRCHAR(f, rt, rs, r);
          151                         if(r == '\'')
          152                                 FMTRCHAR(f, rt, rs, r);
          153                 }else{
          154                         FMTRUNE(f, t, s, r);
          155                         if(r == '\'')
          156                                 FMTRUNE(f, t, s, r);
          157                 }
          158         }
          159 
          160         if(f->runes){
          161                 FMTRCHAR(f, rt, rs, '\'');
          162                 USED(rs);
          163                 f->nfmt += rt - (Rune *)f->to;
          164                 f->to = rt;
          165                 if(fl & FmtLeft && __rfmtpad(f, w - q->nrunesout) < 0)
          166                         return -1;
          167         }else{
          168                 FMTRUNE(f, t, s, '\'');
          169                 USED(s);
          170                 f->nfmt += t - (char *)f->to;
          171                 f->to = t;
          172                 if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
          173                         return -1;
          174         }
          175         return 0;
          176 }
          177 
          178 int
          179 __quotestrfmt(int runesin, Fmt *f)
          180 {
          181         int nin, outlen;
          182         Rune *r;
          183         char *s;
          184         Quoteinfo q;
          185 
          186         nin = -1;
          187         if(f->flags&FmtPrec)
          188                 nin = f->prec;
          189         if(runesin){
          190                 r = va_arg(f->args, Rune *);
          191                 s = nil;
          192         }else{
          193                 s = va_arg(f->args, char *);
          194                 r = nil;
          195         }
          196         if(!s && !r)
          197                 return __fmtcpy(f, (void*)"<nil>", 5, 5);
          198 
          199         if(f->flush)
          200                 outlen = 0x7FFFFFFF;        /* if we can flush, no output limit */
          201         else if(f->runes)
          202                 outlen = (Rune*)f->stop - (Rune*)f->to;
          203         else
          204                 outlen = (char*)f->stop - (char*)f->to;
          205 
          206         __quotesetup(s, r, nin, outlen, &q, f->flags&FmtSharp, f->runes);
          207 /*print("bytes in %d bytes out %d runes in %d runesout %d\n", q.nbytesin, q.nbytesout, q.nrunesin, q.nrunesout); */
          208 
          209         if(runesin){
          210                 if(!q.quoted)
          211                         return __fmtrcpy(f, r, q.nrunesin);
          212                 return qstrfmt(nil, r, &q, f);
          213         }
          214 
          215         if(!q.quoted)
          216                 return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
          217         return qstrfmt(s, nil, &q, f);
          218 }
          219 
          220 int
          221 quotestrfmt(Fmt *f)
          222 {
          223         return __quotestrfmt(0, f);
          224 }
          225 
          226 int
          227 quoterunestrfmt(Fmt *f)
          228 {
          229         return __quotestrfmt(1, f);
          230 }
          231 
          232 void
          233 quotefmtinstall(void)
          234 {
          235         fmtinstall('q', quotestrfmt);
          236         fmtinstall('Q', quoterunestrfmt);
          237 }
          238 
          239 int
          240 __needsquotes(char *s, int *quotelenp)
          241 {
          242         Quoteinfo q;
          243 
          244         __quotesetup(s, nil, -1, 0x7FFFFFFF, &q, 0, 0);
          245         *quotelenp = q.nbytesout;
          246 
          247         return q.quoted;
          248 }
          249 
          250 int
          251 __runeneedsquotes(Rune *r, int *quotelenp)
          252 {
          253         Quoteinfo q;
          254 
          255         __quotesetup(nil, r, -1, 0x7FFFFFFF, &q, 0, 0);
          256         *quotelenp = q.nrunesout;
          257 
          258         return q.quoted;
          259 }