main.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #define EXTERN
  10. #include "grep.h"
  11. char *validflags = "bchiLlnsv";
  12. void
  13. usage(void)
  14. {
  15. fprint(2, "usage: grep [-%s] [-e pattern] [-f patternfile] [file ...]\n",
  16. validflags);
  17. exits("usage");
  18. }
  19. void
  20. main(int argc, char *argv[])
  21. {
  22. int i, status;
  23. ARGBEGIN {
  24. default:
  25. if (utfrune(validflags, ARGC()) == nil)
  26. usage();
  27. flags[ARGC()]++;
  28. break;
  29. case 'e':
  30. flags['e']++;
  31. lineno = 0;
  32. str2top(EARGF(usage()));
  33. break;
  34. case 'f':
  35. flags['f']++;
  36. filename = EARGF(usage());
  37. rein = Bopen(filename, OREAD);
  38. if (rein == 0) {
  39. fprint(2, "grep: can't open %s: %r\n", filename);
  40. exits("open");
  41. }
  42. lineno = 1;
  43. str2top(filename);
  44. break;
  45. }
  46. ARGEND if (flags['f'] == 0 && flags['e'] == 0) {
  47. if (argc <= 0)
  48. usage();
  49. str2top(argv[0]);
  50. argc--;
  51. argv++;
  52. }
  53. follow = mal(maxfollow * sizeof(*follow));
  54. state0 = initstate(topre.beg);
  55. Binit(&bout, 1, OWRITE);
  56. switch (argc) {
  57. case 0:
  58. status = search(0, 0);
  59. break;
  60. case 1:
  61. status = search(argv[0], 0);
  62. break;
  63. default:
  64. status = 0;
  65. for (i = 0; i < argc; i++)
  66. status |= search(argv[i], Hflag);
  67. break;
  68. }
  69. if (status)
  70. exits(0);
  71. exits("no matches");
  72. }
  73. int
  74. search(char *file, int flag)
  75. {
  76. State *s, *ns;
  77. int c, fid, eof, nl, empty;
  78. int32_t count, lineno, n;
  79. uint8_t *elp, *lp, *bol;
  80. if (file == 0) {
  81. file = "stdin";
  82. fid = 0;
  83. flag |= Bflag;
  84. } else
  85. fid = open(file, OREAD);
  86. if (fid < 0) {
  87. fprint(2, "grep: can't open %s: %r\n", file);
  88. return 0;
  89. }
  90. if (flags['b'])
  91. flag ^= Bflag; /* dont buffer output */
  92. if (flags['c'])
  93. flag |= Cflag; /* count */
  94. if (flags['h'])
  95. flag &= ~Hflag; /* do not print file name in output */
  96. if (flags['i'])
  97. flag |= Iflag; /* fold upper-lower */
  98. if (flags['l'])
  99. flag |= Llflag; /* print only name of file if any match */
  100. if (flags['L'])
  101. flag |= LLflag; /* print only name of file if any non match */
  102. if (flags['n'])
  103. flag |= Nflag; /* count only */
  104. if (flags['s'])
  105. flag |= Sflag; /* status only */
  106. if (flags['v'])
  107. flag |= Vflag; /* inverse match */
  108. s = state0;
  109. lineno = 0;
  110. count = 0;
  111. eof = 0;
  112. empty = 1;
  113. nl = 0;
  114. lp = u.buf;
  115. bol = lp;
  116. loop0:
  117. n = lp - bol;
  118. if (n > sizeof(u.pre))
  119. n = sizeof(u.pre);
  120. memmove(u.buf - n, bol, n);
  121. bol = u.buf - n;
  122. n = read(fid, u.buf, sizeof(u.buf));
  123. /* if file has no final newline, simulate one to emit matches to last line */
  124. if (n > 0) {
  125. empty = 0;
  126. nl = u.buf[n - 1] == '\n';
  127. } else {
  128. if (n < 0) {
  129. fprint(2, "grep: read error on %s: %r\n", file);
  130. return count != 0;
  131. }
  132. if (!eof && !nl && !empty) {
  133. u.buf[0] = '\n';
  134. n = 1;
  135. eof = 1;
  136. }
  137. }
  138. if (n <= 0) {
  139. close(fid);
  140. if (flag & Cflag) {
  141. if (flag & Hflag)
  142. Bprint(&bout, "%s:", file);
  143. Bprint(&bout, "%ld\n", count);
  144. }
  145. if (((flag & Llflag) && count != 0) || ((flag & LLflag) && count == 0))
  146. Bprint(&bout, "%s\n", file);
  147. Bflush(&bout);
  148. return count != 0;
  149. }
  150. lp = u.buf;
  151. elp = lp + n;
  152. if (flag & Iflag)
  153. goto loopi;
  154. /*
  155. * normal character loop
  156. */
  157. loop:
  158. c = *lp;
  159. ns = s->next[c];
  160. if (ns == 0) {
  161. increment(s, c);
  162. goto loop;
  163. }
  164. // if(flags['2'])
  165. // if(s->match)
  166. // print("%d: %.2x**\n", s, c);
  167. // else
  168. // print("%d: %.2x\n", s, c);
  169. lp++;
  170. s = ns;
  171. if (c == '\n') {
  172. lineno++;
  173. if (! !s->match == !(flag & Vflag)) {
  174. count++;
  175. if (flag & (Cflag | Sflag | Llflag | LLflag))
  176. goto cont;
  177. if (flag & Hflag)
  178. Bprint(&bout, "%s:", file);
  179. if (flag & Nflag)
  180. Bprint(&bout, "%ld: ", lineno);
  181. /* suppress extra newline at EOF unless we are labeling matches with file name */
  182. Bwrite(&bout, bol, lp - bol - (eof && !(flag & Hflag)));
  183. if (flag & Bflag)
  184. Bflush(&bout);
  185. }
  186. if ((lineno & Flshcnt) == 0)
  187. Bflush(&bout);
  188. cont:
  189. bol = lp;
  190. }
  191. if (lp != elp)
  192. goto loop;
  193. goto loop0;
  194. /*
  195. * character loop for -i flag
  196. * for speed
  197. */
  198. loopi:
  199. c = *lp;
  200. if (c >= 'A' && c <= 'Z')
  201. c += 'a' - 'A';
  202. ns = s->next[c];
  203. if (ns == 0) {
  204. increment(s, c);
  205. goto loopi;
  206. }
  207. lp++;
  208. s = ns;
  209. if (c == '\n') {
  210. lineno++;
  211. if (! !s->match == !(flag & Vflag)) {
  212. count++;
  213. if (flag & (Cflag | Sflag | Llflag | LLflag))
  214. goto conti;
  215. if (flag & Hflag)
  216. Bprint(&bout, "%s:", file);
  217. if (flag & Nflag)
  218. Bprint(&bout, "%ld: ", lineno);
  219. /* suppress extra newline at EOF unless we are labeling matches with file name */
  220. Bwrite(&bout, bol, lp - bol - (eof && !(flag & Hflag)));
  221. if (flag & Bflag)
  222. Bflush(&bout);
  223. }
  224. if ((lineno & Flshcnt) == 0)
  225. Bflush(&bout);
  226. conti:
  227. bol = lp;
  228. }
  229. if (lp != elp)
  230. goto loopi;
  231. goto loop0;
  232. }
  233. State *
  234. initstate(Re * r)
  235. {
  236. State *s;
  237. int i;
  238. addcase(r);
  239. if (flags['1'])
  240. reprint("r", r);
  241. nfollow = 0;
  242. gen++;
  243. fol1(r, Cbegin);
  244. follow[nfollow++] = r;
  245. qsort(follow, nfollow, sizeof(*follow), fcmp);
  246. s = sal(nfollow);
  247. for (i = 0; i < nfollow; i++)
  248. s->re[i] = follow[i];
  249. return s;
  250. }