123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /*
- * The authors of this software are Rob Pike and Ken Thompson.
- * Copyright (c) 2002 by Lucent Technologies.
- * Permission to use, copy, modify, and distribute this software for any
- * purpose without fee is hereby granted, provided that this entire notice
- * is included in all copies of any software which is or includes a copy
- * or modification of this software and in all copies of the supporting
- * documentation for such software.
- * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
- * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
- * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
- */
- #include <u.h>
- #include <libc.h>
- #include "fmt.h"
- #include "fmtdef.h"
- extern int (*doquote)(int);
- /*
- * How many bytes of output UTF will be produced by quoting (if necessary) this string?
- * How many runes? How much of the input will be consumed?
- * The parameter q is filled in by _quotesetup.
- * The string may be UTF or Runes (s or r).
- * Return count does not include NUL.
- * Terminate the scan at the first of:
- * NUL in input
- * count exceeded in input
- * count exceeded on output
- * *ninp is set to number of input bytes accepted.
- * nin may be <0 initially, to avoid checking input by count.
- */
- void
- __quotesetup(char *s, int nin, int nout, Quoteinfo *q, int sharp)
- {
- int c;
- q->quoted = 0;
- q->nbytesout = 0;
- q->nrunesout = 0;
- q->nbytesin = 0;
- q->nrunesin = 0;
- if(sharp || nin==0 || *s=='\0'){
- if(nout < 2)
- return;
- q->quoted = 1;
- q->nbytesout = 2;
- q->nrunesout = 2;
- }
- for(; nin!=0; nin-=1){
- c = *s;
- if(c == '\0')
- break;
- if(q->nrunesout+1 > nout)
- break;
- if((c <= L' ') || (c == L'\'') || (doquote!=nil && doquote(c))){
- if(!q->quoted){
- if(1+q->nrunesout+1+1 > nout) /* no room for quotes */
- break;
- q->nrunesout += 2; /* include quotes */
- q->nbytesout += 2; /* include quotes */
- q->quoted = 1;
- }
- if(c == '\'') {
- q->nbytesout++;
- q->nrunesout++; /* quotes reproduce as two characters */
- }
- }
- /* advance input */
- s++;
- q->nbytesin++;
- q->nrunesin++;
- /* advance output */
- q->nbytesout++;
- q->nrunesout++;
- }
- }
- static int
- qstrfmt(char *sin, Quoteinfo *q, Fmt *f)
- {
- int r;
- char *t, *s, *m, *me;
- ulong fl;
- int nc, w;
- m = sin;
- me = m + q->nbytesin;
- w = f->width;
- fl = f->flags;
- if(!(fl & FmtLeft) && __fmtpad(f, w - q->nbytesout) < 0)
- return -1;
- t = f->to;
- s = f->stop;
- FMTCHAR(f, t, s, '\'');
- for(nc = q->nrunesin; nc > 0; nc--){
- r = *(uchar*)m++;
- FMTCHAR(f, t, s, r);
- if(r == '\'')
- FMTCHAR(f, t, s, r);
- }
- FMTCHAR(f, t, s, '\'');
- f->nfmt += t - (char *)f->to;
- f->to = t;
- if(fl & FmtLeft && __fmtpad(f, w - q->nbytesout) < 0)
- return -1;
- return 0;
- }
- int
- __quotestrfmt(int runesin, Fmt *f)
- {
- int outlen;
- char *s;
- Quoteinfo q;
- f->flags &= ~FmtPrec; /* ignored for %q %Q, so disable for %s %S in easy case */
- s = va_arg(f->args, char *);
- if(!s)
- return __fmtcpy(f, "<nil>", 5, 5);
- if(f->flush)
- outlen = 0x7FFFFFFF; /* if we can flush, no output limit */
- else
- outlen = (char*)f->stop - (char*)f->to;
- __quotesetup(s, -1, outlen, &q, f->flags&FmtSharp);
- if(!q.quoted)
- return __fmtcpy(f, s, q.nrunesin, q.nbytesin);
- return qstrfmt(s, &q, f);
- }
- int
- quotestrfmt(Fmt *f)
- {
- return __quotestrfmt(0, f);
- }
- void
- quotefmtinstall(void)
- {
- fmtinstall('q', quotestrfmt);
- }
- int
- __needsquotes(char *s, int *quotelenp)
- {
- Quoteinfo q;
- __quotesetup(s, -1, 0x7FFFFFFF, &q, 0);
- *quotelenp = q.nbytesout;
- return q.quoted;
- }
|