n2.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
n2.c (5055B) | |
--- | |
1 /* | |
2 * n2.c | |
3 * | |
4 * output, cleanup | |
5 */ | |
6 | |
7 #define _BSD_SOURCE 1 /* popen */ | |
8 #include "tdef.h" | |
9 #include "fns.h" | |
10 #include "ext.h" | |
11 #include <setjmp.h> | |
12 | |
13 #ifdef STRICT | |
14 /* not in ANSI or POSIX */ | |
15 FILE* popen(char*, char*); | |
16 #endif | |
17 | |
18 | |
19 extern jmp_buf sjbuf; | |
20 int toolate; | |
21 int error; | |
22 | |
23 char obuf[2*BUFSIZ]; | |
24 char *obufp = obuf; | |
25 | |
26 /* pipe command structure; allows redicously long commends for .… | |
27 struct Pipe { | |
28 char *buf; | |
29 int tick; | |
30 int cnt; | |
31 } Pipe; | |
32 | |
33 | |
34 int xon = 0; /* records if in middle of \X */ | |
35 | |
36 int pchar(Tchar i) | |
37 { | |
38 int j; | |
39 static int hx = 0; /* records if have seen HX */ | |
40 | |
41 if (hx) { | |
42 hx = 0; | |
43 j = absmot(i); | |
44 if (isnmot(i)) { | |
45 if (j > dip->blss) | |
46 dip->blss = j; | |
47 } else { | |
48 if (j > dip->alss) | |
49 dip->alss = j; | |
50 ralss = dip->alss; | |
51 } | |
52 return 0; | |
53 } | |
54 if (ismot(i)) { | |
55 pchar1(i); | |
56 return 0; | |
57 } | |
58 switch (j = cbits(i)) { | |
59 case 0: | |
60 case IMP: | |
61 case RIGHT: | |
62 case LEFT: | |
63 return 0; | |
64 case HX: | |
65 hx = 1; | |
66 return 0; | |
67 case XON: | |
68 xon++; | |
69 break; | |
70 case XOFF: | |
71 xon--; | |
72 break; | |
73 case PRESC: | |
74 if (!xon && !tflg && dip == &d[0]) | |
75 j = eschar; /* fall through */ | |
76 default: | |
77 setcbits(i, trtab[j]); | |
78 } | |
79 if (NROFF & xon) /* rob fix for man2html */ | |
80 return 0; | |
81 pchar1(i); | |
82 return 0; | |
83 } | |
84 | |
85 | |
86 void pchar1(Tchar i) | |
87 { | |
88 int j; | |
89 | |
90 j = cbits(i); | |
91 if (dip != &d[0]) { | |
92 wbf(i); | |
93 dip->op = offset; | |
94 return; | |
95 } | |
96 if (!tflg && !print) { | |
97 if (j == '\n') | |
98 dip->alss = dip->blss = 0; | |
99 return; | |
100 } | |
101 if (j == FILLER && !xon) | |
102 return; | |
103 if (tflg) { /* transparent mode, undiverted */ | |
104 if (print) /* assumes that it's o… | |
105 /* OUT "%c", j PUT; /* i.e., is ascii */ | |
106 outascii(i); | |
107 return; | |
108 } | |
109 if (TROFF && ascii) | |
110 outascii(i); | |
111 else | |
112 ptout(i); | |
113 } | |
114 | |
115 | |
116 void outweird(int k) /* like ptchname() but ascii */ | |
117 { | |
118 char *chn = chname(k); | |
119 | |
120 switch (chn[0]) { | |
121 case MBchar: | |
122 OUT "%s", chn+1 PUT; /* \n not needed? */ | |
123 break; | |
124 case Number: | |
125 OUT "\\N'%s'", chn+1 PUT; | |
126 break; | |
127 case Troffchar: | |
128 if (strlen(chn+1) == 2) | |
129 OUT "\\(%s", chn+1 PUT; | |
130 else | |
131 OUT "\\C'%s'", chn+1 PUT; | |
132 break; | |
133 default: | |
134 OUT " %s? ", chn PUT; | |
135 break; | |
136 } | |
137 } | |
138 | |
139 void outascii(Tchar i) /* print i in best-guess ascii */ | |
140 { | |
141 int j = cbits(i); | |
142 | |
143 /* is this ever called with NROFF set? probably doesn't work at all. */ | |
144 | |
145 if (ismot(i)) | |
146 oput(' '); | |
147 else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t') | |
148 oput(j); | |
149 else if (j == DRAWFCN) | |
150 oputs("\\D"); | |
151 else if (j == HYPHEN) | |
152 oput('-'); | |
153 else if (j == MINUS) /* special pleading for strange enco… | |
154 oputs("\\-"); | |
155 else if (j == PRESC) | |
156 oputs("\\e"); | |
157 else if (j == FILLER) | |
158 oputs("\\&"); | |
159 else if (j == UNPAD) | |
160 oputs("\\ "); | |
161 else if (j == OHC) /* this will never occur; stripped ou… | |
162 oputs("\\%"); | |
163 else if (j == XON) | |
164 oputs("\\X"); | |
165 else if (j == XOFF) | |
166 oputs(" "); | |
167 else if (j == LIG_FI) | |
168 oputs("fi"); | |
169 else if (j == LIG_FL) | |
170 oputs("fl"); | |
171 else if (j == LIG_FF) | |
172 oputs("ff"); | |
173 else if (j == LIG_FFI) | |
174 oputs("ffi"); | |
175 else if (j == LIG_FFL) | |
176 oputs("ffl"); | |
177 else if (j == WORDSP) { /* nothing at all */ | |
178 if (xon) /* except in \X */ | |
179 oput(' '); | |
180 | |
181 } else | |
182 outweird(j); | |
183 } | |
184 | |
185 int flusho(void) | |
186 { | |
187 if (NROFF && !toolate && t.twinit) | |
188 fwrite(t.twinit, strlen(t.twinit), 1, ptid); | |
189 | |
190 if (obufp > obuf) { | |
191 if (pipeflg && !toolate) { | |
192 /* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); … | |
193 if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")… | |
194 ERROR "pipe %s not created.", Pipe.buf W… | |
195 if (Pipe.buf) | |
196 free(Pipe.buf); | |
197 } | |
198 if (!toolate) | |
199 toolate++; | |
200 *obufp = 0; | |
201 fputs(obuf, ptid); | |
202 fflush(ptid); | |
203 obufp = obuf; | |
204 } | |
205 return 1; | |
206 } | |
207 | |
208 | |
209 void caseex(void) | |
210 { | |
211 done(0); | |
212 } | |
213 | |
214 | |
215 void done(int x) | |
216 { | |
217 int i; | |
218 | |
219 error |= x; | |
220 app = ds = lgf = 0; | |
221 if (i = em) { | |
222 donef = -1; | |
223 eschar = '\\'; | |
224 em = 0; | |
225 if (control(i, 0)) | |
226 longjmp(sjbuf, 1); | |
227 } | |
228 if (!nfo) | |
229 done3(0); | |
230 mflg = 0; | |
231 dip = &d[0]; | |
232 if (woff) /* BUG!!! This isn't set anywhere */ | |
233 wbf((Tchar)0); | |
234 if (pendw) | |
235 getword(1); | |
236 pendnf = 0; | |
237 if (donef == 1) | |
238 done1(0); | |
239 donef = 1; | |
240 ip = 0; | |
241 frame = stk; | |
242 nxf = frame + 1; | |
243 if (!ejf) | |
244 tbreak(); | |
245 nflush++; | |
246 eject((Stack *)0); | |
247 longjmp(sjbuf, 1); | |
248 } | |
249 | |
250 | |
251 void done1(int x) | |
252 { | |
253 error |= x; | |
254 if (numtabp[NL].val) { | |
255 trap = 0; | |
256 eject((Stack *)0); | |
257 longjmp(sjbuf, 1); | |
258 } | |
259 if (!ascii) | |
260 pttrailer(); | |
261 done2(0); | |
262 } | |
263 | |
264 | |
265 void done2(int x) | |
266 { | |
267 ptlead(); | |
268 if (TROFF && !ascii) | |
269 ptstop(); | |
270 flusho(); | |
271 done3(x); | |
272 } | |
273 | |
274 void done3(int x) | |
275 { | |
276 error |= x; | |
277 flusho(); | |
278 if (NROFF) | |
279 twdone(); | |
280 if (pipeflg) | |
281 pclose(ptid); | |
282 exit(error); | |
283 } | |
284 | |
285 | |
286 void edone(int x) | |
287 { | |
288 frame = stk; | |
289 nxf = frame + 1; | |
290 ip = 0; | |
291 done(x); | |
292 } | |
293 | |
294 | |
295 void casepi(void) | |
296 { | |
297 int j; | |
298 char buf[NTM]; | |
299 | |
300 if (Pipe.buf == NULL) { | |
301 if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NU… | |
302 ERROR "No buf space for pipe cmd" WARN; | |
303 return; | |
304 } | |
305 Pipe.tick = 1; | |
306 } else | |
307 Pipe.buf[Pipe.cnt++] = '|'; | |
308 | |
309 getline(buf, NTM); | |
310 j = strlen(buf); | |
311 if (toolate) { | |
312 ERROR "Cannot create pipe to %s", buf WARN; | |
313 return; | |
314 } | |
315 Pipe.cnt += j; | |
316 if (j >= NTM +1) { | |
317 Pipe.tick++; | |
318 if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NT… | |
319 ERROR "No more buf space for pipe cmd" WARN; | |
320 return; | |
321 } | |
322 } | |
323 strcat(Pipe.buf, buf); | |
324 pipeflg++; | |
325 } |