Subversion Repositories planix.SVN

Rev

Rev 2 | Blame | Compare with Previous | Last modification | View Log | RSS feed

#include "rc.h"
#include "exec.h"
#include "io.h"
#include "fns.h"

enum { Stralloc = 100, };

int pfmtnest = 0;

void
pfmt(io *f, char *fmt, ...)
{
        va_list ap;
        char err[ERRMAX];

        va_start(ap, fmt);
        pfmtnest++;
        for(;*fmt;fmt++) {
                if(*fmt!='%') {
                        pchr(f, *fmt);
                        continue;
                }
                if(*++fmt == '\0')              /* "blah%"? */
                        break;
                switch(*fmt){
                case 'c':
                        pchr(f, va_arg(ap, int));
                        break;
                case 'd':
                        pdec(f, va_arg(ap, int));
                        break;
                case 'o':
                        poct(f, va_arg(ap, unsigned));
                        break;
                case 'p':
                        pptr(f, va_arg(ap, void*));
                        break;
                case 'Q':
                        pquo(f, va_arg(ap, char *));
                        break;
                case 'q':
                        pwrd(f, va_arg(ap, char *));
                        break;
                case 'r':
                        errstr(err, sizeof err); pstr(f, err);
                        break;
                case 's':
                        pstr(f, va_arg(ap, char *));
                        break;
                case 't':
                        pcmd(f, va_arg(ap, struct tree *));
                        break;
                case 'v':
                        pval(f, va_arg(ap, struct word *));
                        break;
                default:
                        pchr(f, *fmt);
                        break;
                }
        }
        va_end(ap);
        if(--pfmtnest==0)
                flush(f);
}

void
pchr(io *b, int c)
{
        if(b->bufp==b->ebuf)
                fullbuf(b, c);
        else *b->bufp++=c;
}

int
rchr(io *b)
{
        if(b->bufp==b->ebuf)
                return emptybuf(b);
        return *b->bufp++;
}

int
rutf(io *b, char *buf, Rune *r)
{
        int n, i, c;

        c = rchr(b);
        if(c == EOF)
                return EOF;
        *buf = c;
        if(c < Runesync){
                *r = c;
                return 1;
        }
        for(i = 1; (c = rchr(b)) != EOF; ){
                buf[i++] = c;
                buf[i] = 0;
                if(fullrune(buf, i)){
                        n = chartorune(r, buf);
                        b->bufp -= i - n;       /* push back unconsumed bytes */
                        assert(b->fd == -1 || b->bufp > b->buf);
                        return n;
                }
        }
        /* at eof */
        b->bufp -= i - 1;                       /* consume 1 byte */
        *r = Runeerror;
        return runetochar(buf, r);
}

void
pquo(io *f, char *s)
{
        pchr(f, '\'');
        for(;*s;s++)
                if(*s=='\'')
                        pfmt(f, "''");
                else pchr(f, *s);
        pchr(f, '\'');
}

void
pwrd(io *f, char *s)
{
        char *t;
        for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break;
        if(t==s || *t)
                pquo(f, s);
        else pstr(f, s);
}

void
pptr(io *f, void *v)
{
        int n;
        uintptr p;

        p = (uintptr)v;
        if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
                for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);

        for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
}

void
pstr(io *f, char *s)
{
        if(s==0)
                s="(null)";
        while(*s) pchr(f, *s++);
}

void
pdec(io *f, int n)
{
        if(n<0){
                n=-n;
                if(n>=0){
                        pchr(f, '-');
                        pdec(f, n);
                        return;
                }
                /* n is two's complement minimum integer */
                n = 1-n;
                pchr(f, '-');
                pdec(f, n/10);
                pchr(f, n%10+'1');
                return;
        }
        if(n>9)
                pdec(f, n/10);
        pchr(f, n%10+'0');
}

void
poct(io *f, unsigned n)
{
        if(n>7)
                poct(f, n>>3);
        pchr(f, (n&7)+'0');
}

void
pval(io *f, word *a)
{
        if(a){
                while(a->next && a->next->word){
                        pwrd(f, (char *)a->word);
                        pchr(f, ' ');
                        a = a->next;
                }
                pwrd(f, (char *)a->word);
        }
}

int
fullbuf(io *f, int c)
{
        flush(f);
        return *f->bufp++=c;
}

void
flush(io *f)
{
        int n;

        if(f->strp){
                n = f->ebuf - f->strp;
                f->strp = realloc(f->strp, n+Stralloc+1);
                if(f->strp==0)
                        panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
                f->bufp = f->strp + n;
                f->ebuf = f->bufp + Stralloc;
                memset(f->bufp, '\0', Stralloc+1);
        }
        else{
                n = f->bufp-f->buf;
                if(n && Write(f->fd, f->buf, n) != n){
                        Write(2, "Write error\n", 12);
                        if(ntrap)
                                dotrap();
                }
                f->bufp = f->buf;
                f->ebuf = f->buf+NBUF;
        }
}

io*
openfd(int fd)
{
        io *f = new(struct io);
        f->fd = fd;
        f->bufp = f->ebuf = f->buf;
        f->strp = 0;
        return f;
}

io*
openstr(void)
{
        io *f = new(struct io);

        f->fd = -1;
        f->bufp = f->strp = emalloc(Stralloc+1);
        f->ebuf = f->bufp + Stralloc;
        memset(f->bufp, '\0', Stralloc+1);
        return f;
}
/*
 * Open a corebuffer to read.  EOF occurs after reading len
 * characters from buf.
 */

io*
opencore(char *s, int len)
{
        io *f = new(struct io);
        uchar *buf = emalloc(len);

        f->fd = -1 /*open("/dev/null", 0)*/;
        f->bufp = f->strp = buf;
        f->ebuf = buf+len;
        Memcpy(buf, s, len);
        return f;
}

void
rewind(io *io)
{
        if(io->fd==-1)
                io->bufp = io->strp;
        else{
                io->bufp = io->ebuf = io->buf;
                Seek(io->fd, 0L, 0);
        }
}

void
closeio(io *io)
{
        if(io->fd>=0)
                close(io->fd);
        if(io->strp)
                efree(io->strp);
        efree(io);
}

int
emptybuf(io *f)
{
        int n;
        if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
        f->bufp = f->buf;
        f->ebuf = f->buf + n;
        return *f->bufp++;
}