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_xtype
PARAMS((char *argv
[], int *arg_ptr
));
119 static boolean insert_regex
PARAMS((char *argv
[], int *arg_ptr
, boolean ignore_case
));
120 static boolean insert_type
PARAMS((char *argv
[], int *arg_ptr
, boolean (*which_pred
)()));
121 static boolean insert_fprintf
PARAMS((FILE *fp
, boolean (*func
)(), char *argv
[], int *arg_ptr
));
122 static struct segment
**make_segment
PARAMS((struct segment
**segment
, char *format
, int len
, int kind
));
123 static boolean insert_exec_ok
PARAMS((boolean (*func
)(), char *argv
[], int *arg_ptr
));
124 static boolean get_num_days
PARAMS((char *str
, uintmax_t *num_days
, enum comparison_type
*comp_type
));
125 static boolean insert_time
PARAMS((char *argv
[], int *arg_ptr
, PFB pred
));
126 static boolean get_num
PARAMS((char *str
, uintmax_t *num
, enum comparison_type
*comp_type
));
127 static boolean insert_num
PARAMS((char *argv
[], int *arg_ptr
, PFB pred
));
128 static FILE *open_output_file
PARAMS((char *path
));
131 char *find_pred_name
PARAMS((PFB pred_func
));
140 /* GNU find predicates that are not mentioned in POSIX.2 are marked `GNU'.
141 If they are in some Unix versions of find, they are marked `Unix'. */
143 static struct parser_table
const parse_table
[] =
146 {"not", parse_negate
}, /* GNU */
149 {",", parse_comma
}, /* GNU */
151 {"amin", parse_amin
}, /* GNU */
152 {"and", parse_and
}, /* GNU */
153 {"anewer", parse_anewer
}, /* GNU */
154 {"atime", parse_atime
},
155 {"cmin", parse_cmin
}, /* GNU */
156 {"cnewer", parse_cnewer
}, /* GNU */
157 #ifdef UNIMPLEMENTED_UNIX
158 /* It's pretty ugly for find to know about archive formats.
159 Plus what it could do with cpio archives is very limited.
160 Better to leave it out. */
161 {"cpio", parse_cpio
}, /* Unix */
163 {"ctime", parse_ctime
},
164 {"daystart", parse_daystart
}, /* GNU */
165 {"depth", parse_depth
},
166 {"empty", parse_empty
}, /* GNU */
167 {"exec", parse_exec
},
168 {"false", parse_false
}, /* GNU */
169 {"fls", parse_fls
}, /* GNU */
170 {"follow", parse_follow
}, /* GNU, Unix */
171 {"fprint", parse_fprint
}, /* GNU */
172 {"fprint0", parse_fprint0
}, /* GNU */
173 {"fprintf", parse_fprintf
}, /* GNU */
174 {"fstype", parse_fstype
}, /* GNU, Unix */
175 {"gid", parse_gid
}, /* GNU */
176 {"group", parse_group
},
177 {"help", parse_help
}, /* GNU */
178 {"-help", parse_help
}, /* GNU */
179 {"ilname", parse_ilname
}, /* GNU */
180 {"iname", parse_iname
}, /* GNU */
181 {"inum", parse_inum
}, /* GNU, Unix */
182 {"ipath", parse_ipath
}, /* GNU */
183 {"iregex", parse_iregex
}, /* GNU */
184 {"links", parse_links
},
185 {"lname", parse_lname
}, /* GNU */
186 {"ls", parse_ls
}, /* GNU, Unix */
187 {"maxdepth", parse_maxdepth
}, /* GNU */
188 {"mindepth", parse_mindepth
}, /* GNU */
189 {"mmin", parse_mmin
}, /* GNU */
190 {"mount", parse_xdev
}, /* Unix */
191 {"mtime", parse_mtime
},
192 {"name", parse_name
},
193 #ifdef UNIMPLEMENTED_UNIX
194 {"ncpio", parse_ncpio
}, /* Unix */
196 {"newer", parse_newer
},
197 {"noleaf", parse_noleaf
}, /* GNU */
198 {"nogroup", parse_nogroup
},
199 {"nouser", parse_nouser
},
201 {"or", parse_or
}, /* GNU */
203 {"path", parse_path
}, /* GNU, HP-UX */
204 {"perm", parse_perm
},
205 {"print", parse_print
},
206 {"print0", parse_print0
}, /* GNU */
207 {"printf", parse_printf
}, /* GNU */
208 {"prune", parse_prune
},
209 {"regex", parse_regex
}, /* GNU */
210 {"size", parse_size
},
211 {"true", parse_true
}, /* GNU */
212 {"type", parse_type
},
213 {"uid", parse_uid
}, /* GNU */
214 {"used", parse_used
}, /* GNU */
215 {"user", parse_user
},
216 {"version", parse_version
}, /* GNU */
217 {"-version", parse_version
}, /* GNU */
218 {"xdev", parse_xdev
},
219 {"xtype", parse_xtype
}, /* GNU */
223 /* Return a pointer to the parser function to invoke for predicate
225 Return NULL if SEARCH_NAME is not a valid predicate name. */
228 find_parser (char *search_name
)
232 if (*search_name
== '-')
234 for (i
= 0; parse_table
[i
].parser_name
!= 0; i
++)
235 if (strcmp (parse_table
[i
].parser_name
, search_name
) == 0)
236 return (parse_table
[i
].parser_func
);
240 /* The parsers are responsible to continue scanning ARGV for
241 their arguments. Each parser knows what is and isn't
244 ARGV is the argument array.
245 *ARG_PTR is the index to start at in ARGV,
246 updated to point beyond the last element consumed.
248 The predicate structure is updated with the new information. */
251 parse_amin (char **argv
, int *arg_ptr
)
253 struct predicate
*our_pred
;
255 enum comparison_type c_type
;
258 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
260 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
262 t
= cur_day_start
+ DAYSECS
- num
* 60;
263 our_pred
= insert_primary (pred_amin
);
264 our_pred
->args
.info
.kind
= c_type
;
265 our_pred
->args
.info
.negative
= t
< 0;
266 our_pred
->args
.info
.l_val
= t
;
272 parse_and (char **argv
, int *arg_ptr
)
274 struct predicate
*our_pred
;
276 our_pred
= get_new_pred ();
277 our_pred
->pred_func
= pred_and
;
279 our_pred
->p_name
= find_pred_name (pred_and
);
281 our_pred
->p_type
= BI_OP
;
282 our_pred
->p_prec
= AND_PREC
;
283 our_pred
->need_stat
= false;
288 parse_anewer (char **argv
, int *arg_ptr
)
290 struct predicate
*our_pred
;
291 struct stat stat_newer
;
293 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
295 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
296 error (1, errno
, "%s", argv
[*arg_ptr
]);
297 our_pred
= insert_primary (pred_anewer
);
298 our_pred
->args
.time
= stat_newer
.st_mtime
;
304 parse_atime (char **argv
, int *arg_ptr
)
306 return (insert_time (argv
, arg_ptr
, pred_atime
));
310 parse_close (char **argv
, int *arg_ptr
)
312 struct predicate
*our_pred
;
314 our_pred
= get_new_pred ();
315 our_pred
->pred_func
= pred_close
;
317 our_pred
->p_name
= find_pred_name (pred_close
);
319 our_pred
->p_type
= CLOSE_PAREN
;
320 our_pred
->p_prec
= NO_PREC
;
321 our_pred
->need_stat
= false;
326 parse_cmin (char **argv
, int *arg_ptr
)
328 struct predicate
*our_pred
;
330 enum comparison_type c_type
;
333 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
335 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
337 t
= cur_day_start
+ DAYSECS
- num
* 60;
338 our_pred
= insert_primary (pred_cmin
);
339 our_pred
->args
.info
.kind
= c_type
;
340 our_pred
->args
.info
.negative
= t
< 0;
341 our_pred
->args
.info
.l_val
= t
;
347 parse_cnewer (char **argv
, int *arg_ptr
)
349 struct predicate
*our_pred
;
350 struct stat stat_newer
;
352 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
354 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
355 error (1, errno
, "%s", argv
[*arg_ptr
]);
356 our_pred
= insert_primary (pred_cnewer
);
357 our_pred
->args
.time
= stat_newer
.st_mtime
;
363 parse_comma (char **argv
, int *arg_ptr
)
365 struct predicate
*our_pred
;
367 our_pred
= get_new_pred ();
368 our_pred
->pred_func
= pred_comma
;
370 our_pred
->p_name
= find_pred_name (pred_comma
);
372 our_pred
->p_type
= BI_OP
;
373 our_pred
->p_prec
= COMMA_PREC
;
374 our_pred
->need_stat
= false;
379 parse_ctime (char **argv
, int *arg_ptr
)
381 return (insert_time (argv
, arg_ptr
, pred_ctime
));
385 parse_daystart (char **argv
, int *arg_ptr
)
389 if (full_days
== false)
391 cur_day_start
+= DAYSECS
;
392 local
= localtime (&cur_day_start
);
393 cur_day_start
-= (local
394 ? (local
->tm_sec
+ local
->tm_min
* 60
395 + local
->tm_hour
* 3600)
396 : cur_day_start
% DAYSECS
);
403 parse_depth (char **argv
, int *arg_ptr
)
405 do_dir_first
= false;
410 parse_empty (char **argv
, int *arg_ptr
)
412 insert_primary (pred_empty
);
417 parse_exec (char **argv
, int *arg_ptr
)
419 return (insert_exec_ok (pred_exec
, argv
, arg_ptr
));
423 parse_false (char **argv
, int *arg_ptr
)
425 struct predicate
*our_pred
;
427 our_pred
= insert_primary (pred_false
);
428 our_pred
->need_stat
= false;
433 parse_fls (char **argv
, int *arg_ptr
)
435 struct predicate
*our_pred
;
437 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
439 our_pred
= insert_primary (pred_fls
);
440 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
441 our_pred
->side_effects
= true;
442 our_pred
->no_default_print
= true;
448 parse_fprintf (char **argv
, int *arg_ptr
)
452 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
454 if (argv
[*arg_ptr
+ 1] == NULL
)
456 /* Ensure we get "missing arg" message, not "invalid arg". */
460 fp
= open_output_file (argv
[*arg_ptr
]);
462 return (insert_fprintf (fp
, pred_fprintf
, argv
, arg_ptr
));
466 parse_follow (char **argv
, int *arg_ptr
)
470 no_leaf_check
= true;
475 parse_fprint (char **argv
, int *arg_ptr
)
477 struct predicate
*our_pred
;
479 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
481 our_pred
= insert_primary (pred_fprint
);
482 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
483 our_pred
->side_effects
= true;
484 our_pred
->no_default_print
= true;
485 our_pred
->need_stat
= false;
491 parse_fprint0 (char **argv
, int *arg_ptr
)
493 struct predicate
*our_pred
;
495 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
497 our_pred
= insert_primary (pred_fprint0
);
498 our_pred
->args
.stream
= open_output_file (argv
[*arg_ptr
]);
499 our_pred
->side_effects
= true;
500 our_pred
->no_default_print
= true;
501 our_pred
->need_stat
= false;
507 parse_fstype (char **argv
, int *arg_ptr
)
509 struct predicate
*our_pred
;
511 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
513 our_pred
= insert_primary (pred_fstype
);
514 our_pred
->args
.str
= argv
[*arg_ptr
];
520 parse_gid (char **argv
, int *arg_ptr
)
522 return (insert_num (argv
, arg_ptr
, pred_gid
));
526 parse_group (char **argv
, int *arg_ptr
)
528 struct group
*cur_gr
;
529 struct predicate
*our_pred
;
533 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
535 cur_gr
= getgrnam (argv
[*arg_ptr
]);
538 gid
= cur_gr
->gr_gid
;
541 gid_len
= strspn (argv
[*arg_ptr
], "0123456789");
542 if ((gid_len
== 0) || (argv
[*arg_ptr
][gid_len
] != '\0'))
544 gid
= atoi (argv
[*arg_ptr
]);
546 our_pred
= insert_primary (pred_group
);
547 our_pred
->args
.gid
= gid
;
553 parse_help (char **argv
, int *arg_ptr
)
556 Usage: %s [path...] [expression]\n"), program_name
);
558 default path is the current directory; default expression is -print\n\
559 expression may consist of:\n\
560 operators (decreasing precedence; -and is implicit where no others are given):\n\
561 ( EXPR ) ! EXPR -not EXPR EXPR1 -a EXPR2 EXPR1 -and EXPR2\n"));
563 EXPR1 -o EXPR2 EXPR1 -or EXPR2 EXPR1 , EXPR2\n\
564 options (always true): -daystart -depth -follow --help\n\
565 -maxdepth LEVELS -mindepth LEVELS -mount -noleaf --version -xdev\n\
566 tests (N can be +N or -N or N): -amin N -anewer FILE -atime N -cmin N\n"));
568 -cnewer FILE -ctime N -empty -false -fstype TYPE -gid N -group NAME\n\
569 -ilname PATTERN -iname PATTERN -inum N -ipath PATTERN -iregex PATTERN\n\
570 -links N -lname PATTERN -mmin N -mtime N -name PATTERN -newer FILE\n"));
572 -nouser -nogroup -path PATTERN -perm [+-]MODE -regex PATTERN\n\
573 -size N[bckw] -true -type [bcdpfls] -uid N -used N -user NAME\n\
574 -xtype [bcdpfls]\n"));
576 actions: -exec COMMAND ; -fprint FILE -fprint0 FILE -fprintf FILE FORMAT\n\
577 -ok COMMAND ; -print -print0 -printf FORMAT -prune -ls\n"));
578 puts (_("\nReport bugs to <bug-findutils@gnu.org>."));
583 parse_ilname (char **argv
, int *arg_ptr
)
585 struct predicate
*our_pred
;
587 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
589 our_pred
= insert_primary (pred_ilname
);
590 our_pred
->args
.str
= argv
[*arg_ptr
];
596 parse_iname (char **argv
, int *arg_ptr
)
598 struct predicate
*our_pred
;
600 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
602 our_pred
= insert_primary (pred_iname
);
603 our_pred
->need_stat
= false;
604 our_pred
->args
.str
= argv
[*arg_ptr
];
610 parse_inum (char **argv
, int *arg_ptr
)
612 return (insert_num (argv
, arg_ptr
, pred_inum
));
616 parse_ipath (char **argv
, int *arg_ptr
)
618 struct predicate
*our_pred
;
620 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
622 our_pred
= insert_primary (pred_ipath
);
623 our_pred
->need_stat
= false;
624 our_pred
->args
.str
= argv
[*arg_ptr
];
630 parse_iregex (char **argv
, int *arg_ptr
)
632 return insert_regex (argv
, arg_ptr
, true);
636 parse_links (char **argv
, int *arg_ptr
)
638 return (insert_num (argv
, arg_ptr
, pred_links
));
642 parse_lname (char **argv
, int *arg_ptr
)
644 struct predicate
*our_pred
;
646 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
648 our_pred
= insert_primary (pred_lname
);
649 our_pred
->args
.str
= argv
[*arg_ptr
];
655 parse_ls (char **argv
, int *arg_ptr
)
657 struct predicate
*our_pred
;
659 our_pred
= insert_primary (pred_ls
);
660 our_pred
->side_effects
= true;
661 our_pred
->no_default_print
= true;
666 parse_maxdepth (char **argv
, int *arg_ptr
)
670 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
672 depth_len
= strspn (argv
[*arg_ptr
], "0123456789");
673 if ((depth_len
== 0) || (argv
[*arg_ptr
][depth_len
] != '\0'))
675 maxdepth
= atoi (argv
[*arg_ptr
]);
683 parse_mindepth (char **argv
, int *arg_ptr
)
687 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
689 depth_len
= strspn (argv
[*arg_ptr
], "0123456789");
690 if ((depth_len
== 0) || (argv
[*arg_ptr
][depth_len
] != '\0'))
692 mindepth
= atoi (argv
[*arg_ptr
]);
700 parse_mmin (char **argv
, int *arg_ptr
)
702 struct predicate
*our_pred
;
704 enum comparison_type c_type
;
707 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
709 if (!get_num_days (argv
[*arg_ptr
], &num
, &c_type
))
711 t
= cur_day_start
+ DAYSECS
- num
* 60;
712 our_pred
= insert_primary (pred_mmin
);
713 our_pred
->args
.info
.kind
= c_type
;
714 our_pred
->args
.info
.negative
= t
< 0;
715 our_pred
->args
.info
.l_val
= t
;
721 parse_mtime (char **argv
, int *arg_ptr
)
723 return (insert_time (argv
, arg_ptr
, pred_mtime
));
727 parse_name (char **argv
, int *arg_ptr
)
729 struct predicate
*our_pred
;
731 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
733 our_pred
= insert_primary (pred_name
);
734 our_pred
->need_stat
= false;
735 our_pred
->args
.str
= argv
[*arg_ptr
];
741 parse_negate (char **argv
, int *arg_ptr
)
743 struct predicate
*our_pred
;
745 our_pred
= get_new_pred_chk_op ();
746 our_pred
->pred_func
= pred_negate
;
748 our_pred
->p_name
= find_pred_name (pred_negate
);
750 our_pred
->p_type
= UNI_OP
;
751 our_pred
->p_prec
= NEGATE_PREC
;
752 our_pred
->need_stat
= false;
757 parse_newer (char **argv
, int *arg_ptr
)
759 struct predicate
*our_pred
;
760 struct stat stat_newer
;
762 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
764 if ((*xstat
) (argv
[*arg_ptr
], &stat_newer
))
765 error (1, errno
, "%s", argv
[*arg_ptr
]);
766 our_pred
= insert_primary (pred_newer
);
767 our_pred
->args
.time
= stat_newer
.st_mtime
;
773 parse_noleaf (char **argv
, int *arg_ptr
)
775 no_leaf_check
= true;
780 /* Arbitrary amount by which to increase size
781 of `uid_unused' and `gid_unused'. */
782 #define ALLOC_STEP 2048
784 /* Boolean: if uid_unused[n] is nonzero, then UID n has no passwd entry. */
785 char *uid_unused
= NULL
;
787 /* Number of elements in `uid_unused'. */
788 unsigned uid_allocated
;
790 /* Similar for GIDs and group entries. */
791 char *gid_unused
= NULL
;
792 unsigned gid_allocated
;
796 parse_nogroup (char **argv
, int *arg_ptr
)
798 struct predicate
*our_pred
;
800 our_pred
= insert_primary (pred_nogroup
);
802 if (gid_unused
== NULL
)
806 gid_allocated
= ALLOC_STEP
;
807 gid_unused
= xmalloc (gid_allocated
);
808 memset (gid_unused
, 1, gid_allocated
);
810 while ((gr
= getgrent ()) != NULL
)
812 if ((unsigned) gr
->gr_gid
>= gid_allocated
)
814 unsigned new_allocated
= (unsigned) gr
->gr_gid
+ ALLOC_STEP
;
815 gid_unused
= xrealloc (gid_unused
, new_allocated
);
816 memset (gid_unused
+ gid_allocated
, 1,
817 new_allocated
- gid_allocated
);
818 gid_allocated
= new_allocated
;
820 gid_unused
[(unsigned) gr
->gr_gid
] = 0;
829 parse_nouser (char **argv
, int *arg_ptr
)
831 struct predicate
*our_pred
;
833 our_pred
= insert_primary (pred_nouser
);
835 if (uid_unused
== NULL
)
839 uid_allocated
= ALLOC_STEP
;
840 uid_unused
= xmalloc (uid_allocated
);
841 memset (uid_unused
, 1, uid_allocated
);
843 while ((pw
= getpwent ()) != NULL
)
845 if ((unsigned) pw
->pw_uid
>= uid_allocated
)
847 unsigned new_allocated
= (unsigned) pw
->pw_uid
+ ALLOC_STEP
;
848 uid_unused
= xrealloc (uid_unused
, new_allocated
);
849 memset (uid_unused
+ uid_allocated
, 1,
850 new_allocated
- uid_allocated
);
851 uid_allocated
= new_allocated
;
853 uid_unused
[(unsigned) pw
->pw_uid
] = 0;
862 parse_ok (char **argv
, int *arg_ptr
)
864 return (insert_exec_ok (pred_ok
, argv
, arg_ptr
));
868 parse_open (char **argv
, int *arg_ptr
)
870 struct predicate
*our_pred
;
872 our_pred
= get_new_pred_chk_op ();
873 our_pred
->pred_func
= pred_open
;
875 our_pred
->p_name
= find_pred_name (pred_open
);
877 our_pred
->p_type
= OPEN_PAREN
;
878 our_pred
->p_prec
= NO_PREC
;
879 our_pred
->need_stat
= false;
884 parse_or (char **argv
, int *arg_ptr
)
886 struct predicate
*our_pred
;
888 our_pred
= get_new_pred ();
889 our_pred
->pred_func
= pred_or
;
891 our_pred
->p_name
= find_pred_name (pred_or
);
893 our_pred
->p_type
= BI_OP
;
894 our_pred
->p_prec
= OR_PREC
;
895 our_pred
->need_stat
= false;
900 parse_path (char **argv
, int *arg_ptr
)
902 struct predicate
*our_pred
;
904 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
906 our_pred
= insert_primary (pred_path
);
907 our_pred
->need_stat
= false;
908 our_pred
->args
.str
= argv
[*arg_ptr
];
914 parse_perm (char **argv
, int *arg_ptr
)
918 struct mode_change
*change
;
919 struct predicate
*our_pred
;
921 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
924 switch (argv
[*arg_ptr
][0])
935 change
= mode_compile (argv
[*arg_ptr
] + mode_start
, MODE_MASK_PLUS
);
936 if (change
== MODE_INVALID
)
937 error (1, 0, _("invalid mode `%s'"), argv
[*arg_ptr
]);
938 else if (change
== MODE_MEMORY_EXHAUSTED
)
939 error (1, 0, _("virtual memory exhausted"));
940 perm_val
= mode_adjust (0, change
);
943 our_pred
= insert_primary (pred_perm
);
945 switch (argv
[*arg_ptr
][0])
948 our_pred
->args
.perm
.kind
= PERM_AT_LEAST
;
951 our_pred
->args
.perm
.kind
= PERM_ANY
;
954 our_pred
->args
.perm
.kind
= PERM_EXACT
;
957 our_pred
->args
.perm
.val
= perm_val
& MODE_ALL
;
963 parse_print (char **argv
, int *arg_ptr
)
965 struct predicate
*our_pred
;
967 our_pred
= insert_primary (pred_print
);
968 /* -print has the side effect of printing. This prevents us
969 from doing undesired multiple printing when the user has
970 already specified -print. */
971 our_pred
->side_effects
= true;
972 our_pred
->no_default_print
= true;
973 our_pred
->need_stat
= false;
978 parse_print0 (char **argv
, int *arg_ptr
)
980 struct predicate
*our_pred
;
982 our_pred
= insert_primary (pred_print0
);
983 /* -print0 has the side effect of printing. This prevents us
984 from doing undesired multiple printing when the user has
985 already specified -print0. */
986 our_pred
->side_effects
= true;
987 our_pred
->no_default_print
= true;
988 our_pred
->need_stat
= false;
993 parse_printf (char **argv
, int *arg_ptr
)
995 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
997 return (insert_fprintf (stdout
, pred_fprintf
, argv
, arg_ptr
));
1001 parse_prune (char **argv
, int *arg_ptr
)
1003 struct predicate
*our_pred
;
1005 our_pred
= insert_primary (pred_prune
);
1006 our_pred
->need_stat
= false;
1007 /* -prune has a side effect that it does not descend into
1008 the current directory. */
1009 our_pred
->side_effects
= true;
1014 parse_regex (char **argv
, int *arg_ptr
)
1016 return insert_regex (argv
, arg_ptr
, false);
1020 insert_regex (char **argv
, int *arg_ptr
, boolean ignore_case
)
1022 struct predicate
*our_pred
;
1023 struct re_pattern_buffer
*re
;
1024 const char *error_message
;
1026 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1028 our_pred
= insert_primary (pred_regex
);
1029 our_pred
->need_stat
= false;
1030 re
= (struct re_pattern_buffer
*)
1031 xmalloc (sizeof (struct re_pattern_buffer
));
1032 our_pred
->args
.regex
= re
;
1033 re
->allocated
= 100;
1034 re
->buffer
= (unsigned char *) xmalloc (re
->allocated
);
1041 re
->translate
= xmalloc (256);
1042 /* Map uppercase characters to corresponding lowercase ones. */
1043 for (i
= 0; i
< 256; i
++)
1044 re
->translate
[i
] = ISUPPER (i
) ? tolower (i
) : i
;
1047 re
->translate
= NULL
;
1049 error_message
= re_compile_pattern (argv
[*arg_ptr
], strlen (argv
[*arg_ptr
]),
1052 error (1, 0, "%s", error_message
);
1058 parse_size (char **argv
, int *arg_ptr
)
1060 struct predicate
*our_pred
;
1062 enum comparison_type c_type
;
1066 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1068 len
= strlen (argv
[*arg_ptr
]);
1070 error (1, 0, _("invalid null argument to -size"));
1071 switch (argv
[*arg_ptr
][len
- 1])
1075 argv
[*arg_ptr
][len
- 1] = '\0';
1080 argv
[*arg_ptr
][len
- 1] = '\0';
1085 argv
[*arg_ptr
][len
- 1] = '\0';
1090 argv
[*arg_ptr
][len
- 1] = '\0';
1106 error (1, 0, _("invalid -size type `%c'"), argv
[*arg_ptr
][len
- 1]);
1108 if (!get_num (argv
[*arg_ptr
], &num
, &c_type
))
1110 our_pred
= insert_primary (pred_size
);
1111 our_pred
->args
.size
.kind
= c_type
;
1112 our_pred
->args
.size
.blocksize
= blksize
;
1113 our_pred
->args
.size
.size
= num
;
1119 parse_true (char **argv
, int *arg_ptr
)
1121 struct predicate
*our_pred
;
1123 our_pred
= insert_primary (pred_true
);
1124 our_pred
->need_stat
= false;
1129 parse_type (char **argv
, int *arg_ptr
)
1131 return insert_type (argv
, arg_ptr
, pred_type
);
1135 parse_uid (char **argv
, int *arg_ptr
)
1137 return (insert_num (argv
, arg_ptr
, pred_uid
));
1141 parse_used (char **argv
, int *arg_ptr
)
1143 struct predicate
*our_pred
;
1145 enum comparison_type c_type
;
1148 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1150 if (!get_num (argv
[*arg_ptr
], &num_days
, &c_type
))
1152 t
= num_days
* DAYSECS
;
1153 our_pred
= insert_primary (pred_used
);
1154 our_pred
->args
.info
.kind
= c_type
;
1155 our_pred
->args
.info
.negative
= t
< 0;
1156 our_pred
->args
.info
.l_val
= t
;
1162 parse_user (char **argv
, int *arg_ptr
)
1164 struct passwd
*cur_pwd
;
1165 struct predicate
*our_pred
;
1169 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1171 cur_pwd
= getpwnam (argv
[*arg_ptr
]);
1173 if (cur_pwd
!= NULL
)
1174 uid
= cur_pwd
->pw_uid
;
1177 uid_len
= strspn (argv
[*arg_ptr
], "0123456789");
1178 if ((uid_len
== 0) || (argv
[*arg_ptr
][uid_len
] != '\0'))
1180 uid
= atoi (argv
[*arg_ptr
]);
1182 our_pred
= insert_primary (pred_user
);
1183 our_pred
->args
.uid
= uid
;
1189 parse_version (char **argv
, int *arg_ptr
)
1191 extern char *version_string
;
1194 printf (_("GNU find version %s\n"), version_string
);
1199 parse_xdev (char **argv
, int *arg_ptr
)
1201 stay_on_filesystem
= true;
1206 parse_xtype (char **argv
, int *arg_ptr
)
1208 return insert_type (argv
, arg_ptr
, pred_xtype
);
1212 insert_type (char **argv
, int *arg_ptr
, boolean (*which_pred
) (/* ??? */))
1215 struct predicate
*our_pred
;
1217 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
)
1218 || (strlen (argv
[*arg_ptr
]) != 1))
1220 switch (argv
[*arg_ptr
][0])
1222 case 'b': /* block special */
1223 type_cell
= S_IFBLK
;
1225 case 'c': /* character special */
1226 type_cell
= S_IFCHR
;
1228 case 'd': /* directory */
1229 type_cell
= S_IFDIR
;
1231 case 'f': /* regular file */
1232 type_cell
= S_IFREG
;
1235 case 'l': /* symbolic link */
1236 type_cell
= S_IFLNK
;
1240 case 'p': /* pipe */
1241 type_cell
= S_IFIFO
;
1245 case 's': /* socket */
1246 type_cell
= S_IFSOCK
;
1250 case 'D': /* Solaris door */
1251 type_cell
= S_IFDOOR
;
1254 default: /* None of the above ... nuke 'em. */
1257 our_pred
= insert_primary (which_pred
);
1258 our_pred
->args
.type
= type_cell
;
1259 (*arg_ptr
)++; /* Move on to next argument. */
1263 /* If true, we've determined that the current fprintf predicate
1264 uses stat information. */
1265 static boolean fprintf_stat_needed
;
1268 insert_fprintf (FILE *fp
, boolean (*func
) (/* ??? */), char **argv
, int *arg_ptr
)
1270 char *format
; /* Beginning of unprocessed format string. */
1271 register char *scan
; /* Current address in scanning `format'. */
1272 register char *scan2
; /* Address inside of element being scanned. */
1273 struct segment
**segmentp
; /* Address of current segment. */
1274 struct predicate
*our_pred
;
1276 format
= argv
[(*arg_ptr
)++];
1278 fprintf_stat_needed
= false; /* Might be overridden later. */
1279 our_pred
= insert_primary (func
);
1280 our_pred
->side_effects
= true;
1281 our_pred
->no_default_print
= true;
1282 our_pred
->args
.printf_vec
.stream
= fp
;
1283 segmentp
= &our_pred
->args
.printf_vec
.segment
;
1286 for (scan
= format
; *scan
; scan
++)
1291 if (*scan2
>= '0' && *scan2
<= '7')
1295 for (i
= n
= 0; i
< 3 && (*scan2
>= '0' && *scan2
<= '7');
1297 n
= 8 * n
+ *scan2
- '0';
1312 make_segment (segmentp
, format
, scan
- format
, KIND_STOP
);
1313 our_pred
->need_stat
= fprintf_stat_needed
;
1331 /* *scan = '\\'; * it already is */
1335 _("warning: unrecognized escape `\\%c'"), *scan2
);
1340 segmentp
= make_segment (segmentp
, format
, scan
- format
+ 1,
1342 format
= scan2
+ 1; /* Move past the escape. */
1343 scan
= scan2
; /* Incremented immediately by `for'. */
1345 else if (*scan
== '%')
1349 segmentp
= make_segment (segmentp
, format
, scan
- format
+ 1,
1355 /* Scan past flags, width and precision, to verify kind. */
1356 for (scan2
= scan
; *++scan2
&& strchr ("-+ #", *scan2
);)
1358 while (ISDIGIT (*scan2
))
1361 for (scan2
++; ISDIGIT (*scan2
); scan2
++)
1363 if (strchr ("abcdfFgGhHiklmnpPstuU", *scan2
))
1365 segmentp
= make_segment (segmentp
, format
, scan2
- format
,
1370 else if (strchr ("ACT", *scan2
) && scan2
[1])
1372 segmentp
= make_segment (segmentp
, format
, scan2
- format
,
1373 *scan2
| (scan2
[1] << 8));
1380 /* An unrecognized % escape. Print the char after the %. */
1381 error (0, 0, _("warning: unrecognized format directive `%%%c'"),
1383 segmentp
= make_segment (segmentp
, format
, scan
- format
,
1392 make_segment (segmentp
, format
, scan
- format
, KIND_PLAIN
);
1393 our_pred
->need_stat
= fprintf_stat_needed
;
1397 /* Create a new fprintf segment in *SEGMENT, with type KIND,
1398 from the text in FORMAT, which has length LEN.
1399 Return the address of the `next' pointer of the new segment. */
1401 static struct segment
**
1402 make_segment (struct segment
**segment
, char *format
, int len
, int kind
)
1406 *segment
= (struct segment
*) xmalloc (sizeof (struct segment
));
1408 (*segment
)->kind
= kind
;
1409 (*segment
)->next
= NULL
;
1410 (*segment
)->text_len
= len
;
1412 fmt
= (*segment
)->text
= xmalloc (len
+ sizeof "d");
1413 strncpy (fmt
, format
, len
);
1416 switch (kind
& 0xff)
1418 case KIND_PLAIN
: /* Plain text string, no % conversion. */
1419 case KIND_STOP
: /* Terminate argument, no newline. */
1422 case 'a': /* atime in `ctime' format */
1423 case 'A': /* atime in user-specified strftime format */
1424 case 'b': /* size in 512-byte blocks */
1425 case 'c': /* ctime in `ctime' format */
1426 case 'C': /* ctime in user-specified strftime format */
1427 case 'F': /* filesystem type */
1428 case 'G': /* GID number */
1429 case 'g': /* group name */
1430 case 'i': /* inode number */
1431 case 'k': /* size in 1K blocks */
1432 case 'l': /* object of symlink */
1433 case 'n': /* number of links */
1434 case 's': /* size in bytes */
1435 case 't': /* mtime in `ctime' format */
1436 case 'T': /* mtime in user-specified strftime format */
1437 case 'U': /* UID number */
1438 case 'u': /* user name */
1439 fprintf_stat_needed
= true;
1441 case 'f': /* basename of path */
1442 case 'h': /* leading directories part of path */
1443 case 'H': /* ARGV element file was found under */
1444 case 'p': /* pathname */
1445 case 'P': /* pathname with ARGV element stripped */
1449 case 'd': /* depth in search tree (0 = ARGV element) */
1453 case 'm': /* mode as octal number (perms only) */
1455 fprintf_stat_needed
= true;
1460 return (&(*segment
)->next
);
1463 /* handles both exec and ok predicate */
1465 insert_exec_ok (boolean (*func
) (/* ??? */), char **argv
, int *arg_ptr
)
1467 int start
, end
; /* Indexes in ARGV of start & end of cmd. */
1468 int num_paths
; /* Number of args with path replacements. */
1469 int path_pos
; /* Index in array of path replacements. */
1470 int vec_pos
; /* Index in array of args. */
1471 struct predicate
*our_pred
;
1472 struct exec_val
*execp
; /* Pointer for efficiency. */
1474 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1477 /* Count the number of args with path replacements, up until the ';'. */
1479 for (end
= start
, num_paths
= 0;
1481 && ((argv
[end
][0] != ';') || (argv
[end
][1] != '\0'));
1483 if (strstr (argv
[end
], "{}"))
1485 /* Fail if no command given or no semicolon found. */
1486 if ((end
== start
) || (argv
[end
] == NULL
))
1492 our_pred
= insert_primary (func
);
1493 our_pred
->side_effects
= true;
1494 our_pred
->no_default_print
= true;
1495 execp
= &our_pred
->args
.exec_vec
;
1497 (struct path_arg
*) xmalloc (sizeof (struct path_arg
) * (num_paths
+ 1));
1498 execp
->vec
= (char **) xmalloc (sizeof (char *) * (end
- start
+ 1));
1499 /* Record the positions of all args, and the args with path replacements. */
1500 for (end
= start
, path_pos
= vec_pos
= 0;
1502 && ((argv
[end
][0] != ';') || (argv
[end
][1] != '\0'));
1507 execp
->paths
[path_pos
].count
= 0;
1508 for (p
= argv
[end
]; *p
; ++p
)
1509 if (p
[0] == '{' && p
[1] == '}')
1511 execp
->paths
[path_pos
].count
++;
1514 if (execp
->paths
[path_pos
].count
)
1516 execp
->paths
[path_pos
].offset
= vec_pos
;
1517 execp
->paths
[path_pos
].origarg
= argv
[end
];
1520 execp
->vec
[vec_pos
++] = argv
[end
];
1522 execp
->paths
[path_pos
].offset
= -1;
1523 execp
->vec
[vec_pos
] = NULL
;
1525 if (argv
[end
] == NULL
)
1532 /* Get a number of days and comparison type.
1533 STR is the ASCII representation.
1534 Set *NUM_DAYS to the number of days, taken as being from
1535 the current moment (or possibly midnight). Thus the sense of the
1536 comparison type appears to be reversed.
1537 Set *COMP_TYPE to the kind of comparison that is requested.
1539 Return true if all okay, false if input error.
1541 Used by -atime, -ctime and -mtime (parsers) to
1542 get the appropriate information for a time predicate processor. */
1545 get_num_days (char *str
, uintmax_t *num_days
, enum comparison_type
*comp_type
)
1547 boolean r
= get_num (str
, num_days
, comp_type
);
1551 case COMP_LT
: *comp_type
= COMP_GT
; break;
1552 case COMP_GT
: *comp_type
= COMP_LT
; break;
1558 /* Insert a time predicate PRED.
1559 ARGV is a pointer to the argument array.
1560 ARG_PTR is a pointer to an index into the array, incremented if
1563 Return true if input is valid, false if not.
1565 A new predicate node is assigned, along with an argument node
1566 obtained with malloc.
1568 Used by -atime, -ctime, and -mtime parsers. */
1571 insert_time (char **argv
, int *arg_ptr
, PFB pred
)
1573 struct predicate
*our_pred
;
1575 enum comparison_type c_type
;
1578 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1580 if (!get_num_days (argv
[*arg_ptr
], &num_days
, &c_type
))
1582 t
= (cur_day_start
- num_days
* DAYSECS
1583 + ((c_type
== COMP_GT
) ? DAYSECS
- 1 : 0));
1584 our_pred
= insert_primary (pred
);
1585 our_pred
->args
.info
.kind
= c_type
;
1586 our_pred
->args
.info
.negative
= t
< 0;
1587 our_pred
->args
.info
.l_val
= t
;
1590 printf (_("inserting %s\n"), our_pred
->p_name
);
1591 printf (_(" type: %s %s "),
1592 (c_type
== COMP_GT
) ? "gt" :
1593 ((c_type
== COMP_LT
) ? "lt" : ((c_type
== COMP_EQ
) ? "eq" : "?")),
1594 (c_type
== COMP_GT
) ? " >" :
1595 ((c_type
== COMP_LT
) ? " <" : ((c_type
== COMP_EQ
) ? ">=" : " ?")));
1596 t
= our_pred
->args
.info
.l_val
;
1597 printf ("%ju %s", (uintmax_t) our_pred
->args
.info
.l_val
, ctime (&t
));
1598 if (c_type
== COMP_EQ
)
1600 t
= our_pred
->args
.info
.l_val
+= DAYSECS
;
1601 printf (" < %ju %s",
1602 (uintmax_t) our_pred
->args
.info
.l_val
, ctime (&t
));
1603 our_pred
->args
.info
.l_val
-= DAYSECS
;
1609 /* Get a number with comparision information.
1610 The sense of the comparision information is 'normal'; that is,
1611 '+' looks for a count > than the number and '-' less than.
1613 STR is the ASCII representation of the number.
1614 Set *NUM to the number.
1615 Set *COMP_TYPE to the kind of comparison that is requested.
1617 Return true if all okay, false if input error. */
1620 get_num (char *str
, uintmax_t *num
, enum comparison_type
*comp_type
)
1622 int len_num
; /* Length of field. */
1629 *comp_type
= COMP_GT
;
1633 *comp_type
= COMP_LT
;
1637 *comp_type
= COMP_EQ
;
1641 return xstrtoumax (str
, NULL
, 10, num
, "") == LONGINT_OK
;
1644 /* Insert a number predicate.
1645 ARGV is a pointer to the argument array.
1646 *ARG_PTR is an index into ARGV, incremented if all went well.
1647 *PRED is the predicate processor to insert.
1649 Return true if input is valid, false if error.
1651 A new predicate node is assigned, along with an argument node
1652 obtained with malloc.
1654 Used by -inum and -links parsers. */
1657 insert_num (char **argv
, int *arg_ptr
, PFB pred
)
1659 struct predicate
*our_pred
;
1661 enum comparison_type c_type
;
1663 if ((argv
== NULL
) || (argv
[*arg_ptr
] == NULL
))
1665 if (!get_num (argv
[*arg_ptr
], &num
, &c_type
))
1667 our_pred
= insert_primary (pred
);
1668 our_pred
->args
.info
.kind
= c_type
;
1669 our_pred
->args
.info
.l_val
= num
;
1672 printf (_("inserting %s\n"), our_pred
->p_name
);
1673 printf (_(" type: %s %s "),
1674 (c_type
== COMP_GT
) ? "gt" :
1675 ((c_type
== COMP_LT
) ? "lt" : ((c_type
== COMP_EQ
) ? "eq" : "?")),
1676 (c_type
== COMP_GT
) ? " >" :
1677 ((c_type
== COMP_LT
) ? " <" : ((c_type
== COMP_EQ
) ? " =" : " ?")));
1678 printf ("%ju\n", our_pred
->args
.info
.l_val
);
1684 open_output_file (char *path
)
1688 if (!strcmp (path
, "/dev/stderr"))
1690 else if (!strcmp (path
, "/dev/stdout"))
1692 f
= fopen (path
, "w");
1694 error (1, errno
, "%s", path
);