19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
3*59c21d95SDavid du Colombier #include <ctype.h>
49a747e4fSDavid du Colombier
59a747e4fSDavid du Colombier int
encodefmt(Fmt * f)69a747e4fSDavid du Colombier encodefmt(Fmt *f)
79a747e4fSDavid du Colombier {
89a747e4fSDavid du Colombier char *out;
99a747e4fSDavid du Colombier char *buf;
109a747e4fSDavid du Colombier int len;
119a747e4fSDavid du Colombier int ilen;
129a747e4fSDavid du Colombier int rv;
139a747e4fSDavid du Colombier uchar *b;
14*59c21d95SDavid du Colombier char *p;
159a747e4fSDavid du Colombier char obuf[64]; // rsc optimization
169a747e4fSDavid du Colombier
179a747e4fSDavid du Colombier if(!(f->flags&FmtPrec) || f->prec < 1)
189a747e4fSDavid du Colombier goto error;
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier b = va_arg(f->args, uchar*);
217fd46167SDavid du Colombier if(b == 0)
227fd46167SDavid du Colombier return fmtstrcpy(f, "<nil>");
239a747e4fSDavid du Colombier
249a747e4fSDavid du Colombier ilen = f->prec;
259a747e4fSDavid du Colombier f->prec = 0;
269a747e4fSDavid du Colombier f->flags &= ~FmtPrec;
279a747e4fSDavid du Colombier switch(f->r){
289a747e4fSDavid du Colombier case '<':
299a747e4fSDavid du Colombier len = (8*ilen+4)/5 + 3;
309a747e4fSDavid du Colombier break;
319a747e4fSDavid du Colombier case '[':
329a747e4fSDavid du Colombier len = (8*ilen+5)/6 + 4;
339a747e4fSDavid du Colombier break;
349a747e4fSDavid du Colombier case 'H':
359a747e4fSDavid du Colombier len = 2*ilen + 1;
369a747e4fSDavid du Colombier break;
379a747e4fSDavid du Colombier default:
389a747e4fSDavid du Colombier goto error;
399a747e4fSDavid du Colombier }
409a747e4fSDavid du Colombier
419a747e4fSDavid du Colombier if(len > sizeof(obuf)){
429a747e4fSDavid du Colombier buf = malloc(len);
439a747e4fSDavid du Colombier if(buf == nil)
449a747e4fSDavid du Colombier goto error;
459a747e4fSDavid du Colombier } else
469a747e4fSDavid du Colombier buf = obuf;
479a747e4fSDavid du Colombier
489a747e4fSDavid du Colombier // convert
499a747e4fSDavid du Colombier out = buf;
509a747e4fSDavid du Colombier switch(f->r){
519a747e4fSDavid du Colombier case '<':
529a747e4fSDavid du Colombier rv = enc32(out, len, b, ilen);
539a747e4fSDavid du Colombier break;
549a747e4fSDavid du Colombier case '[':
559a747e4fSDavid du Colombier rv = enc64(out, len, b, ilen);
569a747e4fSDavid du Colombier break;
579a747e4fSDavid du Colombier case 'H':
589a747e4fSDavid du Colombier rv = enc16(out, len, b, ilen);
59*59c21d95SDavid du Colombier if(rv >= 0 && (f->flags & FmtLong))
60*59c21d95SDavid du Colombier for(p = buf; *p; p++)
61*59c21d95SDavid du Colombier *p = tolower(*p);
629a747e4fSDavid du Colombier break;
639a747e4fSDavid du Colombier default:
649a747e4fSDavid du Colombier rv = -1;
659a747e4fSDavid du Colombier break;
669a747e4fSDavid du Colombier }
679a747e4fSDavid du Colombier if(rv < 0)
689a747e4fSDavid du Colombier goto error;
699a747e4fSDavid du Colombier
709a747e4fSDavid du Colombier fmtstrcpy(f, buf);
719a747e4fSDavid du Colombier if(buf != obuf)
729a747e4fSDavid du Colombier free(buf);
739a747e4fSDavid du Colombier return 0;
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier error:
769a747e4fSDavid du Colombier return fmtstrcpy(f, "<encodefmt>");
779a747e4fSDavid du Colombier }
78