main.c 4.6 KB

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