79:  return 0;
 80: }
 81:
 82: int main(int argc, const char ** argv) {
 83:  const char * pattern = NULL;
 84:  regex_t regPattern;
 85:  const void * finalPattern;
 86:  int mode = MODE_REGEXP;
 87:  int ignoreCase = 0;
 88:  int maxCount = -1;
 89:  int rc;
 90:  int regFlags;
 91:  const char ** files;
 92:  poptContext optCon;
 93:  FILE * f;
 94:  char * chptr;
 95:  struct poptOption optionsTable[] = {
 96:   { 'extended-regexp', 'E', POPT_ARG_VAL,
 97:     &mode, MODE_EXTENDED,
 98:     'шаблоном для соответствия является расширенное регулярное '
 99:     'выражение'},
100:   { 'fixed-strings', 'F', POPT_ARG_VAL,
101:     &mode, MODE_FIXED,
102:     'шаблоном для соответствия является базовая строка (не '
103:     'регулярное выражение)', NULL },
104:   { 'basic-regexp', 'G', POPT_ARG_VAL,
105:     &mode, MODE_REGEXP,
106:     'шаблоном для соответствия является базовое регулярное выражение' },
107:   { 'ignore-case', 'i', POPT_ARG_NONE, &ignoreCase, 0,
108:     'выполнять поиск, чувствительный к регистру', NULL },
109:   { 'max-count', 'm', POPT_ARG_INT, &maxCount, 0,
110:     'завершить после получения N. совпадений', 'N' },
111:   { 'regexp', 'e', POPT_ARG_STRING, &pattern, 0,
112:     'регулярное выражение для поиска', 'pattern' },
113:     POPT_AUTOHELP
114:   { NULL, ' ', POPT_ARG_NONE, NULL, 0, NULL, NULL }
115:  };
116:
117:  optCon = poptGetContext('grep', argc, argv, optionsTable, 0);
118:  poptSetOtherOptionHelp(optCon, '<шаблон> <список файлов>');
119:
120:  if ((rc = poptGetNextOpt(optCon)) < -1) {
121:   /* во время обработки параметра возникла ошибка */
122:   fprintf(stderr, '%s: %s
',
123:    poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
124:   poptStrerror(rc));
125:   return 1;
126:  }
127:
128:  files = poptGetArgs(optCon);
129:  /* если мы не получили шаблон, то он должен быть первым
130:     из оставшихся */
131:  if (!files && !pattern) {
132:   poptPrintUsage(optCon, stdout, 0);
133:   return 1;
134:  }
135:
136:  if (!pattern) {
137:   pattern = files[0];
138:   files++;
139:  }
140:
141:  regFlags = REG_NEWLINE | REG_NOSUB;
142:  if (ignoreCase) {
143:   regFlags |= REG_ICASE;
144:   /* преобразование шаблона в нижний регистр; этого можно не делать,
145:      если мы игнорируем регистр в регулярном выражении, однако позволяет
146:      функции strstr() правильно обработать -i */
147:   chptr = alloca(strlen(pattern) + 1);
148:   strcpy(chptr, pattern);
149:   pattern = chptr;
150:
151:   while (*chptr) {
152:    if (isalpha(*chptr)) *chptr = tolower(*chptr);
153:    chptr++;
154:   }
155:  }
156:
157:
158:  switch (mode) {
159:  case MODE_EXTENDED:
160:   regFlags |= REG_EXTENDED;
161:  case MODE_REGEXP:
162:   if ((rc = regcomp(®Pattern, pattern, regFlags))) {
163:    do_regerror(rc, ®Pattern);
164:    return 1;
165:   }
166:   finalPattern = ®Pattern;
167:   break;
168:
169:  case MODE_FIXED:
170:   finalPattern = pattern;
171:   break;
172:  }
173:
174:  if (!*files) {
175:   rc = scanFile(stdin, mode, finalPattern, ignoreCase, NULL,

 
                