Mercurial > illumos > onarm
comparison usr/src/cmd/bfs/bfs.c @ 0:c9caec207d52 b86
Initial porting based on b86
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Tue, 02 Jun 2009 18:56:50 +0900 |
parents | |
children | 1a15d5aaf794 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:c9caec207d52 |
---|---|
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 } |