grep.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // Simple grep. Only supports ^ . * $ operators.
  2. #include "types.h"
  3. #include "stat.h"
  4. #include "user.h"
  5. char buf[1024];
  6. int match(char*, char*);
  7. void
  8. grep(char *pattern, int fd)
  9. {
  10. int n, m;
  11. char *p, *q;
  12. m = 0;
  13. while((n = read(fd, buf+m, sizeof(buf)-m)) > 0){
  14. m += n;
  15. p = buf;
  16. while((q = strchr(p, '\n')) != 0){
  17. *q = 0;
  18. if(match(pattern, p)){
  19. *q = '\n';
  20. write(1, p, q+1 - p);
  21. }
  22. p = q+1;
  23. }
  24. if(p == buf)
  25. m = 0;
  26. if(m > 0){
  27. m -= p - buf;
  28. memmove(buf, p, m);
  29. }
  30. }
  31. }
  32. int
  33. main(int argc, char *argv[])
  34. {
  35. int fd, i;
  36. char *pattern;
  37. if(argc <= 1){
  38. printf(2, "usage: grep pattern [file ...]\n");
  39. exit();
  40. }
  41. pattern = argv[1];
  42. if(argc <= 2){
  43. grep(pattern, 0);
  44. exit();
  45. }
  46. for(i = 2; i < argc; i++){
  47. if((fd = open(argv[i], 0)) < 0){
  48. printf(1, "grep: cannot open %s\n", argv[i]);
  49. exit();
  50. }
  51. grep(pattern, fd);
  52. close(fd);
  53. }
  54. exit();
  55. }
  56. // Regexp matcher from Kernighan & Pike,
  57. // The Practice of Programming, Chapter 9.
  58. int matchhere(char*, char*);
  59. int matchstar(int, char*, char*);
  60. int
  61. match(char *re, char *text)
  62. {
  63. if(re[0] == '^')
  64. return matchhere(re+1, text);
  65. do{ // must look at empty string
  66. if(matchhere(re, text))
  67. return 1;
  68. }while(*text++ != '\0');
  69. return 0;
  70. }
  71. // matchhere: search for re at beginning of text
  72. int matchhere(char *re, char *text)
  73. {
  74. if(re[0] == '\0')
  75. return 1;
  76. if(re[1] == '*')
  77. return matchstar(re[0], re+2, text);
  78. if(re[0] == '$' && re[1] == '\0')
  79. return *text == '\0';
  80. if(*text!='\0' && (re[0]=='.' || re[0]==*text))
  81. return matchhere(re+1, text+1);
  82. return 0;
  83. }
  84. // matchstar: search for c*re at beginning of text
  85. int matchstar(int c, char *re, char *text)
  86. {
  87. do{ // a * matches zero or more instances
  88. if(matchhere(re, text))
  89. return 1;
  90. }while(*text!='\0' && (*text++==c || c=='.'));
  91. return 0;
  92. }