9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

io.c (3755B)


      1 #include "rc.h"
      2 #include "exec.h"
      3 #include "io.h"
      4 #include "fns.h"
      5 int pfmtnest = 0;
      6 
      7 void
      8 pfmt(io *f, char *fmt, ...)
      9 {
     10 	va_list ap;
     11 	char err[ERRMAX];
     12 	va_start(ap, fmt);
     13 	pfmtnest++;
     14 	for(;*fmt;fmt++)
     15 		if(*fmt!='%')
     16 			pchr(f, *fmt);
     17 		else switch(*++fmt){
     18 		case '\0':
     19 			va_end(ap);
     20 			return;
     21 		case 'c':
     22 			pchr(f, va_arg(ap, int));
     23 			break;
     24 		case 'd':
     25 			pdec(f, va_arg(ap, int));
     26 			break;
     27 		case 'o':
     28 			poct(f, va_arg(ap, unsigned));
     29 			break;
     30 		case 'p':
     31 			pptr(f, va_arg(ap, void*));
     32 			break;
     33 		case 'Q':
     34 			pquo(f, va_arg(ap, char *));
     35 			break;
     36 		case 'q':
     37 			pwrd(f, va_arg(ap, char *));
     38 			break;
     39 		case 'r':
     40 			rerrstr(err, sizeof err); pstr(f, err);
     41 			break;
     42 		case 's':
     43 			pstr(f, va_arg(ap, char *));
     44 			break;
     45 		case 't':
     46 			pcmd(f, va_arg(ap, struct tree *));
     47 			break;
     48 		case 'v':
     49 			pval(f, va_arg(ap, struct word *));
     50 			break;
     51 		default:
     52 			pchr(f, *fmt);
     53 			break;
     54 		}
     55 	va_end(ap);
     56 	if(--pfmtnest==0)
     57 		flush(f);
     58 }
     59 
     60 void
     61 pchr(io *b, int c)
     62 {
     63 	if(b->bufp==b->ebuf)
     64 		fullbuf(b, c);
     65 	else *b->bufp++=c;
     66 }
     67 
     68 int
     69 rchr(io *b)
     70 {
     71 	if(b->bufp==b->ebuf)
     72 		return emptybuf(b);
     73 	return *b->bufp++ & 0xFF;
     74 }
     75 
     76 void
     77 pquo(io *f, char *s)
     78 {
     79 	pchr(f, '\'');
     80 	for(;*s;s++)
     81 		if(*s=='\'')
     82 			pfmt(f, "''");
     83 		else pchr(f, *s);
     84 	pchr(f, '\'');
     85 }
     86 
     87 void
     88 pwrd(io *f, char *s)
     89 {
     90 	char *t;
     91 	for(t = s;*t;t++) if(!wordchr(*t)) break;
     92 	if(t==s || *t)
     93 		pquo(f, s);
     94 	else pstr(f, s);
     95 }
     96 
     97 void
     98 pptr(io *f, void *v)
     99 {
    100 	int n;
    101 	uintptr p;
    102 
    103 	p = (uintptr)v;
    104 	if(sizeof(uintptr) == sizeof(uvlong) && p>>32)
    105 		for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
    106 
    107 	for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
    108 }
    109 
    110 void
    111 pstr(io *f, char *s)
    112 {
    113 	if(s==0)
    114 		s="(null)";
    115 	while(*s) pchr(f, *s++);
    116 }
    117 
    118 void
    119 pdec(io *f, int n)
    120 {
    121 	if(n<0){
    122 		n=-n;
    123 		if(n>=0){
    124 			pchr(f, '-');
    125 			pdec(f, n);
    126 			return;
    127 		}
    128 		/* n is two's complement minimum integer */
    129 		n = 1-n;
    130 		pchr(f, '-');
    131 		pdec(f, n/10);
    132 		pchr(f, n%10+'1');
    133 		return;
    134 	}
    135 	if(n>9)
    136 		pdec(f, n/10);
    137 	pchr(f, n%10+'0');
    138 }
    139 
    140 void
    141 poct(io *f, unsigned n)
    142 {
    143 	if(n>7)
    144 		poct(f, n>>3);
    145 	pchr(f, (n&7)+'0');
    146 }
    147 
    148 void
    149 pval(io *f, word *a)
    150 {
    151 	if(a){
    152 		while(a->next && a->next->word){
    153 			pwrd(f, a->word);
    154 			pchr(f, ' ');
    155 			a = a->next;
    156 		}
    157 		pwrd(f, a->word);
    158 	}
    159 }
    160 
    161 int
    162 fullbuf(io *f, int c)
    163 {
    164 	flush(f);
    165 	return *f->bufp++=c;
    166 }
    167 
    168 void
    169 flush(io *f)
    170 {
    171 	int n;
    172 	char *s;
    173 	if(f->strp){
    174 		n = f->ebuf-f->strp;
    175 		f->strp = realloc(f->strp, n+101);
    176 		if(f->strp==0)
    177 			panic("Can't realloc %d bytes in flush!", n+101);
    178 		f->bufp = f->strp+n;
    179 		f->ebuf = f->bufp+100;
    180 		for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
    181 	}
    182 	else{
    183 		n = f->bufp-f->buf;
    184 		if(n && Write(f->fd, f->buf, n) < 0){
    185 			Write(3, "Write error\n", 12);
    186 			if(ntrap)
    187 				dotrap();
    188 		}
    189 		f->bufp = f->buf;
    190 		f->ebuf = f->buf+NBUF;
    191 	}
    192 }
    193 
    194 io*
    195 openfd(int fd)
    196 {
    197 	io *f = new(struct io);
    198 	f->fd = fd;
    199 	f->bufp = f->ebuf = f->buf;
    200 	f->strp = 0;
    201 	return f;
    202 }
    203 
    204 io*
    205 openstr(void)
    206 {
    207 	io *f = new(struct io);
    208 	char *s;
    209 	f->fd=-1;
    210 	f->bufp = f->strp = emalloc(101);
    211 	f->ebuf = f->bufp+100;
    212 	for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
    213 	return f;
    214 }
    215 /*
    216  * Open a corebuffer to read.  EOF occurs after reading len
    217  * characters from buf.
    218  */
    219 
    220 io*
    221 opencore(char *s, int len)
    222 {
    223 	io *f = new(struct io);
    224 	char *buf = emalloc(len);
    225 	f->fd= -1 /*open("/dev/null", 0)*/;
    226 	f->bufp = f->strp = buf;
    227 	f->ebuf = buf+len;
    228 	Memcpy(buf, s, len);
    229 	return f;
    230 }
    231 
    232 void
    233 iorewind(io *io)
    234 {
    235 	if(io->fd==-1)
    236 		io->bufp = io->strp;
    237 	else{
    238 		io->bufp = io->ebuf = io->buf;
    239 		Seek(io->fd, 0L, 0);
    240 	}
    241 }
    242 
    243 void
    244 closeio(io *io)
    245 {
    246 	if(io->fd>=0)
    247 		close(io->fd);
    248 	if(io->strp)
    249 		efree(io->strp);
    250 	efree((char *)io);
    251 }
    252 
    253 int
    254 emptybuf(io *f)
    255 {
    256 	int n;
    257 	if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
    258 	f->bufp = f->buf;
    259 	f->ebuf = f->buf+n;
    260 	return *f->bufp++&0xff;
    261 }