1 /* parser.c -- convert the command line args into an expression tree.
2 Copyright (C) 1990, 91, 92, 93, 94, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
24 #include "modechange.h"
30 # define _(Text) gettext (Text)
35 # define N_(String) gettext_noop (String)
37 # define N_(String) (String)
40 #if !defined (isascii) || defined (STDC_HEADERS)
47 #define ISDIGIT(c) (isascii (c) && isdigit (c))
48 #define ISUPPER(c) (isascii (c) && isupper (c))
57 static boolean parse_amin
PARAMS((char *argv
[], int *arg_ptr
));
58 static boolean parse_and
PARAMS((char *argv
[], int *arg_ptr
));
59 static boolean parse_anewer
PARAMS((char *argv
[], int *arg_ptr
));
60 static boolean parse_atime
PARAMS((char *argv
[], int *arg_ptr
));
61 boolean parse_close
PARAMS((char *argv
[], int *arg_ptr
));
62 static boolean parse_cmin
PARAMS((char *argv
[], int *arg_ptr
));
63 static boolean parse_cnewer
PARAMS((char *argv
[], int *arg_ptr
));
64 static boolean parse_comma
PARAMS((char *argv
[], int *arg_ptr
));
65 static boolean parse_ctime
PARAMS((char *argv
[], int *arg_ptr
));
66 static boolean parse_daystart
PARAMS((char *argv
[], int *arg_ptr
));
67 static boolean parse_depth
PARAMS((char *argv
[], int *arg_ptr
));
68 static boolean parse_empty
PARAMS((char *argv
[], int *arg_ptr
));
69 static boolean parse_exec
PARAMS((char *argv
[], int *arg_ptr
));
70 static boolean parse_false
PARAMS((char *argv
[], int *arg_ptr
));
71 static boolean parse_fls
PARAMS((char *argv
[], int *arg_ptr
));
72 static boolean parse_fprintf
PARAMS((char *argv
[], int *arg_ptr
));
73 static boolean parse_follow
PARAMS((char *argv
[], int *arg_ptr
));
74 static boolean parse_fprint
PARAMS((char *argv
[], int *arg_ptr
));
75 static boolean parse_fprint0
PARAMS((char *argv
[], int *arg_ptr
));
76 static boolean parse_fstype
PARAMS((char *argv
[], int *arg_ptr
));
77 static boolean parse_gid
PARAMS((char *argv
[], int *arg_ptr
));
78 static boolean parse_group
PARAMS((char *argv
[], int *arg_ptr
));
79 static boolean parse_help
PARAMS((char *argv
[], int *arg_ptr
));
80 static boolean parse_ilname
PARAMS((char *argv
[], int *arg_ptr
));
81 static boolean parse_iname
PARAMS((char *argv
[], int *arg_ptr
));
82 static boolean parse_inum
PARAMS((char *argv
[], int *arg_ptr
));
83 static boolean parse_ipath
PARAMS((char *argv
[], int *arg_ptr
));
84 static boolean parse_iregex
PARAMS((char *argv
[], int *arg_ptr
));
85 static boolean parse_links
PARAMS((char *argv
[], int *arg_ptr
));
86 static boolean parse_lname
PARAMS((char *argv
[], int *arg_ptr
));
87 static boolean parse_ls
PARAMS((char *argv
[], int *arg_ptr
));
88 static boolean parse_maxdepth
PARAMS((char *argv
[], int *arg_ptr
));
89 static boolean parse_mindepth
PARAMS((char *argv
[], int *arg_ptr
));
90 static boolean parse_mmin
PARAMS((char *argv
[], int *arg_ptr
));
91 static boolean parse_mtime
PARAMS((char *argv
[], int *arg_ptr
));
92 static boolean parse_name
PARAMS((char *argv
[], int *arg_ptr
));
93 static boolean parse_negate
PARAMS((char *argv
[], int *arg_ptr
));
94 static boolean parse_newer
PARAMS((char *argv
[], int *arg_ptr
));
95 static boolean parse_noleaf
PARAMS((char *argv
[], int *arg_ptr
));
96 static boolean parse_nogroup
PARAMS((char *argv
[], int *arg_ptr
));
97 static boolean parse_nouser
PARAMS((char *argv
[], int *arg_ptr
));
98 static boolean parse_ok
PARAMS((char *argv
[], int *arg_ptr
));
99 boolean parse_open
PARAMS((char *argv
[], int *arg_ptr
));
100 static boolean parse_or
PARAMS((char *argv
[], int *arg_ptr
));
101 static boolean parse_path
PARAMS((char *argv
[], int *arg_ptr
));
102 static boolean parse_perm
PARAMS((char *argv
[], int *arg_ptr
));
103 boolean parse_print
PARAMS((char *argv
[], int *arg_ptr
));
104 static boolean parse_print0
PARAMS((char *argv
[], int *arg_ptr
));
105 static boolean parse_printf
PARAMS((char *argv
[], int *arg_ptr
));
106 static boolean parse_prune
PARAMS((char *argv
[], int *arg_ptr
));
107 static boolean parse_regex
PARAMS((char *argv
[], int *arg_ptr
));
108 static boolean insert_regex
PARAMS((char *argv
[], int *arg_ptr
, boolean ignore_case
));
109 static boolean parse_size
PARAMS((char *argv
[], int *arg_ptr
));
110 static boolean parse_true
PARAMS((char *argv
[], int *arg_ptr
));
111 static boolean parse_type
PARAMS((char *argv
[], int *arg_ptr
));
112 static boolean parse_uid
PARAMS((char *argv
[], int *arg_ptr
));
113 static boolean parse_used
PARAMS((char *argv
[], int *arg_ptr
));
114 static boolean parse_user
PARAMS((char *argv
[], int *arg_ptr
));
115 static boolean parse_version
PARAMS((char *argv
[], int *arg_ptr
));
116 static boolean parse_xdev
PARAMS((char *argv
[], int *arg_ptr
));
117 static boolean parse_ignore_race
PARAMS((char *argv
[], int *arg_ptr
));
118 static boolean parse_noignore_race
PARAMS((char *argv
[], int *arg_ptr
));
119 static boolean parse_xtype
PARAMS((char *argv
[], int *arg_ptr
));
121 static boolean insert_regex
PARAMS((char *argv
[], int *arg_ptr
, boolean ignore_case
));
122 static boolean insert_type
PARAMS((char *argv
[], int *arg_ptr
, boolean (*which_pred
)()));
123 static boolean insert_fprintf
PARAMS((FILE *fp
, boolean (*func
)(), char *argv
[], int *arg_ptr
));
124 static struct segment
**make_segment
PARAMS((struct segment
**segment
, char *format
, int len
, int kind
));
125 static boolean insert_exec_ok
PARAMS((boolean (*func
)(), char *argv
[], int *arg_ptr
));
126 static boolean get_num_days
PARAMS((char *str
, uintmax_t *num_days
, enum comparison_type
*comp_type
));
127 static boolean insert_time
PARAMS((char *argv
[], int *arg_ptr
, PFB pred
));
128 static boolean get_num
PARAMS((char *str
, uintmax_t *num
, enum comparison_type
*comp_type
));
129 static boolean insert_num
PARAMS((char *argv
[], int *arg_ptr
, PFB pred
));
130 static FILE *open_output_file
PARAMS((char *path
));
133 char *find_pred_name
PARAMS((PFB pred_func
));
142 /* GNU find predicates that are not mentioned in POSIX.2 are marked `GNU'.
143 If they are in some Unix versions of find, they are marked `Unix'. */
145 static struct parser_table
const parse_table
[] =
148 {"not", parse_negate
}, /* GNU */
151 {",", parse_comma
}, /* GNU */
153 {"amin", parse_amin
}, /* GNU */
154 {"and", parse_and
}, /* GNU */
155 {"anewer", parse_anewer
}, /* GNU */
156 {"atime", parse_atime
},
157 {"cmin", parse_cmin
}, /* GNU */
158 {"cnewer", parse_cnewer
}, /* GNU */
159 #ifdef UNIMPLEMENTED_UNIX
160 /* It's pretty ugly for find to know about archive formats.
161 Plus what it could do with cpio archives is very limited.
162 Better to leave it out. */
163 {"cpio", parse_cpio
}, /* Unix */
165 {"ctime", parse_ctime
},
166 {"daystart", parse_daystart
}, /* GNU */
167 {"depth", parse_depth
},
168 {"empty", parse_empty
}, /* GNU */
169 {"exec", parse_exec
},
170 {"false", parse_false
}, /* GNU */
171 {"fls", parse_fls
}, /* GNU */
172 {"follow", parse_follow
}, /* GNU, Unix */
173 {"fprint", parse_fprint
}, /* GNU */
174 {"fprint0", parse_fprint0
}, /* GNU */
175 {"fprintf", parse_fprintf
}, /* GNU */
176 {"fstype", parse_fstype
}, /* GNU, Unix */
177 {"gid", parse_gid
}, /* GNU */
178 {"group", parse_group
},
179 {"help", parse_help
}, /* GNU */
180 {"-help", parse_help
}, /* GNU */
181 {"ignore_readdir_race", parse_ignore_race
}, /* GNU */
182 {"ilname", parse_ilname
}, /* GNU */
183 {"iname", parse_iname
}, /* GNU */
184 {"inum", parse_inum
}, /* GNU, Unix */
185 {"ipath", parse_ipath
}, /* GNU */
186 {"iregex", parse_iregex
}, /* GNU */
187 {"links", parse_links
},
188 {"lname", parse_lname
}, /* GNU */
189 {"ls", parse_ls
}, /* GNU, Unix */
190 {"maxdepth", parse_maxdepth
}, /* GNU */
191 {"mindepth", parse_mindepth
}, /* GNU */
192 {"mmin", parse_mmin
}, /* GNU */
193 {"mount", parse_xdev
}, /* Unix */
194 {"mtime", parse_mtime
},
195 {"name", parse_name
},
196 #ifdef UNIMPLEMENTED_UNIX
197 {"ncpio", parse_ncpio
}, /* Unix */
199 {"newer", parse_newer
},
200 {"noleaf", parse_noleaf
}, /* GNU */
201 {"nogroup", parse_nogroup
},
202 {"nouser", parse_nouser
},
203 {"noignore_readdir_race", parse_noignore_race
}, /* GNU */
205 {"or", parse_or
}, /* GNU */
207 {"path", parse_path
}, /* GNU, HP-UX */
208 {"perm", parse_perm
},
209 {"print", parse_print
},
210 {"print0", parse_print0
}, /* GNU */
211 {"printf", parse_printf
}, /* GNU */
212 {"prune", parse_prune
},
213 {"regex", parse_regex
}, /* GNU */
214 {"size", parse_size
},
215 {"true", parse_true
}, /* GNU */
216 {"type", parse_type
},
217 {"uid", parse_uid
}, /* GNU */
218 {"used", parse_used
}, /* GNU */
219 {"user", parse_user
},
220 {"version", parse_version
}, /* GNU */
221 {"-version", parse_version
}, /* GNU */
222 {"xdev", parse_xdev
},
223 {"xtype", parse_xtype
}, /* GNU */
227 /* Return a pointer to the parser function to invoke for predicate
229 Return NULL if SEARCH_NAME is not a valid predicate name. */
232 find_parser (char *search_name
)
236 if (*search_name
== '-')
238 for (i
= 0; parse_table
[i
].parser_name
!= 0; i
++)
239 if (strcmp (parse_table
[i
].parser_name
, search_name
) == 0)
240 return (parse_table
[i
].parser_func
);
244 /* The parsers are responsible to continue scanning ARGV for
245 their arguments. Each parser knows what is and isn't
248 ARGV is the argument array.
249 *ARG_PTR is the index to start at in ARGV,
250 updated to point beyond the last element consumed.
252 The predicate structure is updated with the new information. */
255 parse_amin (char **argv
, int *arg_ptr
)
257 struct predicate
*our_pred
;
259 enum comparison_type c_type
;
262 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
264 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
266 t
= cur_day_start
+ DAYSECS
- num
* 60;
267 our_pred
= insert_primary (pred_amin
);
268 our_pred
->args
.info
.kind
= c_type
;
269 our_pred
->args
.info
.negative
= t
< 0;
270 our_pred
->args
.info
.l_val
= t
;
276 parse_and (char **argv
, int *arg_ptr
)
278 struct predicate
*our_pred
;
280 our_pred
= get_new_pred ();
281 our_pred
->pred_func
= pred_and
;
283 our_pred
->p_name
= find_pred_name (pred_and
);
285 our_pred
->p_type
= BI_OP
;
286 our_pred
->p_prec
= AND_PREC
;
287 our_pred
->need_stat
= false;
292 parse_anewer (char **argv
, int *arg_ptr
)
294 struct predicate
*our_pred
;
295 struct stat stat_newer
;
297 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
299 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
300 error (1, errno
, "%s", argv
[*arg_ptr
]);
301 our_pred
= insert_primary (pred_anewer
);
302 our_pred
->args
.time
= stat_newer
.st_mtime
;
308 parse_atime (char **argv
, int *arg_ptr
)
310 return (insert_time (argv
, arg_ptr
, pred_atime
));
314 parse_close (char **argv
, int *arg_ptr
)
316 struct predicate
*our_pred
;
318 our_pred
= get_new_pred ();
319 our_pred
->pred_func
= pred_close
;
321 our_pred
->p_name
= find_pred_name (pred_close
);
323 our_pred
->p_type
= CLOSE_PAREN
;
324 our_pred
->p_prec
= NO_PREC
;
325 our_pred
->need_stat
= false;
330 parse_cmin (char **argv
, int *arg_ptr
)
332 struct predicate
*our_pred
;
334 enum comparison_type c_type
;
337 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
339 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
341 t
= cur_day_start
+ DAYSECS
- num
* 60;
342 our_pred
= insert_primary (pred_cmin
);
343 our_pred
->args
.info
.kind
= c_type
;
344 our_pred
->args
.info
.negative
= t
< 0;
345 our_pred
->args
.info
.l_val
= t
;
351 parse_cnewer (char **argv
, int *arg_ptr
)
353 struct predicate
*our_pred
;
354 struct stat stat_newer
;
356 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
358 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
359 error (1, errno
, "%s", argv
[*arg_ptr
]);
360 our_pred
= insert_primary (pred_cnewer
);
361 our_pred
->args
.time
= stat_newer
.st_mtime
;
367 parse_comma (char **argv
, int *arg_ptr
)
369 struct predicate
*our_pred
;
371 our_pred
= get_new_pred ();
372 our_pred
->pred_func
= pred_comma
;
374 our_pred
->p_name
= find_pred_name (pred_comma
);
376 our_pred
->p_type
= BI_OP
;
377 our_pred
->p_prec
= COMMA_PREC
;
378 our_pred
->need_stat
= false;
383 parse_ctime (char **argv
, int *arg_ptr
)
385 return (insert_time (argv
, arg_ptr
, pred_ctime
));
389 parse_daystart (char **argv
, int *arg_ptr
)
393 if (full_days
== false)
395 cur_day_start
+= DAYSECS
;
396 local
= localtime (&cur_day_start
);
397 cur_day_start
-= (local
398 ? (local
->tm_sec
+ local
->tm_min
* 60
399 + local
->tm_hour
* 3600)
400 : cur_day_start
% DAYSECS
);
407 parse_depth (char **argv
, int *arg_ptr
)
409 do_dir_first
= false;
414 parse_empty (char **argv
, int *arg_ptr
)
416 insert_primary (pred_empty
);
421 parse_exec (char **argv
, int *arg_ptr
)
423 return (insert_exec_ok (pred_exec
, argv
, arg_ptr
));
427 parse_false (char **argv
, int *arg_ptr
)
429 struct predicate
*our_pred
;
431 our_pred
= insert_primary (pred_false
);
432 our_pred
->need_stat
= false;
437 parse_fls (char **argv
, int *arg_ptr
)
439 struct predicate
*our_pred
;
441 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
443 our_pred
= insert_primary (pred_fls
);
444 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
445 our_pred
->side_effects
= true;
446 our_pred
->no_default_print
= true;
452 parse_fprintf (char **argv
, int *arg_ptr
)
456 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
458 if (argv
[*arg_ptr
+ 1] == NULL
)
460 /* Ensure we get "missing arg" message, not "invalid arg". */
464 fp
= open_output_file (argv
[*arg_ptr
]);
466 return (insert_fprintf (fp
, pred_fprintf
, argv
, arg_ptr
));
470 parse_follow (char **argv
, int *arg_ptr
)
474 no_leaf_check
= true;
479 parse_fprint (char **argv
, int *arg_ptr
)
481 struct predicate
*our_pred
;
483 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
485 our_pred
= insert_primary (pred_fprint
);
486 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
487 our_pred
->side_effects
= true;
488 our_pred
->no_default_print
= true;
489 our_pred
->need_stat
= false;
495 parse_fprint0 (char **argv
, int *arg_ptr
)
497 struct predicate
*our_pred
;
499 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
501 our_pred
= insert_primary (pred_fprint0
);
502 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
503 our_pred
->side_effects
= true;
504 our_pred
->no_default_print
= true;
505 our_pred
->need_stat
= false;
511 parse_fstype (char **argv
, int *arg_ptr
)
513 struct predicate
*our_pred
;
515 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
517 our_pred
= insert_primary (pred_fstype
);
518 our_pred
->args
.str
= argv
[*arg_ptr
];
524 parse_gid (char **argv
, int *arg_ptr
)
526 return (insert_num (argv
, arg_ptr
, pred_gid
));
530 parse_group (char **argv
, int *arg_ptr
)
532 struct group
*cur_gr
;
533 struct predicate
*our_pred
;
537 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
539 cur_gr
= getgrnam (argv
[*arg_ptr
]);
542 gid
= cur_gr
->gr_gid
;
545 gid_len
= strspn (argv
[*arg_ptr
], "0123456789");
546 if ((gid_len
== 0) || (argv
[*arg_ptr
][gid_len
] != '\0'))
548 gid
= atoi (argv
[*arg_ptr
]);
550 our_pred
= insert_primary (pred_group
);
551 our_pred
->args
.gid
= gid
;
557 parse_help (char **argv
, int *arg_ptr
)
560 Usage: %s [path...] [expression]\n"), program_name
);
562 default path is the current directory; default expression is -print\n\
563 expression may consist of:\n\
564 operators (decreasing precedence; -and is implicit where no others are given):\n\
565 ( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2\n"));
567 EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2\n\
568 options (always true): -daystart -depth -follow --help\n\
569 -maxdepth LEVELS -mindepth LEVELS -mount -noleaf --version -xdev\n\
570 tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n"));
572 -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
573 -ilname PATTERN -iname PATTERN -inum N -ipath PATTERN -iregex PATTERN\n\
574 -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE\n"));
576 -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
577 -size N[bckw] -true -type [bcdpfls] -uid N -used N -user NAME\n\
578 -xtype [bcdpfls]\n"));
580 actions: -exec COMMAND ; -fprint FILE -fprint0 FILE -fprintf FILE FORMAT\n\
581 -ok COMMAND ; -print -print0 -printf FORMAT -prune -ls\n"));
582 puts (_("\nReport bugs to <bug-findutils@gnu.org>."));
587 parse_ilname (char **argv
, int *arg_ptr
)
589 struct predicate
*our_pred
;
591 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
593 our_pred
= insert_primary (pred_ilname
);
594 our_pred
->args
.str
= argv
[*arg_ptr
];
600 parse_iname (char **argv
, int *arg_ptr
)
602 struct predicate
*our_pred
;
604 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
606 our_pred
= insert_primary (pred_iname
);
607 our_pred
->need_stat
= false;
608 our_pred
->args
.str
= argv
[*arg_ptr
];
614 parse_inum (char **argv
, int *arg_ptr
)
616 return (insert_num (argv
, arg_ptr
, pred_inum
));
620 parse_ipath (char **argv
, int *arg_ptr
)
622 struct predicate
*our_pred
;
624 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
626 our_pred
= insert_primary (pred_ipath
);
627 our_pred
->need_stat
= false;
628 our_pred
->args
.str
= argv
[*arg_ptr
];
634 parse_iregex (char **argv
, int *arg_ptr
)
636 return insert_regex (argv
, arg_ptr
, true);
640 parse_links (char **argv
, int *arg_ptr
)
642 return (insert_num (argv
, arg_ptr
, pred_links
));
646 parse_lname (char **argv
, int *arg_ptr
)
648 struct predicate
*our_pred
;
650 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
652 our_pred
= insert_primary (pred_lname
);
653 our_pred
->args
.str
= argv
[*arg_ptr
];
659 parse_ls (char **argv
, int *arg_ptr
)
661 struct predicate
*our_pred
;
663 our_pred
= insert_primary (pred_ls
);
664 our_pred
->side_effects
= true;
665 our_pred
->no_default_print
= true;
670 parse_maxdepth (char **argv
, int *arg_ptr
)
674 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
676 depth_len
= strspn (argv
[*arg_ptr
], "0123456789");
677 if ((depth_len
== 0) || (argv
[*arg_ptr
][depth_len
] != '\0'))
679 maxdepth
= atoi (argv
[*arg_ptr
]);
687 parse_mindepth (char **argv
, int *arg_ptr
)
691 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
693 depth_len
= strspn (argv
[*arg_ptr
], "0123456789");
694 if ((depth_len
== 0) || (argv
[*arg_ptr
][depth_len
] != '\0'))
696 mindepth
= atoi (argv
[*arg_ptr
]);
704 parse_mmin (char **argv
, int *arg_ptr
)
706 struct predicate
*our_pred
;
708 enum comparison_type c_type
;
711 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
713 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
715 t
= cur_day_start
+ DAYSECS
- num
* 60;
716 our_pred
= insert_primary (pred_mmin
);
717 our_pred
->args
.info
.kind
= c_type
;
718 our_pred
->args
.info
.negative
= t
< 0;
719 our_pred
->args
.info
.l_val
= t
;
725 parse_mtime (char **argv
, int *arg_ptr
)
727 return (insert_time (argv
, arg_ptr
, pred_mtime
));
731 parse_name (char **argv
, int *arg_ptr
)
733 struct predicate
*our_pred
;
735 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
737 our_pred
= insert_primary (pred_name
);
738 our_pred
->need_stat
= false;
739 our_pred
->args
.str
= argv
[*arg_ptr
];
745 parse_negate (char **argv
, int *arg_ptr
)
747 struct predicate
*our_pred
;
749 our_pred
= get_new_pred_chk_op ();
750 our_pred
->pred_func
= pred_negate
;
752 our_pred
->p_name
= find_pred_name (pred_negate
);
754 our_pred
->p_type
= UNI_OP
;
755 our_pred
->p_prec
= NEGATE_PREC
;
756 our_pred
->need_stat
= false;
761 parse_newer (char **argv
, int *arg_ptr
)
763 struct predicate
*our_pred
;
764 struct stat stat_newer
;
766 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
768 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
769 error (1, errno
, "%s", argv
[*arg_ptr
]);
770 our_pred
= insert_primary (pred_newer
);
771 our_pred
->args
.time
= stat_newer
.st_mtime
;
777 parse_noleaf (char **argv
, int *arg_ptr
)
779 no_leaf_check
= true;
784 /* Arbitrary amount by which to increase size
785 of `uid_unused' and `gid_unused'. */
786 #define ALLOC_STEP 2048
788 /* Boolean: if uid_unused[n] is nonzero, then UID n has no passwd entry. */
789 char *uid_unused
= NULL
;
791 /* Number of elements in `uid_unused'. */
792 unsigned uid_allocated
;
794 /* Similar for GIDs and group entries. */
795 char *gid_unused
= NULL
;
796 unsigned gid_allocated
;
800 parse_nogroup (char **argv
, int *arg_ptr
)
802 struct predicate
*our_pred
;
804 our_pred
= insert_primary (pred_nogroup
);
806 if (gid_unused
== NULL
)
810 gid_allocated
= ALLOC_STEP
;
811 gid_unused
= xmalloc (gid_allocated
);
812 memset (gid_unused
, 1, gid_allocated
);
814 while ((gr
= getgrent ()) != NULL
)
816 if ((unsigned) gr
->gr_gid
>= gid_allocated
)
818 unsigned new_allocated
= (unsigned) gr
->gr_gid
+ ALLOC_STEP
;
819 gid_unused
= xrealloc (gid_unused
, new_allocated
);
820 memset (gid_unused
+ gid_allocated
, 1,
821 new_allocated
- gid_allocated
);
822 gid_allocated
= new_allocated
;
824 gid_unused
[(unsigned) gr
->gr_gid
] = 0;
833 parse_nouser (char **argv
, int *arg_ptr
)
835 struct predicate
*our_pred
;
837 our_pred
= insert_primary (pred_nouser
);
839 if (uid_unused
== NULL
)
843 uid_allocated
= ALLOC_STEP
;
844 uid_unused
= xmalloc (uid_allocated
);
845 memset (uid_unused
, 1, uid_allocated
);
847 while ((pw
= getpwent ()) != NULL
)
849 if ((unsigned) pw
->pw_uid
>= uid_allocated
)
851 unsigned new_allocated
= (unsigned) pw
->pw_uid
+ ALLOC_STEP
;
852 uid_unused
= xrealloc (uid_unused
, new_allocated
);
853 memset (uid_unused
+ uid_allocated
, 1,
854 new_allocated
- uid_allocated
);
855 uid_allocated
= new_allocated
;
857 uid_unused
[(unsigned) pw
->pw_uid
] = 0;
866 parse_ok (char **argv
, int *arg_ptr
)
868 return (insert_exec_ok (pred_ok
, argv
, arg_ptr
));
872 parse_open (char **argv
, int *arg_ptr
)
874 struct predicate
*our_pred
;
876 our_pred
= get_new_pred_chk_op ();
877 our_pred
->pred_func
= pred_open
;
879 our_pred
->p_name
= find_pred_name (pred_open
);
881 our_pred
->p_type
= OPEN_PAREN
;
882 our_pred
->p_prec
= NO_PREC
;
883 our_pred
->need_stat
= false;
888 parse_or (char **argv
, int *arg_ptr
)
890 struct predicate
*our_pred
;
892 our_pred
= get_new_pred ();
893 our_pred
->pred_func
= pred_or
;
895 our_pred
->p_name
= find_pred_name (pred_or
);
897 our_pred
->p_type
= BI_OP
;
898 our_pred
->p_prec
= OR_PREC
;
899 our_pred
->need_stat
= false;
904 parse_path (char **argv
, int *arg_ptr
)
906 struct predicate
*our_pred
;
908 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
910 our_pred
= insert_primary (pred_path
);
911 our_pred
->need_stat
= false;
912 our_pred
->args
.str
= argv
[*arg_ptr
];
918 parse_perm (char **argv
, int *arg_ptr
)
922 struct mode_change
*change
;
923 struct predicate
*our_pred
;
925 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
928 switch (argv
[*arg_ptr
][0])
939 change
= mode_compile (argv
[*arg_ptr
] + mode_start
, MODE_MASK_PLUS
);
940 if (change
== MODE_INVALID
)
941 error (1, 0, _("invalid mode `%s'"), argv
[*arg_ptr
]);
942 else if (change
== MODE_MEMORY_EXHAUSTED
)
943 error (1, 0, _("virtual memory exhausted"));
944 perm_val
= mode_adjust (0, change
);
947 our_pred
= insert_primary (pred_perm
);
949 switch (argv
[*arg_ptr
][0])
952 our_pred
->args
.perm
.kind
= PERM_AT_LEAST
;
955 our_pred
->args
.perm
.kind
= PERM_ANY
;
958 our_pred
->args
.perm
.kind
= PERM_EXACT
;
961 our_pred
->args
.perm
.val
= perm_val
& MODE_ALL
;
967 parse_print (char **argv
, int *arg_ptr
)
969 struct predicate
*our_pred
;
971 our_pred
= insert_primary (pred_print
);
972 /* -print has the side effect of printing. This prevents us
973 from doing undesired multiple printing when the user has
974 already specified -print. */
975 our_pred
->side_effects
= true;
976 our_pred
->no_default_print
= true;
977 our_pred
->need_stat
= false;
982 parse_print0 (char **argv
, int *arg_ptr
)
984 struct predicate
*our_pred
;
986 our_pred
= insert_primary (pred_print0
);
987 /* -print0 has the side effect of printing. This prevents us
988 from doing undesired multiple printing when the user has
989 already specified -print0. */
990 our_pred
->side_effects
= true;
991 our_pred
->no_default_print
= true;
992 our_pred
->need_stat
= false;
997 parse_printf (char **argv
, int *arg_ptr
)
999 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1001 return (insert_fprintf (stdout
, pred_fprintf
, argv
, arg_ptr
));
1005 parse_prune (char **argv
, int *arg_ptr
)
1007 struct predicate
*our_pred
;
1009 our_pred
= insert_primary (pred_prune
);
1010 our_pred
->need_stat
= false;
1011 /* -prune has a side effect that it does not descend into
1012 the current directory. */
1013 our_pred
->side_effects
= true;
1018 parse_regex (char **argv
, int *arg_ptr
)
1020 return insert_regex (argv
, arg_ptr
, false);
1024 insert_regex (char **argv
, int *arg_ptr
, boolean ignore_case
)
1026 struct predicate
*our_pred
;
1027 struct re_pattern_buffer
*re
;
1028 const char *error_message
;
1030 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1032 our_pred
= insert_primary (pred_regex
);
1033 our_pred
->need_stat
= false;
1034 re
= (struct re_pattern_buffer
*)
1035 xmalloc (sizeof (struct re_pattern_buffer
));
1036 our_pred
->args
.regex
= re
;
1037 re
->allocated
= 100;
1038 re
->buffer
= (unsigned char *) xmalloc (re
->allocated
);
1045 re
->translate
= xmalloc (256);
1046 /* Map uppercase characters to corresponding lowercase ones. */
1047 for (i
= 0; i
< 256; i
++)
1048 re
->translate
[i
] = ISUPPER (i
) ? tolower (i
) : i
;
1051 re
->translate
= NULL
;
1053 error_message
= re_compile_pattern (argv
[*arg_ptr
], strlen (argv
[*arg_ptr
]),
1056 error (1, 0, "%s", error_message
);
1062 parse_size (char **argv
, int *arg_ptr
)
1064 struct predicate
*our_pred
;
1066 enum comparison_type c_type
;
1070 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1072 len
= strlen (argv
[*arg_ptr
]);
1074 error (1, 0, _("invalid null argument to -size"));
1075 switch (argv
[*arg_ptr
][len
- 1])
1079 argv
[*arg_ptr
][len
- 1] = '\0';
1084 argv
[*arg_ptr
][len
- 1] = '\0';
1089 argv
[*arg_ptr
][len
- 1] = '\0';
1092 case 'M': /* Megabytes */
1093 blksize
= 1024*1024;
1094 argv
[*arg_ptr
][len
- 1] = '\0';
1097 case 'G': /* Gigabytes */
1098 blksize
= 1024*1024*1024;
1099 argv
[*arg_ptr
][len
- 1] = '\0';
1104 argv
[*arg_ptr
][len
- 1] = '\0';
1120 error (1, 0, _("invalid -size type `%c'"), argv
[*arg_ptr
][len
- 1]);
1122 if (!get_num (argv
[*arg_ptr
], &num
, &c_type
))
1124 our_pred
= insert_primary (pred_size
);
1125 our_pred
->args
.size
.kind
= c_type
;
1126 our_pred
->args
.size
.blocksize
= blksize
;
1127 our_pred
->args
.size
.size
= num
;
1133 parse_true (char **argv
, int *arg_ptr
)
1135 struct predicate
*our_pred
;
1137 our_pred
= insert_primary (pred_true
);
1138 our_pred
->need_stat
= false;
1143 parse_type (char **argv
, int *arg_ptr
)
1145 return insert_type (argv
, arg_ptr
, pred_type
);
1149 parse_uid (char **argv
, int *arg_ptr
)
1151 return (insert_num (argv
, arg_ptr
, pred_uid
));
1155 parse_used (char **argv
, int *arg_ptr
)
1157 struct predicate
*our_pred
;
1159 enum comparison_type c_type
;
1162 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1164 if (!get_num (argv
[*arg_ptr
], &num_days
, &c_type
))
1166 t
= num_days
* DAYSECS
;
1167 our_pred
= insert_primary (pred_used
);
1168 our_pred
->args
.info
.kind
= c_type
;
1169 our_pred
->args
.info
.negative
= t
< 0;
1170 our_pred
->args
.info
.l_val
= t
;
1176 parse_user (char **argv
, int *arg_ptr
)
1178 struct passwd
*cur_pwd
;
1179 struct predicate
*our_pred
;
1183 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1185 cur_pwd
= getpwnam (argv
[*arg_ptr
]);
1187 if (cur_pwd
!= NULL
)
1188 uid
= cur_pwd
->pw_uid
;
1191 uid_len
= strspn (argv
[*arg_ptr
], "0123456789");
1192 if ((uid_len
== 0) || (argv
[*arg_ptr
][uid_len
] != '\0'))
1194 uid
= atoi (argv
[*arg_ptr
]);
1196 our_pred
= insert_primary (pred_user
);
1197 our_pred
->args
.uid
= uid
;
1203 parse_version (char **argv
, int *arg_ptr
)
1205 extern char *version_string
;
1208 printf (_("GNU find version %s\n"), version_string
);
1213 parse_xdev (char **argv
, int *arg_ptr
)
1215 stay_on_filesystem
= true;
1220 parse_ignore_race (char **argv
, int *arg_ptr
)
1222 ignore_readdir_race
= true;
1227 parse_noignore_race (char **argv
, int *arg_ptr
)
1229 ignore_readdir_race
= false;
1234 parse_xtype (char **argv
, int *arg_ptr
)
1236 return insert_type (argv
, arg_ptr
, pred_xtype
);
1240 insert_type (char **argv
, int *arg_ptr
, boolean (*which_pred
) (/* ??? */))
1243 struct predicate
*our_pred
;
1245 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
)
1246 || (strlen (argv
[*arg_ptr
]) != 1))
1248 switch (argv
[*arg_ptr
][0])
1250 case 'b': /* block special */
1251 type_cell
= S_IFBLK
;
1253 case 'c': /* character special */
1254 type_cell
= S_IFCHR
;
1256 case 'd': /* directory */
1257 type_cell
= S_IFDIR
;
1259 case 'f': /* regular file */
1260 type_cell
= S_IFREG
;
1263 case 'l': /* symbolic link */
1264 type_cell
= S_IFLNK
;
1268 case 'p': /* pipe */
1269 type_cell
= S_IFIFO
;
1273 case 's': /* socket */
1274 type_cell
= S_IFSOCK
;
1278 case 'D': /* Solaris door */
1279 type_cell
= S_IFDOOR
;
1282 default: /* None of the above ... nuke 'em. */
1285 our_pred
= insert_primary (which_pred
);
1286 our_pred
->args
.type
= type_cell
;
1287 (*arg_ptr
)++; /* Move on to next argument. */
1291 /* If true, we've determined that the current fprintf predicate
1292 uses stat information. */
1293 static boolean fprintf_stat_needed
;
1296 insert_fprintf (FILE *fp
, boolean (*func
) (/* ??? */), char **argv
, int *arg_ptr
)
1298 char *format
; /* Beginning of unprocessed format string. */
1299 register char *scan
; /* Current address in scanning `format'. */
1300 register char *scan2
; /* Address inside of element being scanned. */
1301 struct segment
**segmentp
; /* Address of current segment. */
1302 struct predicate
*our_pred
;
1304 format
= argv
[(*arg_ptr
)++];
1306 fprintf_stat_needed
= false; /* Might be overridden later. */
1307 our_pred
= insert_primary (func
);
1308 our_pred
->side_effects
= true;
1309 our_pred
->no_default_print
= true;
1310 our_pred
->args
.printf_vec
.stream
= fp
;
1311 segmentp
= &our_pred
->args
.printf_vec
.segment
;
1314 for (scan
= format
; *scan
; scan
++)
1319 if (*scan2
>= '0' && *scan2
<= '7')
1323 for (i
= n
= 0; i
< 3 && (*scan2
>= '0' && *scan2
<= '7');
1325 n
= 8 * n
+ *scan2
- '0';
1340 make_segment (segmentp
, format
, scan
- format
, KIND_STOP
);
1341 our_pred
->need_stat
= fprintf_stat_needed
;
1359 /* *scan = '\\'; * it already is */
1363 _("warning: unrecognized escape `\\%c'"), *scan2
);
1368 segmentp
= make_segment (segmentp
, format
, scan
- format
+ 1,
1370 format
= scan2
+ 1; /* Move past the escape. */
1371 scan
= scan2
; /* Incremented immediately by `for'. */
1373 else if (*scan
== '%')
1377 segmentp
= make_segment (segmentp
, format
, scan
- format
+ 1,
1383 /* Scan past flags, width and precision, to verify kind. */
1384 for (scan2
= scan
; *++scan2
&& strchr ("-+ #", *scan2
);)
1386 while (ISDIGIT (*scan2
))
1389 for (scan2
++; ISDIGIT (*scan2
); scan2
++)
1391 if (strchr ("abcdfFgGhHiklmnpPstuU", *scan2
))
1393 segmentp
= make_segment (segmentp
, format
, scan2
- format
,
1398 else if (strchr ("ACT", *scan2
) && scan2
[1])
1400 segmentp
= make_segment (segmentp
, format
, scan2
- format
,
1401 *scan2
| (scan2
[1] << 8));
1408 /* An unrecognized % escape. Print the char after the %. */
1409 error (0, 0, _("warning: unrecognized format directive `%%%c'"),
1411 segmentp
= make_segment (segmentp
, format
, scan
- format
,
1420 make_segment (segmentp
, format
, scan
- format
, KIND_PLAIN
);
1421 our_pred
->need_stat
= fprintf_stat_needed
;
1425 /* Create a new fprintf segment in *SEGMENT, with type KIND,
1426 from the text in FORMAT, which has length LEN.
1427 Return the address of the `next' pointer of the new segment. */
1429 static struct segment
**
1430 make_segment (struct segment
**segment
, char *format
, int len
, int kind
)
1434 *segment
= (struct segment
*) xmalloc (sizeof (struct segment
));
1436 (*segment
)->kind
= kind
;
1437 (*segment
)->next
= NULL
;
1438 (*segment
)->text_len
= len
;
1440 fmt
= (*segment
)->text
= xmalloc (len
+ sizeof "d");
1441 strncpy (fmt
, format
, len
);
1444 switch (kind
& 0xff)
1446 case KIND_PLAIN
: /* Plain text string, no % conversion. */
1447 case KIND_STOP
: /* Terminate argument, no newline. */
1450 case 'a': /* atime in `ctime' format */
1451 case 'A': /* atime in user-specified strftime format */
1452 case 'b': /* size in 512-byte blocks */
1453 case 'c': /* ctime in `ctime' format */
1454 case 'C': /* ctime in user-specified strftime format */
1455 case 'F': /* filesystem type */
1456 case 'G': /* GID number */
1457 case 'g': /* group name */
1458 case 'i': /* inode number */
1459 case 'k': /* size in 1K blocks */
1460 case 'l': /* object of symlink */
1461 case 'n': /* number of links */
1462 case 's': /* size in bytes */
1463 case 't': /* mtime in `ctime' format */
1464 case 'T': /* mtime in user-specified strftime format */
1465 case 'U': /* UID number */
1466 case 'u': /* user name */
1467 fprintf_stat_needed
= true;
1469 case 'f': /* basename of path */
1470 case 'h': /* leading directories part of path */
1471 case 'H': /* ARGV element file was found under */
1472 case 'p': /* pathname */
1473 case 'P': /* pathname with ARGV element stripped */
1477 case 'd': /* depth in search tree (0 = ARGV element) */
1481 case 'm': /* mode as octal number (perms only) */
1483 fprintf_stat_needed
= true;
1488 return (&(*segment
)->next
);
1491 /* handles both exec and ok predicate */
1493 insert_exec_ok (boolean (*func
) (/* ??? */), char **argv
, int *arg_ptr
)
1495 int start
, end
; /* Indexes in ARGV of start & end of cmd. */
1496 int num_paths
; /* Number of args with path replacements. */
1497 int path_pos
; /* Index in array of path replacements. */
1498 int vec_pos
; /* Index in array of args. */
1499 struct predicate
*our_pred
;
1500 struct exec_val
*execp
; /* Pointer for efficiency. */
1502 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1505 /* Count the number of args with path replacements, up until the ';'. */
1507 for (end
= start
, num_paths
= 0;
1509 && ((argv
[end
][0] != ';') || (argv
[end
][1] != '\0'));
1511 if (strstr (argv
[end
], "{}"))
1513 /* Fail if no command given or no semicolon found. */
1514 if ((end
== start
) || (argv
[end
] == NULL
))
1520 our_pred
= insert_primary (func
);
1521 our_pred
->side_effects
= true;
1522 our_pred
->no_default_print
= true;
1523 execp
= &our_pred
->args
.exec_vec
;
1525 (struct path_arg
*) xmalloc (sizeof (struct path_arg
) * (num_paths
+ 1));
1526 execp
->vec
= (char **) xmalloc (sizeof (char *) * (end
- start
+ 1));
1527 /* Record the positions of all args, and the args with path replacements. */
1528 for (end
= start
, path_pos
= vec_pos
= 0;
1530 && ((argv
[end
][0] != ';') || (argv
[end
][1] != '\0'));
1535 execp
->paths
[path_pos
].count
= 0;
1536 for (p
= argv
[end
]; *p
; ++p
)
1537 if (p
[0] == '{' && p
[1] == '}')
1539 execp
->paths
[path_pos
].count
++;
1542 if (execp
->paths
[path_pos
].count
)
1544 execp
->paths
[path_pos
].offset
= vec_pos
;
1545 execp
->paths
[path_pos
].origarg
= argv
[end
];
1548 execp
->vec
[vec_pos
++] = argv
[end
];
1550 execp
->paths
[path_pos
].offset
= -1;
1551 execp
->vec
[vec_pos
] = NULL
;
1553 if (argv
[end
] == NULL
)
1560 /* Get a number of days and comparison type.
1561 STR is the ASCII representation.
1562 Set *NUM_DAYS to the number of days, taken as being from
1563 the current moment (or possibly midnight). Thus the sense of the
1564 comparison type appears to be reversed.
1565 Set *COMP_TYPE to the kind of comparison that is requested.
1567 Return true if all okay, false if input error.
1569 Used by -atime, -ctime and -mtime (parsers) to
1570 get the appropriate information for a time predicate processor. */
1573 get_num_days (char *str
, uintmax_t *num_days
, enum comparison_type
*comp_type
)
1575 boolean r
= get_num (str
, num_days
, comp_type
);
1579 case COMP_LT
: *comp_type
= COMP_GT
; break;
1580 case COMP_GT
: *comp_type
= COMP_LT
; break;
1586 /* Insert a time predicate PRED.
1587 ARGV is a pointer to the argument array.
1588 ARG_PTR is a pointer to an index into the array, incremented if
1591 Return true if input is valid, false if not.
1593 A new predicate node is assigned, along with an argument node
1594 obtained with malloc.
1596 Used by -atime, -ctime, and -mtime parsers. */
1599 insert_time (char **argv
, int *arg_ptr
, PFB pred
)
1601 struct predicate
*our_pred
;
1603 enum comparison_type c_type
;
1606 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1608 if (!get_num_days (argv
[*arg_ptr
], &num_days
, &c_type
))
1611 /* Figure out the timestamp value we are looking for. */
1612 t
= ( cur_day_start
- num_days
* DAYSECS
1613 + ((c_type
== COMP_GT
) ? DAYSECS
- 1 : 0));
1615 intmax_t val
= ( (intmax_t)cur_day_start
- num_days
* DAYSECS
1616 + ((c_type
== COMP_GT
) ? DAYSECS
- 1 : 0));
1619 /* Check for possibility of an overflow */
1620 if ( (intmax_t)t
!= val
)
1622 error (1, 0, "arithmetic overflow while converting %s days to a number of seconds", argv
[*arg_ptr
]);
1626 our_pred
= insert_primary (pred
);
1627 our_pred
->args
.info
.kind
= c_type
;
1628 our_pred
->args
.info
.negative
= t
< 0;
1629 our_pred
->args
.info
.l_val
= t
;
1632 printf (_("inserting %s\n"), our_pred
->p_name
);
1633 printf (_(" type: %s %s "),
1634 (c_type
== COMP_GT
) ? "gt" :
1635 ((c_type
== COMP_LT
) ? "lt" : ((c_type
== COMP_EQ
) ? "eq" : "?")),
1636 (c_type
== COMP_GT
) ? " >" :
1637 ((c_type
== COMP_LT
) ? " <" : ((c_type
== COMP_EQ
) ? ">=" : " ?")));
1638 t
= our_pred
->args
.info
.l_val
;
1639 printf ("%ju %s", (uintmax_t) our_pred
->args
.info
.l_val
, ctime (&t
));
1640 if (c_type
== COMP_EQ
)
1642 t
= our_pred
->args
.info
.l_val
+= DAYSECS
;
1643 printf (" < %ju %s",
1644 (uintmax_t) our_pred
->args
.info
.l_val
, ctime (&t
));
1645 our_pred
->args
.info
.l_val
-= DAYSECS
;
1651 /* Get a number with comparision information.
1652 The sense of the comparision information is 'normal'; that is,
1653 '+' looks for a count > than the number and '-' less than.
1655 STR is the ASCII representation of the number.
1656 Set *NUM to the number.
1657 Set *COMP_TYPE to the kind of comparison that is requested.
1659 Return true if all okay, false if input error. */
1662 get_num (char *str
, uintmax_t *num
, enum comparison_type
*comp_type
)
1664 int len_num
; /* Length of field. */
1671 *comp_type
= COMP_GT
;
1675 *comp_type
= COMP_LT
;
1679 *comp_type
= COMP_EQ
;
1683 return xstrtoumax (str
, NULL
, 10, num
, "") == LONGINT_OK
;
1686 /* Insert a number predicate.
1687 ARGV is a pointer to the argument array.
1688 *ARG_PTR is an index into ARGV, incremented if all went well.
1689 *PRED is the predicate processor to insert.
1691 Return true if input is valid, false if error.
1693 A new predicate node is assigned, along with an argument node
1694 obtained with malloc.
1696 Used by -inum and -links parsers. */
1699 insert_num (char **argv
, int *arg_ptr
, PFB pred
)
1701 struct predicate
*our_pred
;
1703 enum comparison_type c_type
;
1705 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1707 if (!get_num (argv
[*arg_ptr
], &num
, &c_type
))
1709 our_pred
= insert_primary (pred
);
1710 our_pred
->args
.info
.kind
= c_type
;
1711 our_pred
->args
.info
.l_val
= num
;
1714 printf (_("inserting %s\n"), our_pred
->p_name
);
1715 printf (_(" type: %s %s "),
1716 (c_type
== COMP_GT
) ? "gt" :
1717 ((c_type
== COMP_LT
) ? "lt" : ((c_type
== COMP_EQ
) ? "eq" : "?")),
1718 (c_type
== COMP_GT
) ? " >" :
1719 ((c_type
== COMP_LT
) ? " <" : ((c_type
== COMP_EQ
) ? " =" : " ?")));
1720 printf ("%ju\n", our_pred
->args
.info
.l_val
);
1726 open_output_file (char *path
)
1730 if (!strcmp (path
, "/dev/stderr"))
1732 else if (!strcmp (path
, "/dev/stdout"))
1734 f
= fopen (path
, "w");
1736 error (1, errno
, "%s", path
);