xref: /plan9-contrib/sys/src/cmd/rc/io.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include "rc.h"
2 #include "exec.h"
3 #include "io.h"
4 #include "fns.h"
5 int pfmtnest=0;
6 void pfmt(io *f, char *fmt, ...){
7 	va_list ap;
8 	char err[ERRMAX];
9 	va_start(ap, fmt);
10 	pfmtnest++;
11 	for(;*fmt;fmt++)
12 		if(*fmt!='%') pchr(f, *fmt);
13 		else switch(*++fmt){
14 		case '\0': va_end(ap); return;
15 		case 'c': pchr(f, va_arg(ap, int)); break;
16 		case 'd': pdec(f, va_arg(ap, int)); break;
17 		case 'o': poct(f, va_arg(ap, unsigned)); break;
18 		case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/
19 		case 'Q': pquo(f, va_arg(ap, char *)); break;
20 		case 'q': pwrd(f, va_arg(ap, char *)); break;
21 		case 'r': errstr(err, sizeof err); pstr(f, err); break;
22 		case 's': pstr(f, va_arg(ap, char *)); break;
23 		case 't': pcmd(f, va_arg(ap, struct tree *)); break;
24 		case 'v': pval(f, va_arg(ap, struct word *)); break;
25 		default: pchr(f, *fmt); break;
26 		}
27 	va_end(ap);
28 	if(--pfmtnest==0) flush(f);
29 }
30 void pchr(io *b, int c)
31 {
32 	if(b->bufp==b->ebuf) fullbuf(b, c);
33 	else *b->bufp++=c;
34 }
35 int rchr(io *b)
36 {
37 	if(b->bufp==b->ebuf) return emptybuf(b);
38 	return *b->bufp++ & 0xFF;
39 }
40 void pquo(io *f, char *s)
41 {
42 	pchr(f, '\'');
43 	for(;*s;s++)
44 		if(*s=='\'') pfmt(f, "''");
45 		else pchr(f, *s);
46 	pchr(f, '\'');
47 }
48 void pwrd(io *f, char *s)
49 {
50 	char *t;
51 	for(t=s;*t;t++) if(!wordchr(*t)) break;
52 	if(t==s || *t) pquo(f, s);
53 	else pstr(f, s);
54 }
55 void phex(io *f, long p)
56 {
57 	int n;
58 	for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
59 }
60 void pstr(io *f, char *s)
61 {
62 	if(s==0) s="(null)";
63 	while(*s) pchr(f, *s++);
64 }
65 void pdec(io *f, long n)
66 {
67 	if(n<0){
68 		n=-n;
69 		if(n>=0){
70 			pchr(f, '-');
71 			pdec(f, n);
72 			return;
73 		}
74 		/* n is two's complement minimum integer */
75 		n=1-n;
76 		pchr(f, '-');
77 		pdec(f, n/10);
78 		pchr(f, n%10+'1');
79 		return;
80 	}
81 	if(n>9) pdec(f, n/10);
82 	pchr(f, n%10+'0');
83 }
84 void poct(io *f, ulong n)
85 {
86 	if(n>7) poct(f, n>>3);
87 	pchr(f, (n&7)+'0');
88 }
89 void pval(io *f, word *a)
90 {
91 	if(a){
92 		while(a->next && a->next->word){
93 			pwrd(f, a->word);
94 			pchr(f, ' ');
95 			a=a->next;
96 		}
97 		pwrd(f, a->word);
98 	}
99 }
100 int fullbuf(io *f, int c)
101 {
102 	flush(f);
103 	return *f->bufp++=c;
104 }
105 void flush(io *f)
106 {
107 	int n;
108 	char *s;
109 	if(f->strp){
110 		n=f->ebuf-f->strp;
111 		f->strp=realloc(f->strp, n+101);
112 		if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101);
113 		f->bufp=f->strp+n;
114 		f->ebuf=f->bufp+100;
115 		for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
116 	}
117 	else{
118 		n=f->bufp-f->buf;
119 		if(n && Write(f->fd, f->buf, n) < 0){
120 			Write(3, "Write error\n", 12);
121 			if(ntrap) dotrap();
122 		}
123 		f->bufp=f->buf;
124 		f->ebuf=f->buf+NBUF;
125 	}
126 }
127 io *openfd(int fd){
128 	io *f=new(struct io);
129 	f->fd=fd;
130 	f->bufp=f->ebuf=f->buf;
131 	f->strp=0;
132 	return f;
133 }
134 io *openstr(void){
135 	io *f=new(struct io);
136 	char *s;
137 	f->fd=-1;
138 	f->bufp=f->strp=emalloc(101);
139 	f->ebuf=f->bufp+100;
140 	for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
141 	return f;
142 }
143 /*
144  * Open a corebuffer to read.  EOF occurs after reading len
145  * characters from buf.
146  */
147 io *opencore(char *s, int len)
148 {
149 	io *f=new(struct io);
150 	char *buf=emalloc(len);
151 	f->fd= -1 /*open("/dev/null", 0)*/;
152 	f->bufp=f->strp=buf;
153 	f->ebuf=buf+len;
154 	Memcpy(buf, s, len);
155 	return f;
156 }
157 void rewind(io *io)
158 {
159 	if(io->fd==-1) io->bufp=io->strp;
160 	else{
161 		io->bufp=io->ebuf=io->buf;
162 		Seek(io->fd, 0L, 0);
163 	}
164 }
165 void closeio(io *io)
166 {
167 	if(io->fd>=0) close(io->fd);
168 	if(io->strp) efree(io->strp);
169 	efree((char *)io);
170 }
171 int emptybuf(io *f)
172 {
173 	int n;
174 	if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF;
175 	f->bufp=f->buf;
176 	f->ebuf=f->buf+n;
177 	return *f->bufp++&0xff;
178 }
179