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