URI: 
       tfmtquote.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tfmtquote.c (3609B)
       ---
            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 <u.h>
           15 #include <libc.h>
           16 #include "fmt.h"
           17 #include "fmtdef.h"
           18 
           19 extern int (*doquote)(int);
           20 
           21 /*
           22  * How many bytes of output UTF will be produced by quoting (if necessary) this string?
           23  * How many runes? How much of the input will be consumed?
           24  * The parameter q is filled in by _quotesetup.
           25  * The string may be UTF or Runes (s or r).
           26  * Return count does not include NUL.
           27  * Terminate the scan at the first of:
           28  *        NUL in input
           29  *        count exceeded in input
           30  *        count exceeded on output
           31  * *ninp is set to number of input bytes accepted.
           32  * nin may be <0 initially, to avoid checking input by count.
           33  */
           34 void
           35 __quotesetup(char *s, int nin, int nout, Quoteinfo *q, int sharp)
           36 {
           37         int 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=='\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-=1){
           52                 c = *s;
           53 
           54                 if(c == '\0')
           55                         break;
           56                 if(q->nrunesout+1 > nout)
           57                         break;
           58 
           59                 if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){
           60                         if(!q->quoted){
           61                                 if(1+q->nrunesout+1+1 > nout)        /* no room for quotes */
           62                                         break;
           63                                 q->nrunesout += 2;        /* include quotes */
           64                                 q->nbytesout += 2;        /* include quotes */
           65                                 q->quoted = 1;
           66                         }
           67                         if(c == '\'')        {
           68                                 q->nbytesout++;
           69                                 q->nrunesout++;        /* quotes reproduce as two characters */
           70                         }
           71                 }
           72 
           73                 /* advance input */
           74                 s++;
           75                 q->nbytesin++;
           76                 q->nrunesin++;
           77 
           78                 /* advance output */
           79                 q->nbytesout++;
           80                 q->nrunesout++;
           81         }
           82 }
           83 
           84 static int
           85 qstrfmt(char *sin, Quoteinfo *q, Fmt *f)
           86 {
           87         int r;
           88         char *t, *s, *m, *me;
           89         ulong fl;
           90         int nc, w;
           91 
           92         m = sin;
           93         me = m + q->nbytesin;
           94 
           95         w = f->width;
           96         fl = f->flags;
           97         if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
           98                 return -1;
           99         t = f->to;
          100         s = f->stop;
          101         FMTCHAR(f, t, s, '\'');
          102         for(nc = q->nrunesin; nc > 0; nc--){
          103                 r = *(uchar*)m++;
          104                 FMTCHAR(f, t, s, r);
          105                 if(r == '\'')
          106                         FMTCHAR(f, t, s, r);
          107         }
          108 
          109         FMTCHAR(f, t, s, '\'');
          110         f->nfmt += t - (char *)f->to;
          111         f->to = t;
          112         if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
          113                 return -1;
          114         return 0;
          115 }
          116 
          117 int
          118 __quotestrfmt(int runesin, Fmt *f)
          119 {
          120         int outlen;
          121         char *s;
          122         Quoteinfo q;
          123 
          124         f->flags &= ~FmtPrec;        /* ignored for %q %Q, so disable for %s %S in easy case */
          125         s = va_arg(f->args, char *);
          126         if(!s)
          127                 return __fmtcpy(f, "<nil>", 5, 5);
          128 
          129         if(f->flush)
          130                 outlen = 0x7FFFFFFF;        /* if we can flush, no output limit */
          131         else
          132                 outlen = (char*)f->stop - (char*)f->to;
          133 
          134         __quotesetup(s, -1, outlen, &q, f->flags&FmtSharp);
          135 
          136         if(!q.quoted)
          137                 return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
          138         return qstrfmt(s, &q, f);
          139 }
          140 
          141 int
          142 quotestrfmt(Fmt *f)
          143 {
          144         return __quotestrfmt(0, f);
          145 }
          146 
          147 void
          148 quotefmtinstall(void)
          149 {
          150         fmtinstall('q', quotestrfmt);
          151 }
          152 
          153 int
          154 __needsquotes(char *s, int *quotelenp)
          155 {
          156         Quoteinfo q;
          157 
          158         __quotesetup(s, -1, 0x7FFFFFFF, &q, 0);
          159         *quotelenp = q.nbytesout;
          160 
          161         return q.quoted;
          162 }