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