@@ -189,30 +189,74 @@ static struct grep_expr *compile_pattern_expr(struct grep_pat **list)
189189 return compile_pattern_or (list );
190190}
191191
192- void compile_grep_patterns (struct grep_opt * opt )
192+ static struct grep_expr * grep_true_expr (void )
193+ {
194+ struct grep_expr * z = xcalloc (1 , sizeof (* z ));
195+ z -> node = GREP_NODE_TRUE ;
196+ return z ;
197+ }
198+
199+ static struct grep_expr * grep_or_expr (struct grep_expr * left , struct grep_expr * right )
200+ {
201+ struct grep_expr * z = xcalloc (1 , sizeof (* z ));
202+ z -> node = GREP_NODE_OR ;
203+ z -> u .binary .left = left ;
204+ z -> u .binary .right = right ;
205+ return z ;
206+ }
207+
208+ static struct grep_expr * prep_header_patterns (struct grep_opt * opt )
193209{
194210 struct grep_pat * p ;
195- struct grep_expr * header_expr = NULL ;
196-
197- if (opt -> header_list ) {
198- p = opt -> header_list ;
199- header_expr = compile_pattern_expr (& p );
200- if (p )
201- die ("incomplete pattern expression: %s" , p -> pattern );
202- for (p = opt -> header_list ; p ; p = p -> next ) {
203- switch (p -> token ) {
204- case GREP_PATTERN : /* atom */
205- case GREP_PATTERN_HEAD :
206- case GREP_PATTERN_BODY :
207- compile_regexp (p , opt );
208- break ;
209- default :
210- opt -> extended = 1 ;
211- break ;
212- }
211+ struct grep_expr * header_expr ;
212+ struct grep_expr * (header_group [GREP_HEADER_FIELD_MAX ]);
213+ enum grep_header_field fld ;
214+
215+ if (!opt -> header_list )
216+ return NULL ;
217+ p = opt -> header_list ;
218+ for (p = opt -> header_list ; p ; p = p -> next ) {
219+ if (p -> token != GREP_PATTERN_HEAD )
220+ die ("bug: a non-header pattern in grep header list." );
221+ if (p -> field < 0 || GREP_HEADER_FIELD_MAX <= p -> field )
222+ die ("bug: unknown header field %d" , p -> field );
223+ compile_regexp (p , opt );
224+ }
225+
226+ for (fld = 0 ; fld < GREP_HEADER_FIELD_MAX ; fld ++ )
227+ header_group [fld ] = NULL ;
228+
229+ for (p = opt -> header_list ; p ; p = p -> next ) {
230+ struct grep_expr * h ;
231+ struct grep_pat * pp = p ;
232+
233+ h = compile_pattern_atom (& pp );
234+ if (!h || pp != p -> next )
235+ die ("bug: malformed header expr" );
236+ if (!header_group [p -> field ]) {
237+ header_group [p -> field ] = h ;
238+ continue ;
213239 }
240+ header_group [p -> field ] = grep_or_expr (h , header_group [p -> field ]);
214241 }
215242
243+ header_expr = NULL ;
244+
245+ for (fld = 0 ; fld < GREP_HEADER_FIELD_MAX ; fld ++ ) {
246+ if (!header_group [fld ])
247+ continue ;
248+ if (!header_expr )
249+ header_expr = grep_true_expr ();
250+ header_expr = grep_or_expr (header_group [fld ], header_expr );
251+ }
252+ return header_expr ;
253+ }
254+
255+ void compile_grep_patterns (struct grep_opt * opt )
256+ {
257+ struct grep_pat * p ;
258+ struct grep_expr * header_expr = prep_header_patterns (opt );
259+
216260 for (p = opt -> pattern_list ; p ; p = p -> next ) {
217261 switch (p -> token ) {
218262 case GREP_PATTERN : /* atom */
@@ -231,9 +275,6 @@ void compile_grep_patterns(struct grep_opt *opt)
231275 else if (!opt -> extended )
232276 return ;
233277
234- /* Then bundle them up in an expression.
235- * A classic recursive descent parser would do.
236- */
237278 p = opt -> pattern_list ;
238279 if (p )
239280 opt -> pattern_expression = compile_pattern_expr (& p );
@@ -243,22 +284,18 @@ void compile_grep_patterns(struct grep_opt *opt)
243284 if (!header_expr )
244285 return ;
245286
246- if (opt -> pattern_expression ) {
247- struct grep_expr * z ;
248- z = xcalloc (1 , sizeof (* z ));
249- z -> node = GREP_NODE_OR ;
250- z -> u .binary .left = opt -> pattern_expression ;
251- z -> u .binary .right = header_expr ;
252- opt -> pattern_expression = z ;
253- } else {
287+ if (!opt -> pattern_expression )
254288 opt -> pattern_expression = header_expr ;
255- }
289+ else
290+ opt -> pattern_expression = grep_or_expr (opt -> pattern_expression ,
291+ header_expr );
256292 opt -> all_match = 1 ;
257293}
258294
259295static void free_pattern_expr (struct grep_expr * x )
260296{
261297 switch (x -> node ) {
298+ case GREP_NODE_TRUE :
262299 case GREP_NODE_ATOM :
263300 break ;
264301 case GREP_NODE_NOT :
@@ -487,6 +524,9 @@ static int match_expr_eval(struct grep_expr *x, char *bol, char *eol,
487524 if (!x )
488525 die ("Not a valid grep expression" );
489526 switch (x -> node ) {
527+ case GREP_NODE_TRUE :
528+ h = 1 ;
529+ break ;
490530 case GREP_NODE_ATOM :
491531 h = match_one_pattern (x -> u .atom , bol , eol , ctx , & match , 0 );
492532 break ;
0 commit comments