Print this page
3737 grep does not support -H option
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fgrep/fgrep.c
+++ new/usr/src/cmd/fgrep/fgrep.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30 /* Copyright (c) 1987, 1988 Microsoft Corporation */
31 31 /* All Rights Reserved */
32 32
33 33 #pragma ident "%Z%%M% %I% %E% SMI"
34 34
35 35 /*
36 36 * fgrep -- print all lines containing any of a set of keywords
37 37 *
38 38 * status returns:
39 39 * 0 - ok, and some matches
40 40 * 1 - ok, but no matches
41 41 * 2 - some error
42 42 */
43 43
44 44 #include <stdio.h>
45 45 #include <ctype.h>
46 46 #include <sys/types.h>
47 47 #include <stdlib.h>
48 48 #include <string.h>
49 49 #include <locale.h>
50 50 #include <libintl.h>
51 51 #include <euc.h>
52 52 #include <sys/stat.h>
53 53 #include <fcntl.h>
54 54
55 55 #include <getwidth.h>
56 56
57 57 eucwidth_t WW;
58 58 #define WIDTH1 WW._eucw1
59 59 #define WIDTH2 WW._eucw2
60 60 #define WIDTH3 WW._eucw3
61 61 #define MULTI_BYTE WW._multibyte
62 62 #define GETONE(lc, p) \
63 63 cw = ISASCII(lc = (unsigned char)*p++) ? 1 : \
64 64 (ISSET2(lc) ? WIDTH2 : \
65 65 (ISSET3(lc) ? WIDTH3 : WIDTH1)); \
66 66 if (--cw > --ccount) { \
67 67 cw -= ccount; \
68 68 while (ccount--) \
69 69 lc = (lc << 7) | ((*p++) & 0177); \
70 70 if (p >= &buf[fw_lBufsiz + BUFSIZ]) { \
71 71 if (nlp == buf) { \
72 72 /* Increase the buffer size */ \
73 73 fw_lBufsiz += BUFSIZ; \
74 74 if ((buf = realloc(buf, \
75 75 fw_lBufsiz + BUFSIZ)) == NULL) { \
76 76 exit(2); /* out of memory */ \
77 77 } \
78 78 nlp = buf; \
79 79 p = &buf[fw_lBufsiz]; \
80 80 } else { \
81 81 /* shift the buffer contents down */ \
82 82 (void) memmove(buf, nlp, \
83 83 &buf[fw_lBufsiz + BUFSIZ] - nlp);\
84 84 p -= nlp - buf; \
85 85 nlp = buf; \
86 86 } \
87 87 } \
88 88 if (p > &buf[fw_lBufsiz]) { \
89 89 if ((ccount = fread(p, sizeof (char), \
90 90 &buf[fw_lBufsiz + BUFSIZ] - p, fptr))\
91 91 <= 0) break; \
92 92 } else if ((ccount = fread(p, \
93 93 sizeof (char), BUFSIZ, fptr)) <= 0) \
94 94 break; \
95 95 blkno += (long long)ccount; \
96 96 } \
97 97 ccount -= cw; \
98 98 while (cw--) \
99 99 lc = (lc << 7) | ((*p++) & 0177)
↓ open down ↓ |
99 lines elided |
↑ open up ↑ |
100 100
101 101 /*
102 102 * The same() macro and letter() function were inserted to allow for
103 103 * the -i option work for the multi-byte environment.
104 104 */
105 105 wchar_t letter();
106 106 #define same(a, b) \
107 107 (a == b || iflag && (!MULTI_BYTE || ISASCII(a)) && (a ^ b) == ' ' && \
108 108 letter(a) == letter(b))
109 109
110 +#define STDIN_FILENAME gettext("(standard input)")
110 111
111 112 #define QSIZE 400
112 113 struct words {
113 114 wchar_t inp;
114 115 char out;
115 116 struct words *nst;
116 117 struct words *link;
117 118 struct words *fail;
118 119 } *w = NULL, *smax, *q;
119 120
120 121 FILE *fptr;
121 122 long long lnum;
122 -int bflag, cflag, lflag, fflag, nflag, vflag, xflag, eflag, sflag;
123 -int hflag, iflag;
123 +int bflag, cflag, lflag, fflag, nflag, vflag, xflag, eflag, qflag;
124 +int Hflag, hflag, iflag;
124 125 int retcode = 0;
125 126 int nfile;
126 127 long long blkno;
127 128 int nsucc;
128 129 long long tln;
129 130 FILE *wordf;
130 131 char *argptr;
131 132 off_t input_size = 0;
132 133
133 134 void execute(char *);
134 135 void cgotofn(void);
135 136 void overflo(void);
136 137 void cfail(void);
137 138
138 139 static long fw_lBufsiz = 0;
139 140
140 141 int
141 142 main(int argc, char **argv)
142 143 {
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
143 144 int c;
144 145 int errflg = 0;
145 146 struct stat file_stat;
146 147
147 148 (void) setlocale(LC_ALL, "");
148 149 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
149 150 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
150 151 #endif
151 152 (void) textdomain(TEXT_DOMAIN);
152 153
153 - while ((c = getopt(argc, argv, "hybcie:f:lnvxs")) != EOF)
154 + while ((c = getopt(argc, argv, "Hhybcie:f:lnvxqs")) != EOF)
154 155 switch (c) {
155 156
156 - case 's':
157 - sflag++;
157 + case 'q':
158 + case 's': /* Solaris: legacy option */
159 + qflag++;
160 + continue;
161 + case 'H':
162 + Hflag++;
163 + hflag = 0;
158 164 continue;
159 165 case 'h':
160 166 hflag++;
167 + Hflag = 0;
161 168 continue;
162 169 case 'b':
163 170 bflag++;
164 171 continue;
165 172
166 173 case 'i':
167 174 case 'y':
168 175 iflag++;
169 176 continue;
170 177
171 178 case 'c':
172 179 cflag++;
173 180 continue;
174 181
175 182 case 'e':
176 183 eflag++;
177 184 argptr = optarg;
178 185 input_size = strlen(argptr);
179 186 continue;
180 187
181 188 case 'f':
182 189 fflag++;
183 190 wordf = fopen(optarg, "r");
184 191 if (wordf == NULL) {
185 192 (void) fprintf(stderr,
186 193 gettext("fgrep: can't open %s\n"),
187 194 optarg);
188 195 exit(2);
189 196 }
190 197
191 198 if (fstat(fileno(wordf), &file_stat) == 0) {
192 199 input_size = file_stat.st_size;
193 200 } else {
194 201 (void) fprintf(stderr,
195 202 gettext("fgrep: can't fstat %s\n"),
196 203 optarg);
197 204 exit(2);
198 205 }
199 206
200 207 continue;
201 208
202 209 case 'l':
203 210 lflag++;
204 211 continue;
205 212
206 213 case 'n':
207 214 nflag++;
208 215 continue;
209 216
210 217 case 'v':
211 218 vflag++;
212 219 continue;
213 220
↓ open down ↓ |
43 lines elided |
↑ open up ↑ |
214 221 case 'x':
215 222 xflag++;
216 223 continue;
217 224
218 225 case '?':
219 226 errflg++;
220 227 }
221 228
222 229 argc -= optind;
223 230 if (errflg || ((argc <= 0) && !fflag && !eflag)) {
224 - (void) printf(gettext("usage: fgrep [ -bchilnsvx ] "
231 + (void) printf(gettext("usage: fgrep [ -bcHhilnqsvx ] "
225 232 "[ -e exp ] [ -f file ] [ strings ] [ file ] ...\n"));
226 233 exit(2);
227 234 }
228 235 if (!eflag && !fflag) {
229 236 argptr = argv[optind];
230 237 input_size = strlen(argptr);
231 238 input_size++;
232 239 optind++;
233 240 argc--;
234 241 }
235 242
236 243 /*
237 244 * Normally we need one struct words for each letter in the pattern
238 245 * plus one terminating struct words with outp = 1, but when -x option
239 246 * is specified we require one more struct words for `\n` character so we
240 247 * calculate the input_size as below. We add extra 1 because
241 248 * (input_size/2) rounds off odd numbers
242 249 */
243 250
244 251 if (xflag) {
245 252 input_size = input_size + (input_size/2) + 1;
246 253 }
247 254
248 255 input_size++;
249 256
250 257 w = (struct words *)calloc(input_size, sizeof (struct words));
251 258 if (w == NULL) {
252 259 (void) fprintf(stderr,
253 260 gettext("fgrep: could not allocate "
254 261 "memory for wordlist\n"));
255 262 exit(2);
256 263 }
257 264
258 265 getwidth(&WW);
259 266 if ((WIDTH1 == 0) && (WIDTH2 == 0) &&
260 267 (WIDTH3 == 0)) {
261 268 /*
262 269 * If non EUC-based locale,
263 270 * assume WIDTH1 is 1.
264 271 */
265 272 WIDTH1 = 1;
266 273 }
267 274 WIDTH2++;
268 275 WIDTH3++;
269 276
270 277 cgotofn();
271 278 cfail();
272 279 nfile = argc;
273 280 argv = &argv[optind];
274 281 if (argc <= 0) {
275 282 execute((char *)NULL);
276 283 } else
277 284 while (--argc >= 0) {
278 285 execute(*argv);
279 286 argv++;
280 287 }
281 288
282 289 if (w != NULL) {
283 290 free(w);
284 291 }
285 292
286 293 return (retcode != 0 ? retcode : nsucc == 0);
287 294 }
288 295
289 296 void
290 297 execute(char *file)
291 298 {
292 299 char *p;
293 300 struct words *c;
294 301 int ccount;
295 302 static char *buf = NULL;
296 303 int failed;
297 304 char *nlp;
298 305 wchar_t lc;
299 306 int cw;
300 307
301 308 if (buf == NULL) {
302 309 fw_lBufsiz = BUFSIZ;
303 310 if ((buf = malloc(fw_lBufsiz + BUFSIZ)) == NULL) {
304 311 exit(2); /* out of memory */
305 312 }
↓ open down ↓ |
71 lines elided |
↑ open up ↑ |
306 313 }
307 314
308 315 if (file) {
309 316 if ((fptr = fopen(file, "r")) == NULL) {
310 317 (void) fprintf(stderr,
311 318 gettext("fgrep: can't open %s\n"), file);
312 319 retcode = 2;
313 320 return;
314 321 }
315 322 } else {
316 - file = "<stdin>";
317 323 fptr = stdin;
324 + file = STDIN_FILENAME;
318 325 }
319 326 ccount = 0;
320 327 failed = 0;
321 328 lnum = 1;
322 329 tln = 0;
323 330 blkno = 0;
324 331 p = buf;
325 332 nlp = p;
326 333 c = w;
327 334 for (;;) {
328 335 if (c == 0)
329 336 break;
330 337 if (ccount <= 0) {
331 338 if (p >= &buf[fw_lBufsiz + BUFSIZ]) {
332 339 if (nlp == buf) {
333 340 /* increase the buffer size */
334 341 fw_lBufsiz += BUFSIZ;
335 342 if ((buf = realloc(buf,
336 343 fw_lBufsiz + BUFSIZ)) == NULL) {
337 344 exit(2); /* out of memory */
338 345 }
339 346 nlp = buf;
340 347 p = &buf[fw_lBufsiz];
341 348 } else {
342 349 /* shift the buffer down */
343 350 (void) memmove(buf, nlp,
344 351 &buf[fw_lBufsiz + BUFSIZ]
345 352 - nlp);
346 353 p -= nlp - buf;
347 354 nlp = buf;
348 355 }
349 356
350 357 }
351 358 if (p > &buf[fw_lBufsiz]) {
352 359 if ((ccount = fread(p, sizeof (char),
353 360 &buf[fw_lBufsiz + BUFSIZ] - p, fptr))
354 361 <= 0)
355 362 break;
356 363 } else if ((ccount = fread(p, sizeof (char),
357 364 BUFSIZ, fptr)) <= 0)
358 365 break;
359 366 blkno += (long long)ccount;
360 367 }
361 368 GETONE(lc, p);
362 369 nstate:
363 370 if (same(c->inp, lc)) {
364 371 c = c->nst;
365 372 } else if (c->link != 0) {
366 373 c = c->link;
367 374 goto nstate;
368 375 } else {
369 376 c = c->fail;
370 377 failed = 1;
371 378 if (c == 0) {
372 379 c = w;
373 380 istate:
374 381 if (same(c->inp, lc)) {
375 382 c = c->nst;
376 383 } else if (c->link != 0) {
377 384 c = c->link;
378 385 goto istate;
379 386 }
380 387 } else
381 388 goto nstate;
382 389 }
383 390
384 391 if (c == 0)
385 392 break;
386 393
387 394 if (c->out) {
388 395 while (lc != '\n') {
389 396 if (ccount <= 0) {
390 397 if (p == &buf[fw_lBufsiz + BUFSIZ]) {
391 398 if (nlp == buf) {
392 399 /* increase buffer size */
393 400 fw_lBufsiz += BUFSIZ;
394 401 if ((buf = realloc(buf, fw_lBufsiz + BUFSIZ)) == NULL) {
395 402 exit(2); /* out of memory */
396 403 }
397 404 nlp = buf;
398 405 p = &buf[fw_lBufsiz];
399 406 } else {
400 407 /* shift buffer down */
401 408 (void) memmove(buf, nlp, &buf[fw_lBufsiz + BUFSIZ] - nlp);
402 409 p -= nlp - buf;
403 410 nlp = buf;
404 411 }
405 412 }
406 413 if (p > &buf[fw_lBufsiz]) {
407 414 if ((ccount = fread(p, sizeof (char),
408 415 &buf[fw_lBufsiz + BUFSIZ] - p, fptr)) <= 0) break;
409 416 } else if ((ccount = fread(p, sizeof (char), BUFSIZ,
↓ open down ↓ |
82 lines elided |
↑ open up ↑ |
410 417 fptr)) <= 0) break;
411 418 blkno += (long long)ccount;
412 419 }
413 420 GETONE(lc, p);
414 421 }
415 422 if ((vflag && (failed == 0 || xflag == 0)) ||
416 423 (vflag == 0 && xflag && failed))
417 424 goto nomatch;
418 425 succeed:
419 426 nsucc = 1;
420 - if (cflag)
421 - tln++;
422 - else if (lflag && !sflag) {
423 - (void) printf("%s\n", file);
427 + if (lflag || qflag) {
428 + if (!qflag)
429 + (void) printf("%s\n", file);
424 430 (void) fclose(fptr);
425 431 return;
426 - } else if (!sflag) {
427 - if (nfile > 1 && !hflag)
432 + }
433 + if (cflag) {
434 + tln++;
435 + } else {
436 + if (Hflag || (nfile > 1 && !hflag))
428 437 (void) printf("%s:", file);
429 438 if (bflag)
430 439 (void) printf("%lld:",
431 440 (blkno - (long long)(ccount-1))
432 441 / BUFSIZ);
433 442 if (nflag)
434 443 (void) printf("%lld:", lnum);
435 444 if (p <= nlp) {
436 445 while (nlp < &buf[fw_lBufsiz + BUFSIZ])
437 446 (void) putchar(*nlp++);
438 447 nlp = buf;
439 448 }
440 449 while (nlp < p)
441 450 (void) putchar(*nlp++);
442 451 }
443 452 nomatch:
444 453 lnum++;
445 454 nlp = p;
446 455 c = w;
447 456 failed = 0;
448 457 continue;
449 458 }
450 459 if (lc == '\n')
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
451 460 if (vflag)
452 461 goto succeed;
453 462 else {
454 463 lnum++;
455 464 nlp = p;
456 465 c = w;
457 466 failed = 0;
458 467 }
459 468 }
460 469 (void) fclose(fptr);
461 - if (cflag) {
462 - if ((nfile > 1) && !hflag)
470 + if (cflag && !qflag) {
471 + if (Hflag || (nfile > 1 && !hflag))
463 472 (void) printf("%s:", file);
464 473 (void) printf("%lld\n", tln);
465 474 }
466 475 }
467 476
468 477
469 478 wchar_t
470 479 getargc(void)
471 480 {
472 481 /* appends a newline to shell quoted argument list so */
473 482 /* the list looks like it came from an ed style file */
474 483 wchar_t c;
475 484 int cw;
476 485 int b;
477 486 static int endflg;
478 487
479 488
480 489 if (wordf) {
481 490 if ((b = getc(wordf)) == EOF)
482 491 return (EOF);
483 492 cw = ISASCII(c = (wchar_t)b) ? 1 :
484 493 (ISSET2(c) ? WIDTH2 : (ISSET3(c) ? WIDTH3 : WIDTH1));
485 494 while (--cw) {
486 495 if ((b = getc(wordf)) == EOF)
487 496 return (EOF);
488 497 c = (c << 7) | (b & 0177);
489 498 }
490 499 return (iflag ? letter(c) : c);
491 500 }
492 501
493 502 if (endflg)
494 503 return (EOF);
495 504
496 505 {
497 506 cw = ISASCII(c = (unsigned char)*argptr++) ? 1 :
498 507 (ISSET2(c) ? WIDTH2 : (ISSET3(c) ? WIDTH3 : WIDTH1));
499 508
500 509 while (--cw)
501 510 c = (c << 7) | ((*argptr++) & 0177);
502 511 if (c == '\0') {
503 512 endflg++;
504 513 return ('\n');
505 514 }
506 515 }
507 516 return (iflag ? letter(c) : c);
508 517
509 518
510 519 }
511 520
512 521 void
513 522 cgotofn(void)
514 523 {
515 524 int c;
516 525 struct words *s;
517 526
518 527 s = smax = w;
519 528 nword:
520 529 for (;;) {
521 530 c = getargc();
522 531 if (c == EOF)
523 532 return;
524 533 if (c == 0)
525 534 goto enter;
526 535 if (c == '\n') {
527 536 if (xflag) {
528 537 for (;;) {
529 538 if (s->inp == c) {
530 539 s = s->nst;
531 540 break;
532 541 }
533 542 if (s->inp == 0)
534 543 goto nenter;
535 544 if (s->link == 0) {
536 545 if (smax >= &w[input_size -1])
537 546 overflo();
538 547 s->link = ++smax;
539 548 s = smax;
540 549 goto nenter;
541 550 }
542 551 s = s->link;
543 552 }
544 553 }
545 554 s->out = 1;
546 555 s = w;
547 556 } else {
548 557 loop:
549 558 if (s->inp == c) {
550 559 s = s->nst;
551 560 continue;
552 561 }
553 562 if (s->inp == 0)
554 563 goto enter;
555 564 if (s->link == 0) {
556 565 if (smax >= &w[input_size -1])
557 566 overflo();
558 567 s->link = ++smax;
559 568 s = smax;
560 569 goto enter;
561 570 }
562 571 s = s->link;
563 572 goto loop;
564 573 }
565 574 }
566 575
567 576 enter:
568 577 do {
569 578 s->inp = c;
570 579 if (smax >= &w[input_size -1])
571 580 overflo();
572 581 s->nst = ++smax;
573 582 s = smax;
574 583 } while ((c = getargc()) != '\n' && c != EOF);
575 584 if (xflag) {
576 585 nenter:
577 586 s->inp = '\n';
578 587 if (smax >= &w[input_size -1])
579 588 overflo();
580 589 s->nst = ++smax;
581 590 }
582 591 smax->out = 1;
583 592 s = w;
584 593 if (c != EOF)
585 594 goto nword;
586 595 }
587 596
588 597 /*
589 598 * This function is an unexpected condition, since input_size should have been
590 599 * calculated correctly before hand.
591 600 */
592 601
593 602 void
594 603 overflo(void)
595 604 {
596 605 (void) fprintf(stderr, gettext("fgrep: wordlist too large\n"));
597 606 exit(2);
598 607 }
599 608
600 609 void
601 610 cfail(void)
602 611 {
603 612 int qsize = QSIZE;
604 613 struct words **queue = NULL;
605 614
606 615 /*
607 616 * front and rear are pointers used to traverse the global words
608 617 * structure "w" which contains the data of input pattern file
609 618 */
610 619 struct words **front, **rear;
611 620 struct words *state;
612 621 unsigned long frontoffset = 0, rearoffset = 0;
613 622 char c;
614 623 struct words *s;
615 624 s = w;
616 625 if ((queue = (struct words **)calloc(qsize, sizeof (struct words *)))
617 626 == NULL) {
618 627 perror("fgrep");
619 628 exit(2);
620 629 }
621 630 front = rear = queue;
622 631 init:
623 632 if ((s->inp) != 0) {
624 633 *rear++ = s->nst;
625 634 /*
626 635 * Reallocates the queue if the number of distinct starting
627 636 * character of patterns exceeds the qsize value
628 637 */
629 638 if (rear >= &queue[qsize - 1]) {
630 639 frontoffset = front - queue;
631 640 rearoffset = rear - queue;
632 641 qsize += QSIZE;
633 642 if ((queue = (struct words **)realloc(queue,
634 643 qsize * sizeof (struct words *))) == NULL) {
635 644 perror("fgrep");
636 645 exit(2);
637 646 }
638 647 front = queue + frontoffset;
639 648 rear = queue + rearoffset;
640 649 }
641 650 }
642 651 if ((s = s->link) != 0) {
643 652 goto init;
644 653 }
645 654
646 655 while (rear != front) {
647 656 s = *front++;
648 657 cloop:
649 658 if ((c = s->inp) != 0) {
650 659 *rear++ = (q = s->nst);
651 660 /*
652 661 * Reallocate the queue if the rear pointer reaches the end
653 662 * queue
654 663 */
655 664 if (rear >= &queue[qsize - 1]) {
656 665 frontoffset = front - queue;
657 666 rearoffset = rear - queue;
658 667 qsize += QSIZE;
659 668 if ((queue = (struct words **)realloc(queue,
660 669 qsize * sizeof (struct words *))) == NULL) {
661 670 perror("fgrep");
662 671 exit(2);
663 672 }
664 673 front = queue + frontoffset;
665 674 rear = queue + rearoffset;
666 675 }
667 676 state = s->fail;
668 677 floop:
669 678 if (state == 0)
670 679 state = w;
671 680 if (state->inp == c) {
672 681 qloop:
673 682 q->fail = state->nst;
674 683 if ((state->nst)->out == 1)
675 684 q->out = 1;
676 685 if ((q = q->link) != 0)
677 686 goto qloop;
678 687 } else if ((state = state->link) != 0)
679 688 goto floop;
680 689 }
681 690 if ((s = s->link) != 0)
682 691 goto cloop;
683 692 }
684 693 }
685 694
686 695 wchar_t
687 696 letter(wchar_t c)
688 697 {
689 698 if (c >= 'a' && c <= 'z')
690 699 return (c);
691 700 if (c >= 'A' && c <= 'Z')
692 701 return (c + 'a' - 'A');
693 702 return (c);
694 703 }
↓ open down ↓ |
222 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX