0
|
1 /*
|
|
2 * CDDL HEADER START
|
|
3 *
|
|
4 * The contents of this file are subject to the terms of the
|
|
5 * Common Development and Distribution License, Version 1.0 only
|
|
6 * (the "License"). You may not use this file except in compliance
|
|
7 * with the License.
|
|
8 *
|
|
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
|
|
10 * or http://www.opensolaris.org/os/licensing.
|
|
11 * See the License for the specific language governing permissions
|
|
12 * and limitations under the License.
|
|
13 *
|
|
14 * When distributing Covered Code, include this CDDL HEADER in each
|
|
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
|
16 * If applicable, add the following below this CDDL HEADER, with the
|
|
17 * fields enclosed by brackets "[]" replaced with your own identifying
|
|
18 * information: Portions Copyright [yyyy] [name of copyright owner]
|
|
19 *
|
|
20 * CDDL HEADER END
|
|
21 */
|
|
22 /*
|
|
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
|
|
24 * Use is subject to license terms.
|
|
25 */
|
|
26
|
|
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
|
|
28 /* All Rights Reserved */
|
|
29
|
|
30 #pragma ident "@(#)bfs.c 1.15 05/07/26 SMI"
|
|
31
|
|
32 #include <setjmp.h>
|
|
33 #include <signal.h>
|
|
34 #include <stdlib.h>
|
|
35 #include <regexpr.h>
|
|
36 #include <limits.h>
|
|
37 #include <sys/types.h>
|
|
38 #include <unistd.h>
|
|
39 #include <sys/stat.h>
|
|
40 #include <locale.h>
|
|
41 #include <stdio.h>
|
|
42 #include <string.h>
|
|
43 #include <wait.h>
|
|
44 #include <fcntl.h>
|
|
45 int setjmp();
|
|
46 static jmp_buf env;
|
|
47
|
|
48 extern int scrwidth(wchar_t);
|
|
49
|
|
50 #define BRKTYP char
|
|
51 #define BRKSIZ 8192
|
|
52 #define BRKTWO 4
|
|
53 #define BFSAND
|
|
54 #define BFSLIM 511
|
|
55 #define BFSTRU 511
|
|
56 #define BFSBUF 512
|
|
57
|
|
58 struct Comd {
|
|
59 int Cnumadr;
|
|
60 int Cadr[2];
|
|
61 char Csep;
|
|
62 char Cop;
|
|
63 };
|
|
64
|
|
65 static int Dot, Dollar;
|
|
66 static int markarray[26], *mark;
|
|
67 static int fstack[15] = {1, -1};
|
|
68 static int infildes = 0;
|
|
69 static int outfildes = 1;
|
|
70 static char internal[512], *intptr;
|
|
71 static char comdlist[100];
|
|
72 static char *endds;
|
|
73 static char charbuf = '\n';
|
|
74 static int peeked;
|
|
75 static char currex[100];
|
|
76 static int trunc = BFSTRU;
|
|
77 static int crunch = -1;
|
|
78 static int segblk[512], segoff[512], txtfd, prevblk, prevoff;
|
|
79 static int oldfd = 0;
|
|
80 static int flag4 = 0;
|
|
81 static int flag3 = 0;
|
|
82 static int flag2 = 0;
|
|
83 static int flag1 = 0;
|
|
84 static int flag = 0;
|
|
85 static int lprev = 1;
|
|
86 static int status[1];
|
|
87 static BRKTYP *lincnt;
|
|
88 static char *perbuf;
|
|
89 static char *rebuf;
|
|
90 static char *glbuf;
|
|
91 static char tty, *bigfile;
|
|
92 static char fle[80];
|
|
93 static char prompt = 1;
|
|
94 static char verbose = 1; /* 1=print # of bytes read in; 0=silent. */
|
|
95 static char varray[10][100]; /* Holds xv cmd parameters. */
|
|
96 static double outcnt;
|
|
97 static char strtmp[32];
|
|
98
|
|
99 static void reset();
|
|
100 static void begin(struct Comd *p);
|
|
101 static int bigopen(char file[]);
|
|
102 static void sizeprt(int blk, int off);
|
|
103 static void bigread(int l, char rec[]);
|
|
104 static int gcomd(struct Comd *p, int k);
|
|
105 static int fcomd(struct Comd *p);
|
|
106 static void ecomd();
|
|
107 static int kcomd(struct Comd *p);
|
|
108 static int xncomd(struct Comd *p);
|
|
109 static int pcomd(struct Comd *p);
|
|
110 static int qcomd();
|
|
111 static int xcomds(struct Comd *p);
|
|
112 static int xbcomd(struct Comd *p);
|
|
113 static int xccomd(struct Comd *p);
|
|
114 static int xfcomd(struct Comd *p);
|
|
115 static int xocomd(struct Comd *p);
|
|
116 static int xtcomd(struct Comd *p);
|
|
117 static int xvcomd();
|
|
118 static int wcomd(struct Comd *p);
|
|
119 static int nlcomd(struct Comd *p);
|
|
120 static int eqcomd(struct Comd *p);
|
|
121 static int colcomd(struct Comd *p);
|
|
122 static int excomd();
|
|
123 static int xcomdlist(struct Comd *p);
|
|
124 static int defaults(struct Comd *p, int prt, int max,
|
|
125 int def1, int def2, int setdot, int errsok);
|
|
126 static int getcomd(struct Comd *p, int prt);
|
|
127 static int getadrs(struct Comd *p, int prt);
|
|
128 static int getadr(struct Comd *p, int prt);
|
|
129 static int getnumb(struct Comd *p, int prt);
|
|
130 static int rdnumb(int prt);
|
|
131 static int getrel(struct Comd *p, int prt);
|
|
132 static int getmark(struct Comd *p, int prt);
|
|
133 static int getrex(struct Comd *p, int prt, char c);
|
|
134 static int hunt(int prt, char rex[], int start, int down, int wrap, int errsok);
|
|
135 static int jump(int prt, char label[]);
|
|
136 static int getstr(int prt, char buf[], char brk, char ignr, int nonl);
|
|
137 static int regerr(int c);
|
|
138 static int err(int prt, char msg[]);
|
|
139 static char mygetc();
|
|
140 static int readc(int f, char *c);
|
|
141 static int percent(char line[256]);
|
|
142 static int newfile(int prt, char f[]);
|
|
143 static void push(int s[], int d);
|
|
144 static int pop(int s[]);
|
|
145 static int peekc();
|
|
146 static void eat();
|
|
147 static int more();
|
|
148 static void quit();
|
|
149 static void out(char *ln);
|
|
150 static char *untab(char l[]);
|
|
151 static int patoi(char *b);
|
|
152 static int equal(char *a, char *b);
|
|
153
|
|
154 int
|
|
155 main(int argc, char *argv[])
|
|
156 {
|
|
157 struct Comd comdstruct, *p;
|
|
158 (void) setlocale(LC_ALL, "");
|
|
159 if (argc < 2 || argc > 3) {
|
|
160 (void) err(1, "arg count");
|
|
161 quit();
|
|
162 }
|
|
163 mark = markarray-'a';
|
|
164 if (argc == 3) {
|
|
165 verbose = 0;
|
|
166 }
|
|
167 setbuf(stdout, 0);
|
|
168 if (bigopen(bigfile = argv[argc-1]))
|
|
169 quit();
|
|
170 tty = isatty(0);
|
|
171 p = &comdstruct;
|
|
172 /* Look for 0 or more non-'%' char followed by a '%' */
|
|
173 perbuf = compile("[^%]*%", (char *)0, (char *)0);
|
|
174 if (regerrno)
|
|
175 (void) regerr(regerrno);
|
|
176 (void) setjmp(env);
|
|
177 #if defined(__STDC__)
|
|
178 (void) signal(SIGINT, (void (*)(int))reset);
|
|
179 #else
|
|
180 (void) signal(SIGINT, reset);
|
|
181 #endif
|
|
182 (void) err(0, "");
|
|
183 (void) printf("\n");
|
|
184 flag = 0;
|
|
185 prompt = 0;
|
|
186 /*CONSTCOND*/ for (;;)
|
|
187 begin(p);
|
|
188
|
|
189 /* NOTREACHED */
|
|
190 return (0);
|
|
191 }
|
|
192
|
|
193 static void
|
|
194 reset() /* for longjmp on signal */
|
|
195 {
|
|
196 longjmp(env, 1);
|
|
197 }
|
|
198
|
|
199 static void
|
|
200 begin(struct Comd *p)
|
|
201 {
|
|
202 char line[256];
|
|
203 strtagn:
|
|
204 if (flag == 0)
|
|
205 eat();
|
|
206 if (infildes != 100) {
|
|
207 if (infildes == 0 && prompt)
|
|
208 (void) printf("*");
|
|
209 flag3 = 1;
|
|
210 if (getstr(1, line, 0, 0, 0))
|
|
211 exit(1);
|
|
212 flag3 = 0;
|
|
213 if (percent(line) < 0)
|
|
214 goto strtagn;
|
|
215 (void) newfile(1, "");
|
|
216 }
|
|
217 if (!(getcomd(p, 1) < 0)) {
|
|
218 switch (p->Cop) {
|
|
219 case 'e':
|
|
220 if (!flag)
|
|
221 ecomd();
|
|
222 else
|
|
223 (void) err(0, "");
|
|
224 break;
|
|
225
|
|
226 case 'f':
|
|
227 (void) fcomd(p);
|
|
228 break;
|
|
229
|
|
230 case 'g':
|
|
231 if (flag == 0)
|
|
232 (void) gcomd(p, 1);
|
|
233 else
|
|
234 (void) err(0, "");
|
|
235 break;
|
|
236
|
|
237 case 'k':
|
|
238 (void) kcomd(p);
|
|
239 break;
|
|
240
|
|
241 case 'p':
|
|
242 (void) pcomd(p);
|
|
243 break;
|
|
244
|
|
245 case 'q':
|
|
246 (void) qcomd();
|
|
247 break;
|
|
248
|
|
249 case 'v':
|
|
250 if (flag == 0)
|
|
251 (void) gcomd(p, 0);
|
|
252 else
|
|
253 (void) err(0, "");
|
|
254 break;
|
|
255
|
|
256 case 'x':
|
|
257 if (!flag)
|
|
258 (void) xcomds(p);
|
|
259 else
|
|
260 (void) err(0, "");
|
|
261 break;
|
|
262
|
|
263 case 'w':
|
|
264 (void) wcomd(p);
|
|
265 break;
|
|
266
|
|
267 case '\n':
|
|
268 (void) nlcomd(p);
|
|
269 break;
|
|
270
|
|
271 case '=':
|
|
272 (void) eqcomd(p);
|
|
273 break;
|
|
274
|
|
275 case ':':
|
|
276 (void) colcomd(p);
|
|
277 break;
|
|
278
|
|
279 case '!':
|
|
280 (void) excomd();
|
|
281 break;
|
|
282
|
|
283 case 'P':
|
|
284 prompt = !prompt;
|
|
285 break;
|
|
286
|
|
287 default:
|
|
288 if (flag)
|
|
289 (void) err(0, "");
|
|
290 else
|
|
291 (void) err(1, "bad command");
|
|
292 break;
|
|
293 }
|
|
294 }
|
|
295 }
|
|
296
|
|
297 static int
|
|
298 bigopen(char file[])
|
|
299 {
|
|
300 int l, off, cnt;
|
|
301 int blk, newline, n, s;
|
|
302 char block[512];
|
|
303 size_t totsiz;
|
|
304 BRKTYP *tptr;
|
|
305 if ((txtfd = open(file, 0)) < 0)
|
|
306 return (err(1, "can't open"));
|
|
307 blk = -1;
|
|
308 newline = 1;
|
|
309 l = cnt = s = 0;
|
|
310 off = 512;
|
|
311 totsiz = 0;
|
|
312 if ((lincnt = (BRKTYP *)malloc(BRKSIZ)) == (BRKTYP *)NULL)
|
|
313 return (err(1, "too many lines"));
|
|
314 endds = (BRKTYP *)lincnt;
|
|
315 totsiz += BRKSIZ;
|
|
316 while ((n = read(txtfd, block, 512)) > 0) {
|
|
317 blk++;
|
|
318 for (off = 0; off < n; off++) {
|
|
319 if (newline) {
|
|
320 newline = 0;
|
|
321 if (l > 0 && !(l&07777)) {
|
|
322 totsiz += BRKSIZ;
|
|
323 tptr = (BRKTYP *)
|
|
324 realloc(lincnt, totsiz);
|
|
325 if (tptr == NULL)
|
|
326 return
|
|
327 (err(1, "too many lines"));
|
|
328 else
|
|
329 lincnt = tptr;
|
|
330 }
|
|
331 lincnt[l] = (char)cnt;
|
|
332 cnt = 0;
|
|
333 if (!(l++ & 077)) {
|
|
334 segblk[s] = blk;
|
|
335 segoff[s++] = off;
|
|
336 }
|
|
337 if (l < 0 || l > 32767)
|
|
338 return (err(1, "too many lines"));
|
|
339 }
|
|
340 if (block[off] == '\n') newline = 1;
|
|
341 cnt++;
|
|
342 }
|
|
343 }
|
|
344 if (!(l&07777)) {
|
|
345 totsiz += BRKTWO;
|
|
346 tptr = (BRKTYP *)realloc(lincnt, totsiz);
|
|
347 if (tptr == NULL)
|
|
348 return (err(1, "too many lines"));
|
|
349 else
|
|
350 lincnt = tptr;
|
|
351 }
|
|
352 lincnt[Dot = Dollar = l] = (char)cnt;
|
|
353 sizeprt(blk, off);
|
|
354 return (0);
|
|
355 }
|
|
356
|
|
357 static void
|
|
358 sizeprt(int blk, int off)
|
|
359 {
|
|
360 if (verbose)
|
|
361 (void) printf("%.0f", 512.*blk+off);
|
|
362 }
|
|
363
|
|
364 static int saveblk = -1;
|
|
365
|
|
366 static void
|
|
367 bigread(int l, char rec[])
|
|
368 {
|
|
369 int i;
|
|
370 char *r, *b;
|
|
371 int off;
|
|
372 static char savetxt[512];
|
|
373
|
|
374 if ((i = l-lprev) == 1) prevoff += lincnt[lprev]BFSAND;
|
|
375 else if (i >= 0 && i <= 32)
|
|
376 for (i = lprev; i < l; i++) prevoff += lincnt[i]BFSAND;
|
|
377 else if (i < 0 && i >= -32)
|
|
378 for (i = lprev-1; i >= l; i--) prevoff -= lincnt[i]BFSAND;
|
|
379 else {
|
|
380 prevblk = segblk[i = (l-1)>>6];
|
|
381 prevoff = segoff[i];
|
|
382 for (i = (i<<6)+1; i < l; i++) prevoff += lincnt[i]BFSAND;
|
|
383 }
|
|
384
|
|
385 prevblk += prevoff>>9;
|
|
386 prevoff &= 0777;
|
|
387 lprev = l;
|
|
388 if (prevblk != saveblk) {
|
|
389 (void) lseek(txtfd, ((long)(saveblk = prevblk))<<9, 0);
|
|
390 (void) read(txtfd, savetxt, 512);
|
|
391 }
|
|
392 r = rec;
|
|
393 off = prevoff;
|
|
394 /*CONSTCOND*/while (1) {
|
|
395 for (b = savetxt+off; b < savetxt+512; b++) {
|
|
396 if ((*r++ = *b) == '\n') {
|
|
397 *(r-1) = '\0';
|
|
398 return;
|
|
399 }
|
|
400 if (((unsigned)r - (unsigned)rec) > BFSLIM) {
|
|
401
|
|
402 (void) write(2,
|
|
403 "Line too long--output truncated\n", 32);
|
|
404 return;
|
|
405 }
|
|
406 }
|
|
407 (void) read(txtfd, savetxt, 512);
|
|
408 off = 0;
|
|
409 saveblk++;
|
|
410 }
|
|
411 }
|
|
412
|
|
413 static void
|
|
414 ecomd()
|
|
415 {
|
|
416 int i = 0;
|
|
417 while (peekc() == ' ')
|
|
418 (void) mygetc();
|
|
419 while ((fle[i++] = mygetc()) != '\n');
|
|
420 fle[--i] = '\0';
|
|
421 /* Without this, ~20 "e" cmds gave "can't open" msg. */
|
|
422 (void) close(txtfd);
|
|
423 free(endds);
|
|
424 /* Reset parameters. */
|
|
425 lprev = 1;
|
|
426 prevblk = 0;
|
|
427 prevoff = 0;
|
|
428 saveblk = -1;
|
|
429 if (bigopen(bigfile = fle))
|
|
430 quit();
|
|
431 (void) printf("\n");
|
|
432 }
|
|
433
|
|
434 static int
|
|
435 fcomd(struct Comd *p)
|
|
436 {
|
|
437 if (more() || defaults(p, 1, 0, 0, 0, 0, 0))
|
|
438 return (-1);
|
|
439 (void) printf("%s\n", bigfile);
|
|
440 return (0);
|
|
441 }
|
|
442
|
|
443 static int
|
|
444 gcomd(struct Comd *p, int k)
|
|
445 {
|
|
446 char d;
|
|
447 int i, end;
|
|
448 char line[BFSBUF];
|
|
449 if (defaults(p, 1, 2, 1, Dollar, 0, 0))
|
|
450 return (-1);
|
|
451 if ((d = mygetc()) == '\n')
|
|
452 return (err(1, "syntax"));
|
|
453 if (peekc() == d)
|
|
454 (void) mygetc();
|
|
455 else
|
|
456 if (getstr(1, currex, d, 0, 1))
|
|
457 return (-1);
|
|
458 glbuf = compile(currex, (char *)0, (char *)0);
|
|
459 if (regerrno) {
|
|
460 (void) regerr(regerrno);
|
|
461 return (-1);
|
|
462 } else {
|
|
463 if (glbuf)
|
|
464 free(glbuf);
|
|
465 }
|
|
466
|
|
467 if (getstr(1, comdlist, 0, 0, 0))
|
|
468 return (-1);
|
|
469 i = p->Cadr[0];
|
|
470 end = p->Cadr[1];
|
|
471 while (i <= end) {
|
|
472 bigread(i, line);
|
|
473 if (!(step(line, glbuf))) {
|
|
474 if (!k) {
|
|
475 Dot = i;
|
|
476 if (xcomdlist(p))
|
|
477 return (err(1, "bad comd list"));
|
|
478 }
|
|
479 i++;
|
|
480 } else {
|
|
481 if (k) {
|
|
482 Dot = i;
|
|
483 if (xcomdlist(p))
|
|
484 return (err(1, "bad comd list"));
|
|
485 }
|
|
486 i++;
|
|
487 }
|
|
488 }
|
|
489 return (0);
|
|
490 }
|
|
491
|
|
492 static int
|
|
493 kcomd(struct Comd *p)
|
|
494 {
|
|
495 char c;
|
|
496 if ((c = peekc()) < 'a' || c > 'z')
|
|
497 return (err(1, "bad mark"));
|
|
498 (void) mygetc();
|
|
499 if (more() || defaults(p, 1, 1, Dot, 0, 1, 0))
|
|
500 return (-1);
|
|
501 mark[c] = Dot = p->Cadr[0];
|
|
502 return (0);
|
|
503 }
|
|
504
|
|
505 static int
|
|
506 xncomd(struct Comd *p)
|
|
507 {
|
|
508 char c;
|
|
509 if (more() || defaults(p, 1, 0, 0, 0, 0, 0))
|
|
510 return (-1);
|
|
511
|
|
512 for (c = 'a'; c <= 'z'; c++)
|
|
513 if (mark[c])
|
|
514 (void) printf("%c\n", c);
|
|
515
|
|
516 return (0);
|
|
517 }
|
|
518
|
|
519 static int
|
|
520 pcomd(struct Comd *p)
|
|
521 {
|
|
522 int i;
|
|
523 char line[BFSBUF];
|
|
524 if (more() || defaults(p, 1, 2, Dot, Dot, 1, 0))
|
|
525 return (-1);
|
|
526 for (i = p->Cadr[0]; i <= p->Cadr[1] && i > 0; i++) {
|
|
527 bigread(i, line);
|
|
528 out(line);
|
|
529 }
|
|
530 return (0);
|
|
531 }
|
|
532
|
|
533 static int
|
|
534 qcomd()
|
|
535 {
|
|
536 if (more())
|
|
537 return (-1);
|
|
538 quit();
|
|
539 return (0);
|
|
540 }
|
|
541
|
|
542 static int
|
|
543 xcomds(struct Comd *p)
|
|
544 {
|
|
545 switch (mygetc()) {
|
|
546 case 'b': return (xbcomd(p));
|
|
547 case 'c': return (xccomd(p));
|
|
548 case 'f': return (xfcomd(p));
|
|
549 case 'n': return (xncomd(p));
|
|
550 case 'o': return (xocomd(p));
|
|
551 case 't': return (xtcomd(p));
|
|
552 case 'v': return (xvcomd());
|
|
553 default: return (err(1, "bad command"));
|
|
554 }
|
|
555 }
|
|
556
|
|
557 static int
|
|
558 xbcomd(struct Comd *p)
|
|
559 {
|
|
560 int fail, n;
|
|
561 char d;
|
|
562 char str[50];
|
|
563
|
|
564 fail = 0;
|
|
565 if (defaults(p, 0, 2, Dot, Dot, 0, 1))
|
|
566 fail = 1;
|
|
567 else {
|
|
568 if ((d = mygetc()) == '\n')
|
|
569 return (err(1, "syntax"));
|
|
570 if (d == 'z') {
|
|
571 if (status[0] != 0)
|
|
572 return (0);
|
|
573 (void) mygetc();
|
|
574 if (getstr(1, str, 0, 0, 0))
|
|
575 return (-1);
|
|
576 return (jump(1, str));
|
|
577 }
|
|
578 if (d == 'n') {
|
|
579 if (status[0] == 0)
|
|
580 return (0);
|
|
581 (void) mygetc();
|
|
582 if (getstr(1, str, 0, 0, 0))
|
|
583 return (-1);
|
|
584 return (jump(1, str));
|
|
585 }
|
|
586 if (getstr(1, str, d, ' ', 0))
|
|
587 return (-1);
|
|
588 if ((n = hunt(0, str, p->Cadr[0]-1, 1, 0, 1)) < 0)
|
|
589 fail = 1;
|
|
590 if (getstr(1, str, 0, 0, 0))
|
|
591 return (-1);
|
|
592 if (more())
|
|
593 return (err(1, "syntax"));
|
|
594 }
|
|
595 if (!fail) {
|
|
596 Dot = n;
|
|
597 return (jump(1, str));
|
|
598 }
|
|
599 return (0);
|
|
600 }
|
|
601
|
|
602 static int
|
|
603 xccomd(struct Comd *p)
|
|
604 {
|
|
605 char arg[100];
|
|
606 if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 0, 0, 0, 0, 0))
|
|
607 return (-1);
|
|
608 if (equal(arg, ""))
|
|
609 crunch = -crunch;
|
|
610 else if (equal(arg, "0"))
|
|
611 crunch = -1;
|
|
612 else if (equal(arg, "1"))
|
|
613 crunch = 1;
|
|
614 else
|
|
615 return (err(1, "syntax"));
|
|
616
|
|
617 return (0);
|
|
618 }
|
|
619
|
|
620 static int
|
|
621 xfcomd(struct Comd *p)
|
|
622 {
|
|
623 char fl[100];
|
|
624 char *f;
|
|
625 if (defaults(p, 1, 0, 0, 0, 0, 0))
|
|
626 return (-1);
|
|
627
|
|
628 while (peekc() == ' ')
|
|
629 (void) mygetc();
|
|
630 for (f = fl; (*f = mygetc()) != '\n'; f++);
|
|
631 if (f == fl)
|
|
632 return (err(1, "no file"));
|
|
633 *f = '\0';
|
|
634
|
|
635 return (newfile(1, fl));
|
|
636 }
|
|
637
|
|
638 static int
|
|
639 xocomd(struct Comd *p)
|
|
640 {
|
|
641 int fd;
|
|
642 char arg[100];
|
|
643
|
|
644 if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 0, 0, 0, 0, 0))
|
|
645 return (-1);
|
|
646
|
|
647 if (!arg[0]) {
|
|
648 if (outfildes == 1)
|
|
649 return (err(1, "no diversion"));
|
|
650 (void) close(outfildes);
|
|
651 outfildes = 1;
|
|
652 } else {
|
|
653 if (outfildes != 1)
|
|
654 return (err(1, "already diverted"));
|
|
655 if ((fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC,
|
|
656 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))) < 0)
|
|
657 return (err(1, "can't create"));
|
|
658 outfildes = fd;
|
|
659 }
|
|
660 return (0);
|
|
661 }
|
|
662
|
|
663 static int
|
|
664 xtcomd(struct Comd *p)
|
|
665 {
|
|
666 int t;
|
|
667
|
|
668 while (peekc() == ' ')
|
|
669 (void) mygetc();
|
|
670 if ((t = rdnumb(1)) < 0 || more() || defaults(p, 1, 0, 0, 0, 0, 0))
|
|
671 return (-1);
|
|
672
|
|
673 trunc = t;
|
|
674 return (0);
|
|
675 }
|
|
676
|
|
677 static int
|
|
678 xvcomd()
|
|
679 {
|
|
680 char c;
|
|
681 int i;
|
|
682 int temp0, temp1, temp2;
|
|
683 int fildes[2];
|
|
684
|
|
685 if ((c = peekc()) < '0' || c > '9')
|
|
686 return (err(1, "digit required"));
|
|
687 (void) mygetc();
|
|
688 c -= '0';
|
|
689 while (peekc() == ' ')
|
|
690 (void) mygetc();
|
|
691 if (peekc() == '\\')
|
|
692 (void) mygetc();
|
|
693 else if (peekc() == '!') {
|
|
694 if (pipe(fildes) < 0) {
|
|
695 (void) printf("Try again");
|
|
696 return (-1);
|
|
697 }
|
|
698 temp0 = dup(0);
|
|
699 temp1 = dup(1);
|
|
700 temp2 = infildes;
|
|
701 (void) close(0);
|
|
702 (void) dup(fildes[0]);
|
|
703 (void) close(1);
|
|
704 (void) dup(fildes[1]);
|
|
705 (void) close(fildes[0]);
|
|
706 (void) close(fildes[1]);
|
|
707 (void) mygetc();
|
|
708 flag4 = 1;
|
|
709 (void) excomd();
|
|
710 (void) close(1);
|
|
711 infildes = 0;
|
|
712 }
|
|
713 for (i = 0; (varray[c][i] = mygetc()) != '\n'; i++);
|
|
714 varray[c][i] = '\0';
|
|
715 if (flag4) {
|
|
716 infildes = temp2;
|
|
717 (void) close(0);
|
|
718 (void) dup(temp0);
|
|
719 (void) close(temp0);
|
|
720 (void) dup(temp1);
|
|
721 (void) close(temp1);
|
|
722 flag4 = 0;
|
|
723 charbuf = ' ';
|
|
724 }
|
|
725 return (0);
|
|
726 }
|
|
727
|
|
728 static int
|
|
729 wcomd(struct Comd *p)
|
|
730 {
|
|
731 int i, fd, savefd;
|
|
732 int savecrunch, savetrunc;
|
|
733 char arg[100], line[BFSBUF];
|
|
734
|
|
735 if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 2, 1, Dollar, 1, 0))
|
|
736 return (-1);
|
|
737 if (!arg[0])
|
|
738 return (err(1, "no file name"));
|
|
739 if (equal(arg, bigfile))
|
|
740 return (err(1, "no change indicated"));
|
|
741 if ((fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC,
|
|
742 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))) < 0)
|
|
743 return (err(1, "can't create"));
|
|
744
|
|
745 savefd = outfildes;
|
|
746 savetrunc = trunc;
|
|
747 savecrunch = crunch;
|
|
748 outfildes = fd;
|
|
749 trunc = BFSTRU;
|
|
750 crunch = -1;
|
|
751
|
|
752 outcnt = 0;
|
|
753 for (i = p->Cadr[0]; i <= p->Cadr[1] && i > 0; i++) {
|
|
754 bigread(i, line);
|
|
755 out(line);
|
|
756 }
|
|
757 if (verbose)
|
|
758 (void) printf("%.0f\n", outcnt);
|
|
759 (void) close(fd);
|
|
760
|
|
761 outfildes = savefd;
|
|
762 trunc = savetrunc;
|
|
763 crunch = savecrunch;
|
|
764 return (0);
|
|
765 }
|
|
766
|
|
767 static int
|
|
768 nlcomd(struct Comd *p)
|
|
769 {
|
|
770 if (defaults(p, 1, 2, Dot+1, Dot+1, 1, 0)) {
|
|
771 (void) mygetc();
|
|
772 return (-1);
|
|
773 }
|
|
774 return (pcomd(p));
|
|
775 }
|
|
776
|
|
777 static int
|
|
778 eqcomd(struct Comd *p)
|
|
779 {
|
|
780 if (more() || defaults(p, 1, 1, Dollar, 0, 0, 0))
|
|
781 return (-1);
|
|
782 (void) printf("%d\n", p->Cadr[0]);
|
|
783 return (0);
|
|
784 }
|
|
785
|
|
786 static int
|
|
787 colcomd(struct Comd *p)
|
|
788 {
|
|
789 return (defaults(p, 1, 0, 0, 0, 0, 0));
|
|
790 }
|
|
791
|
|
792 static int
|
|
793 xcomdlist(struct Comd *p)
|
|
794 {
|
|
795 flag = 1;
|
|
796 flag2 = 1;
|
|
797 (void) newfile(1, "");
|
|
798 while (flag2)
|
|
799 begin(p);
|
|
800 if (flag == 0)
|
|
801 return (1);
|
|
802 flag = 0;
|
|
803 return (0);
|
|
804 }
|
|
805
|
|
806 static int
|
|
807 excomd()
|
|
808 {
|
|
809 pid_t i;
|
|
810 int j;
|
|
811 if (infildes != 100)
|
|
812 charbuf = '\n';
|
|
813 while ((i = fork()) < (pid_t)0)
|
|
814 (void) sleep(10);
|
|
815 if (i == (pid_t)0) {
|
|
816 /* Guarantees child can be intr. */
|
|
817 (void) signal(SIGINT, SIG_DFL);
|
|
818 if (infildes == 100 || flag4) {
|
|
819 (void) execl("/usr/bin/sh", "sh", "-c", intptr, 0);
|
|
820 exit(0);
|
|
821 }
|
|
822 if (infildes != 0) {
|
|
823 (void) close(0);
|
|
824 (void) dup(infildes);
|
|
825 }
|
|
826 for (j = 3; j < 15; j++) (void) close(j);
|
|
827 (void) execl("/usr/bin/sh", "sh", "-t", 0);
|
|
828 exit(0);
|
|
829 }
|
|
830 (void) signal(SIGINT, SIG_IGN);
|
|
831 while (wait(status) != i);
|
|
832 status[0] = status[0] >> 8;
|
|
833
|
|
834 #if defined(__STDC__)
|
|
835 (void) signal(SIGINT, (void (*)(int))reset);
|
|
836 #else
|
|
837 (void) signal(SIGINT, reset); /* Restore signal to previous status */
|
|
838 #endif
|
|
839
|
|
840 if (((infildes == 0) || ((infildes == 100) &&
|
|
841 (fstack[fstack[0]] == 0)))&& verbose && (!flag4))
|
|
842 (void) printf("!\n");
|
|
843 return (0);
|
|
844 }
|
|
845
|
|
846 static int
|
|
847 defaults(struct Comd *p, int prt, int max,
|
|
848 int def1, int def2, int setdot, int errsok)
|
|
849 {
|
|
850 if (!def1)
|
|
851 def1 = Dot;
|
|
852 if (!def2)
|
|
853 def2 = def1;
|
|
854 if (p->Cnumadr >= max)
|
|
855 return (errsok?-1:err(prt, "adr count"));
|
|
856 if (p->Cnumadr < 0) {
|
|
857 p->Cadr[++p->Cnumadr] = def1;
|
|
858 p->Cadr[++p->Cnumadr] = def2;
|
|
859 } else if (p->Cnumadr < 1)
|
|
860 p->Cadr[++p->Cnumadr] = p->Cadr[0];
|
|
861 if (p->Cadr[0] < 1 || p->Cadr[0] > Dollar ||
|
|
862 p->Cadr[1] < 1 || p->Cadr[1] > Dollar)
|
|
863 return (errsok?-1:err(prt, "range"));
|
|
864 if (p->Cadr[0] > p->Cadr[1])
|
|
865 return (errsok?-1:err(prt, "adr1 > adr2"));
|
|
866 if (setdot)
|
|
867 Dot = p->Cadr[1];
|
|
868 return (0);
|
|
869 }
|
|
870
|
|
871 static int
|
|
872 getcomd(struct Comd *p, int prt)
|
|
873 {
|
|
874 int r;
|
|
875 int c;
|
|
876
|
|
877 p->Cnumadr = -1;
|
|
878 p->Csep = ' ';
|
|
879 switch (c = peekc()) {
|
|
880 case ',':
|
|
881 case ';': p->Cop = mygetc();
|
|
882 return (0);
|
|
883 }
|
|
884
|
|
885 if ((r = getadrs(p, prt)) < 0)
|
|
886 return (r);
|
|
887
|
|
888 if ((c = peekc()) < 0)
|
|
889 return (err(prt, "syntax"));
|
|
890 if (c == '\n')
|
|
891 p->Cop = '\n';
|
|
892 else
|
|
893 p->Cop = mygetc();
|
|
894
|
|
895 return (0);
|
|
896 }
|
|
897
|
|
898 static int
|
|
899 getadrs(struct Comd *p, int prt)
|
|
900 {
|
|
901 int r;
|
|
902 char c;
|
|
903
|
|
904 if ((r = getadr(p, prt)) < 0)
|
|
905 return (r);
|
|
906
|
|
907 switch (c = peekc()) {
|
|
908 case ';':
|
|
909 Dot = p->Cadr[0];
|
|
910 (void) mygetc();
|
|
911 p->Csep = c;
|
|
912 return (getadr(p, prt));
|
|
913 case ',':
|
|
914 (void) mygetc();
|
|
915 p->Csep = c;
|
|
916 return (getadr(p, prt));
|
|
917 }
|
|
918
|
|
919 return (0);
|
|
920 }
|
|
921
|
|
922 static int
|
|
923 getadr(struct Comd *p, int prt)
|
|
924 {
|
|
925 int r;
|
|
926 char c;
|
|
927
|
|
928 r = 0;
|
|
929 while (peekc() == ' ')
|
|
930 (void) mygetc(); /* Ignore leading spaces */
|
|
931 switch (c = peekc()) {
|
|
932 case '\n':
|
|
933 case ',':
|
|
934 case ';': return (0);
|
|
935 case '\'': (void) mygetc();
|
|
936 r = getmark(p, prt);
|
|
937 break;
|
|
938
|
|
939 case '0':
|
|
940 case '1':
|
|
941 case '2':
|
|
942 case '3':
|
|
943 case '4':
|
|
944 case '5':
|
|
945 case '6':
|
|
946 case '7':
|
|
947 case '8':
|
|
948 case '9': r = getnumb(p, prt);
|
|
949 break;
|
|
950 case '.': (void) mygetc();
|
|
951 p->Cadr[++p->Cnumadr] = Dot;
|
|
952 break;
|
|
953 case '+':
|
|
954 case '-': p->Cadr[++p->Cnumadr] = Dot;
|
|
955 break;
|
|
956 case '$': (void) mygetc();
|
|
957 p->Cadr[++p->Cnumadr] = Dollar;
|
|
958 break;
|
|
959 case '^': (void) mygetc();
|
|
960 p->Cadr[++p->Cnumadr] = Dot - 1;
|
|
961 break;
|
|
962 case '/':
|
|
963 case '?':
|
|
964 case '>':
|
|
965 case '<': (void) mygetc();
|
|
966 r = getrex(p, prt, c);
|
|
967 break;
|
|
968 default: return (0);
|
|
969 }
|
|
970
|
|
971 if (r == 0)
|
|
972 r = getrel(p, prt);
|
|
973 return (r);
|
|
974 }
|
|
975
|
|
976 static int
|
|
977 getnumb(struct Comd *p, int prt)
|
|
978 {
|
|
979 int i;
|
|
980
|
|
981 if ((i = rdnumb(prt)) < 0)
|
|
982 return (-1);
|
|
983 p->Cadr[++p->Cnumadr] = i;
|
|
984 return (0);
|
|
985 }
|
|
986
|
|
987 static int
|
|
988 rdnumb(int prt)
|
|
989 {
|
|
990 char num[20], *n;
|
|
991 int i;
|
|
992
|
|
993 n = num;
|
|
994 while ((*n = peekc()) >= '0' && *n <= '9') {
|
|
995 n++;
|
|
996 (void) mygetc();
|
|
997 }
|
|
998
|
|
999 *n = '\0';
|
|
1000 if ((i = patoi(num)) >= 0)
|
|
1001 return (i);
|
|
1002 return (err(prt, "bad num"));
|
|
1003 }
|
|
1004
|
|
1005 static int
|
|
1006 getrel(struct Comd *p, int prt)
|
|
1007 {
|
|
1008 int op, n;
|
|
1009 char c;
|
|
1010 int j;
|
|
1011
|
|
1012 n = 0;
|
|
1013 op = 1;
|
|
1014 while ((c = peekc()) == '+' || c == '-') {
|
|
1015 if (c == '+')
|
|
1016 n++;
|
|
1017 else
|
|
1018 n--;
|
|
1019 (void) mygetc();
|
|
1020 }
|
|
1021 j = n;
|
|
1022 if (n < 0)
|
|
1023 op = -1;
|
|
1024 if (c == '\n')
|
|
1025 p->Cadr[p->Cnumadr] += n;
|
|
1026 else {
|
|
1027 if ((n = rdnumb(0)) > 0 && p->Cnumadr >= 0) {
|
|
1028 p->Cadr[p->Cnumadr] += op*n;
|
|
1029 (void) getrel(p, prt);
|
|
1030 } else {
|
|
1031 p->Cadr[p->Cnumadr] += j;
|
|
1032 }
|
|
1033 }
|
|
1034 return (0);
|
|
1035 }
|
|
1036
|
|
1037 static int
|
|
1038 getmark(struct Comd *p, int prt)
|
|
1039 {
|
|
1040 char c;
|
|
1041
|
|
1042 if ((c = peekc()) < 'a' || c > 'z')
|
|
1043 return (err(prt, "bad mark"));
|
|
1044 (void) mygetc();
|
|
1045
|
|
1046 if (!mark[c])
|
|
1047 return (err(prt, "undefined mark"));
|
|
1048 p->Cadr[++p->Cnumadr] = mark[c];
|
|
1049 return (0);
|
|
1050 }
|
|
1051
|
|
1052 static int
|
|
1053 getrex(struct Comd *p, int prt, char c)
|
|
1054 {
|
|
1055 int down, wrap, start;
|
|
1056
|
|
1057 if (peekc() == c)
|
|
1058 (void) mygetc();
|
|
1059 else if (getstr(prt, currex, c, 0, 1))
|
|
1060 return (-1);
|
|
1061
|
|
1062 switch (c) {
|
|
1063 case '/': down = 1; wrap = 1; break;
|
|
1064 case '?': down = 0; wrap = 1; break;
|
|
1065 case '>': down = 1; wrap = 0; break;
|
|
1066 case '<': down = 0; wrap = 0; break;
|
|
1067 }
|
|
1068
|
|
1069 if (p->Csep == ';')
|
|
1070 start = p->Cadr[0];
|
|
1071 else
|
|
1072 start = Dot;
|
|
1073
|
|
1074 if ((p->Cadr[++p->Cnumadr] = hunt(prt, currex, start, down, wrap, 0))
|
|
1075 < 0)
|
|
1076 return (-1);
|
|
1077 return (0);
|
|
1078 }
|
|
1079
|
|
1080 static int
|
|
1081 hunt(int prt, char rex[], int start, int down, int wrap, int errsok)
|
|
1082 {
|
|
1083 int i, end1, incr;
|
|
1084 int start1, start2;
|
|
1085 char line[BFSBUF];
|
|
1086
|
|
1087 if (down) {
|
|
1088 start1 = start + 1;
|
|
1089 end1 = Dollar;
|
|
1090 start2 = 1;
|
|
1091 incr = 1;
|
|
1092 } else {
|
|
1093 start1 = start - 1;
|
|
1094 end1 = 1;
|
|
1095 start2 = Dollar;
|
|
1096 incr = -1;
|
|
1097 }
|
|
1098
|
|
1099 rebuf = compile(rex, (char *)0, (char *)0);
|
|
1100 if (regerrno)
|
|
1101 (void) regerr(regerrno);
|
|
1102 else
|
|
1103 if (rebuf)
|
|
1104 free(rebuf);
|
|
1105
|
|
1106 for (i = start1; i != end1+incr; i += incr) {
|
|
1107 bigread(i, line);
|
|
1108 if (step(line, rebuf)) {
|
|
1109 return (i);
|
|
1110 }
|
|
1111 }
|
|
1112
|
|
1113 if (!wrap)
|
|
1114 return (errsok?-1:err(prt, "not found"));
|
|
1115
|
|
1116 for (i = start2; i != start1; i += incr) {
|
|
1117 bigread(i, line);
|
|
1118 if (step(line, rebuf)) {
|
|
1119 return (i);
|
|
1120 }
|
|
1121 }
|
|
1122
|
|
1123 return (errsok?-1:err(prt, "not found"));
|
|
1124 }
|
|
1125
|
|
1126 static int
|
|
1127 jump(int prt, char label[])
|
|
1128 {
|
|
1129 char *l;
|
|
1130 char line[256];
|
|
1131
|
|
1132 if (infildes == 0 && tty)
|
|
1133 return (err(prt, "jump on tty"));
|
|
1134 if (infildes == 100)
|
|
1135 intptr = internal;
|
|
1136 else
|
|
1137 (void) lseek(infildes, 0L, 0);
|
|
1138
|
|
1139 (void) snprintf(strtmp,
|
|
1140 sizeof (strtmp) * sizeof (char), "^: *%s$", label);
|
|
1141 rebuf = compile(strtmp, (char *)0, (char *)0);
|
|
1142 if (regerrno) {
|
|
1143 (void) regerr(regerrno);
|
|
1144 return (-1);
|
|
1145 }
|
|
1146
|
|
1147 for (l = line; readc(infildes, l); l++) {
|
|
1148 if (*l == '\n') {
|
|
1149 *l = '\0';
|
|
1150 if (step(line, rebuf)) {
|
|
1151 charbuf = '\n';
|
|
1152 return (peeked = 0);
|
|
1153 }
|
|
1154 l = line - 1;
|
|
1155 }
|
|
1156 }
|
|
1157
|
|
1158 return (err(prt, "label not found"));
|
|
1159 }
|
|
1160
|
|
1161 static int
|
|
1162 getstr(int prt, char buf[], char brk, char ignr, int nonl)
|
|
1163 {
|
|
1164 char *b, c, prevc;
|
|
1165
|
|
1166 prevc = 0;
|
|
1167 for (b = buf; c = peekc(); prevc = c) {
|
|
1168 if (c == '\n') {
|
|
1169 if (prevc == '\\' && (!flag3)) *(b-1) = mygetc();
|
|
1170 else if (prevc == '\\' && flag3) {
|
|
1171 *b++ = mygetc();
|
|
1172 } else if (nonl)
|
|
1173 break;
|
|
1174 else
|
|
1175 return (*b = '\0');
|
|
1176 } else {
|
|
1177 (void) mygetc();
|
|
1178 if (c == brk) {
|
|
1179 if (prevc == '\\') *(b-1) = c;
|
|
1180 else return (*b = '\0');
|
|
1181 } else if (b != buf || c != ignr) *b++ = c;
|
|
1182 }
|
|
1183 }
|
|
1184 return (err(prt, "syntax"));
|
|
1185 }
|
|
1186
|
|
1187 static int
|
|
1188 regerr(int c)
|
|
1189 {
|
|
1190 if (prompt) {
|
|
1191 switch (c) {
|
|
1192 case 11: (void) printf("Range endpoint too large.\n");
|
|
1193 break;
|
|
1194 case 16: (void) printf("Bad number.\n");
|
|
1195 break;
|
|
1196 case 25: (void) printf("``\\digit'' out of range.\n");
|
|
1197 break;
|
|
1198 case 41: (void) printf("No remembered search string.\n");
|
|
1199 break;
|
|
1200 case 42: (void) printf("() imbalance.\n");
|
|
1201 break;
|
|
1202 case 43: (void) printf("Too many (.\n");
|
|
1203 break;
|
|
1204 case 44: (void) printf("More than 2 numbers given in { }.\n");
|
|
1205 break;
|
|
1206 case 45: (void) printf("} expected after \\.\n");
|
|
1207 break;
|
|
1208 case 46: (void) printf("First number exceeds second in { }.\n");
|
|
1209 break;
|
|
1210 case 49: (void) printf("[] imbalance.\n");
|
|
1211 break;
|
|
1212 case 50: (void) printf("Regular expression overflow.\n");
|
|
1213 break;
|
|
1214 case 67: (void) printf("Illegal byte sequence.\n");
|
|
1215 break;
|
|
1216 default: (void) printf("RE error.\n");
|
|
1217 break;
|
|
1218 }
|
|
1219 } else {
|
|
1220 (void) printf("?\n");
|
|
1221 }
|
|
1222 return (-1);
|
|
1223 }
|
|
1224
|
|
1225 static int
|
|
1226 err(int prt, char msg[])
|
|
1227 {
|
|
1228 if (prt) (prompt? (void) printf("%s\n", msg): (void) printf("?\n"));
|
|
1229 if (infildes != 0) {
|
|
1230 infildes = pop(fstack);
|
|
1231 charbuf = '\n';
|
|
1232 peeked = 0;
|
|
1233 flag3 = 0;
|
|
1234 flag2 = 0;
|
|
1235 flag = 0;
|
|
1236 }
|
|
1237 return (-1);
|
|
1238 }
|
|
1239
|
|
1240 static char
|
|
1241 mygetc()
|
|
1242 {
|
|
1243 if (!peeked) {
|
|
1244 while ((!(infildes == oldfd && flag)) && (!flag1) &&
|
|
1245 (!readc(infildes, &charbuf))) {
|
|
1246 if (infildes == 100 && (!flag)) flag1 = 1;
|
|
1247 if ((infildes = pop(fstack)) == -1) quit();
|
|
1248 if ((!flag1) && infildes == 0 && flag3 && prompt)
|
|
1249 (void) printf("*");
|
|
1250 }
|
|
1251 if (infildes == oldfd && flag) flag2 = 0;
|
|
1252 flag1 = 0;
|
|
1253 } else peeked = 0;
|
|
1254 return (charbuf);
|
|
1255 }
|
|
1256
|
|
1257 static int
|
|
1258 readc(int f, char *c)
|
|
1259 {
|
|
1260 if (f == 100) {
|
|
1261 if (!(*c = *intptr++)) {
|
|
1262 intptr--;
|
|
1263 charbuf = '\n';
|
|
1264 return (0);
|
|
1265 }
|
|
1266 } else if (read(f, c, 1) != 1) {
|
|
1267 (void) close(f);
|
|
1268 charbuf = '\n';
|
|
1269 return (0);
|
|
1270 }
|
|
1271 return (1);
|
|
1272 }
|
|
1273
|
|
1274 static int
|
|
1275 percent(char line[256])
|
|
1276 {
|
|
1277 char *lp, *var;
|
|
1278 char *front, *per, c[2], *olp, p[2], fr[256];
|
|
1279 int i, j;
|
|
1280
|
|
1281 per = p;
|
|
1282 var = c;
|
|
1283 front = fr;
|
|
1284 j = 0;
|
|
1285 while (!j) {
|
|
1286 j = 1;
|
|
1287 olp = line;
|
|
1288 intptr = internal;
|
|
1289 while (step(olp, perbuf)) {
|
|
1290 while (loc1 < loc2) *front++ = *loc1++;
|
|
1291 *(--front) = '\0';
|
|
1292 front = fr;
|
|
1293 *per++ = '%';
|
|
1294 *per = '\0';
|
|
1295 per = p;
|
|
1296 *var = *loc2;
|
|
1297 if ((i = 1 + strlen(front)) >= 2 && fr[i-2] == '\\') {
|
|
1298 (void) strcat(front, "");
|
|
1299 --intptr;
|
|
1300 (void) strcat(per, "");
|
|
1301 } else {
|
|
1302 if (!(*var >= '0' && *var <= '9'))
|
|
1303 return (err(1, "usage: %digit"));
|
|
1304 (void) strcat(front, "");
|
|
1305 (void) strcat(varray[*var-'0'], "");
|
|
1306 j = 0;
|
|
1307 loc2++; /* Compensate for removing --lp above */
|
|
1308 }
|
|
1309 olp = loc2;
|
|
1310 }
|
|
1311 (void) strcat(olp, "");
|
|
1312 *intptr = '\0';
|
|
1313 if (!j) {
|
|
1314 intptr = internal;
|
|
1315 lp = line;
|
|
1316 (void)
|
|
1317 strncpy(intptr, lp, sizeof (intptr)*sizeof (char));
|
|
1318 }
|
|
1319 }
|
|
1320 return (0);
|
|
1321 }
|
|
1322
|
|
1323 static int
|
|
1324 newfile(int prt, char f[])
|
|
1325 {
|
|
1326 int fd;
|
|
1327
|
|
1328 if (!*f) {
|
|
1329 if (flag != 0) {
|
|
1330 oldfd = infildes;
|
|
1331 intptr = comdlist;
|
|
1332 } else intptr = internal;
|
|
1333 fd = 100;
|
|
1334 } else if ((fd = open(f, 0)) < 0) {
|
|
1335 (void) snprintf(strtmp, sizeof (strtmp) * sizeof (char),
|
|
1336 "cannot open %s", f);
|
|
1337 return (err(prt, strtmp));
|
|
1338 }
|
|
1339
|
|
1340 push(fstack, infildes);
|
|
1341 if (flag4) oldfd = fd;
|
|
1342 infildes = fd;
|
|
1343 return (peeked = 0);
|
|
1344 }
|
|
1345
|
|
1346 static void
|
|
1347 push(int s[], int d)
|
|
1348 {
|
|
1349 s[++s[0]] = d;
|
|
1350 }
|
|
1351
|
|
1352 static int
|
|
1353 pop(int s[])
|
|
1354 {
|
|
1355 return (s[s[0]--]);
|
|
1356 }
|
|
1357
|
|
1358 static int
|
|
1359 peekc()
|
|
1360 {
|
|
1361 int c;
|
|
1362
|
|
1363 c = mygetc();
|
|
1364 peeked = 1;
|
|
1365
|
|
1366 return (c);
|
|
1367 }
|
|
1368
|
|
1369 static void
|
|
1370 eat()
|
|
1371 {
|
|
1372 if (charbuf != '\n')
|
|
1373 while (mygetc() != '\n');
|
|
1374 peeked = 0;
|
|
1375 }
|
|
1376
|
|
1377 static int
|
|
1378 more()
|
|
1379 {
|
|
1380 if (mygetc() != '\n')
|
|
1381 return (err(1, "syntax"));
|
|
1382 return (0);
|
|
1383 }
|
|
1384
|
|
1385 static void
|
|
1386 quit()
|
|
1387 {
|
|
1388 exit(0);
|
|
1389 }
|
|
1390
|
|
1391 static void
|
|
1392 out(char *ln)
|
|
1393 {
|
|
1394 char *rp, *wp, prev;
|
|
1395 int w, width;
|
|
1396 char *oldrp;
|
|
1397 wchar_t cl;
|
|
1398 int p;
|
|
1399 ptrdiff_t lim;
|
|
1400 if (crunch > 0) {
|
|
1401
|
|
1402 ln = untab(ln);
|
|
1403 rp = wp = ln - 1;
|
|
1404 prev = ' ';
|
|
1405
|
|
1406 while (*++rp) {
|
|
1407 if (prev != ' ' || *rp != ' ')
|
|
1408 *++wp = *rp;
|
|
1409 prev = *rp;
|
|
1410 }
|
|
1411 *++wp = '\n';
|
|
1412 lim = (ptrdiff_t)wp - (ptrdiff_t)ln;
|
|
1413 *++wp = '\0';
|
|
1414
|
|
1415 if (*ln == '\n')
|
|
1416 return;
|
|
1417 } else
|
|
1418 ln[lim = strlen(ln)] = '\n';
|
|
1419
|
|
1420 if (MB_CUR_MAX <= 1) {
|
|
1421 if (lim > trunc)
|
|
1422 ln[lim = trunc] = '\n';
|
|
1423 } else {
|
|
1424 if ((trunc < (BFSBUF -1)) || (lim > trunc)) {
|
|
1425 w = 0;
|
|
1426 oldrp = rp = ln;
|
|
1427 /*CONSTCOND*/while (1) {
|
|
1428 if ((p = mbtowc(&cl, rp, MB_LEN_MAX)) == 0) {
|
|
1429 break;
|
|
1430 }
|
|
1431 if (p == -1) {
|
|
1432 width = p = 1;
|
|
1433 } else {
|
|
1434 width = scrwidth(cl);
|
|
1435 if (width == 0)
|
|
1436 width = 1;
|
|
1437 }
|
|
1438 if ((w += width) > trunc)
|
|
1439 break;
|
|
1440 rp += p;
|
|
1441 }
|
|
1442 *rp = '\n';
|
|
1443 lim = (ptrdiff_t)rp - (ptrdiff_t)oldrp;
|
|
1444 }
|
|
1445 }
|
|
1446
|
|
1447 outcnt += write(outfildes, ln, lim+1);
|
|
1448 }
|
|
1449
|
|
1450 static char *
|
|
1451 untab(char l[])
|
|
1452 {
|
|
1453 static char line[BFSBUF];
|
|
1454 char *q, *s;
|
|
1455
|
|
1456 s = l;
|
|
1457 q = line;
|
|
1458 do {
|
|
1459 if (*s == '\t')
|
|
1460 do
|
|
1461 *q++ = ' ';
|
|
1462 while (((ptrdiff_t)q-(ptrdiff_t)line)%8);
|
|
1463 else *q++ = *s;
|
|
1464 } while (*s++);
|
|
1465 return (line);
|
|
1466 }
|
|
1467
|
|
1468 /*
|
|
1469 * Function to convert ascii string to integer. Converts
|
|
1470 * positive numbers only. Returns -1 if non-numeric
|
|
1471 * character encountered.
|
|
1472 */
|
|
1473
|
|
1474 static int
|
|
1475 patoi(char *b)
|
|
1476 {
|
|
1477 int i;
|
|
1478 char *a;
|
|
1479
|
|
1480 a = b;
|
|
1481 i = 0;
|
|
1482 while (*a >= '0' && *a <= '9') i = 10 * i + *a++ - '0';
|
|
1483
|
|
1484 if (*a)
|
|
1485 return (-1);
|
|
1486 return (i);
|
|
1487 }
|
|
1488
|
|
1489 /*
|
|
1490 * Compares 2 strings. Returns 1 if equal, 0 if not.
|
|
1491 */
|
|
1492
|
|
1493 static int
|
|
1494 equal(char *a, char *b)
|
|
1495 {
|
|
1496 char *x, *y;
|
|
1497
|
|
1498 x = a;
|
|
1499 y = b;
|
|
1500 while (*x == *y++)
|
|
1501 if (*x++ == 0)
|
|
1502 return (1);
|
|
1503 return (0);
|
|
1504 }
|