home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
f
/
find12as.zip
/
PARSER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-02-22
|
26KB
|
1,064 lines
/* The Parsers and associated routines for Find.
Copyright (C) 1987, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* MS-DOS port (c) 1990 by Thorsten Ohl, ohl@gnu.ai.mit.edu
This port is also distributed under the terms of the
GNU General Public License as published by the
Free Software Foundation.
Please note that this file is not identical to the
original GNU release, you should have received this
code as patch to the official release.
$Header: e:/gnu/find/RCS/parser.c 1.2.0.3 90/09/23 16:09:45 tho Exp $
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#ifndef MSDOS
#include <grp.h>
#endif /* not MSDOS */
#include <time.h>
#ifndef USG
#include <strings.h>
#else
#include <string.h>
#define index strchr
#define rindex strrchr
#endif
#include "modechange.h"
#include "defs.h"
#ifndef S_IFLNK
#define lstat stat
#endif
#ifdef MSDOS
static boolean parse_atime (PARSE_ARGS);
static boolean parse_ctime (PARSE_ARGS);
static boolean parse_depth (PARSE_ARGS);
static boolean parse_exec (PARSE_ARGS);
static boolean parse_fulldays (PARSE_ARGS);
static boolean parse_fstype (PARSE_ARGS);
static boolean parse_group (PARSE_ARGS);
static boolean parse_inum (PARSE_ARGS);
static boolean parse_links (PARSE_ARGS);
static boolean parse_ls (PARSE_ARGS);
static boolean parse_mtime (PARSE_ARGS);
static boolean parse_name (PARSE_ARGS);
static boolean parse_negate (PARSE_ARGS);
static boolean parse_newer (PARSE_ARGS);
static boolean parse_nogroup (PARSE_ARGS);
static boolean parse_nouser (PARSE_ARGS);
static boolean parse_ok (PARSE_ARGS);
static boolean parse_or (PARSE_ARGS);
static boolean parse_perm (PARSE_ARGS);
static boolean parse_permmask (PARSE_ARGS);
static boolean parse_prune (PARSE_ARGS);
static boolean parse_regex (PARSE_ARGS);
static boolean parse_size (PARSE_ARGS);
static boolean parse_type (PARSE_ARGS);
static boolean parse_user (PARSE_ARGS);
static boolean parse_version (PARSE_ARGS);
static boolean parse_xdev (PARSE_ARGS);
#else /* not MSDOS */
/* no parse_and */
boolean parse_atime ();
boolean parse_close ();
boolean parse_ctime ();
boolean parse_depth ();
boolean parse_exec ();
boolean parse_fstype ();
boolean parse_fulldays ();
boolean parse_group ();
boolean parse_inum ();
boolean parse_links ();
boolean parse_ls ();
boolean parse_mtime ();
boolean parse_name ();
boolean parse_negate ();
boolean parse_newer ();
boolean parse_nogroup ();
boolean parse_nouser ();
boolean parse_ok ();
boolean parse_open ();
boolean parse_or ();
boolean parse_perm ();
boolean parse_permmask ();
boolean parse_print ();
boolean parse_prune ();
boolean parse_regex ();
boolean parse_size ();
boolean parse_type ();
boolean parse_user ();
boolean parse_version ();
boolean parse_xdev ();
boolean pred_and ();
boolean pred_atime ();
boolean pred_close ();
boolean pred_ctime ();
/* no pred_depth */
boolean pred_exec ();
boolean pred_fstype ();
/* no pred_fulldays */
boolean pred_group ();
boolean pred_inum ();
boolean pred_links ();
boolean pred_ls ();
boolean pred_mtime ();
boolean pred_name ();
boolean pred_negate ();
boolean pred_newer ();
boolean pred_nogroup ();
boolean pred_nouser ();
boolean pred_ok ();
boolean pred_open ();
boolean pred_or ();
boolean pred_perm ();
boolean pred_permmask ();
boolean pred_print ();
boolean pred_prune ();
boolean pred_regex ();
boolean pred_size ();
boolean pred_type ();
boolean pred_user ();
/* no pred_version */
/* no pred_xdev */
#endif /* not MSDOS */
long atol ();
struct group *getgrnam ();
struct passwd *getpwnam ();
struct tm *localtime ();
void endgrent ();
void endpwent ();
boolean get_num ();
boolean insert_exec_ok ();
boolean insert_num ();
boolean insert_time ();
char *find_pred_name ();
void read_mtab ();
#ifdef DEBUG
char *find_pred_name ();
#endif /* DEBUG */
struct parser_table_t
{
char *parser_name;
#ifdef MSDOS
PARSE_FCT parser_func;
#else
PFB parser_func;
#endif
};
struct parser_table_t parse_table[] =
{
{"!", parse_negate},
{"(", parse_open},
{")", parse_close},
#ifdef UNIMPLEMENTED_UNIX
{"a", parse_and}, /* do-nothing */
#endif
{"atime", parse_atime},
#ifdef UNIMPLEMENTED_UNIX
{"cpio", parse_cpio},
#endif
{"ctime", parse_ctime},
{"depth", parse_depth},
{"exec", parse_exec},
{"fulldays", parse_fulldays}, /* nonstandard */
{"fstype", parse_fstype},
{"group", parse_group},
{"inum", parse_inum}, /* nonstandard, Unix */
{"links", parse_links},
{"ls", parse_ls}, /* nonstandard, Unix */
{"mtime", parse_mtime},
{"name", parse_name},
#ifdef UNIMPLEMENTED_UNIX
{"ncpio", parse_ncpio},
#endif
{"newer", parse_newer},
{"nogroup", parse_nogroup},
{"nouser", parse_nouser},
{"o", parse_or},
{"or", parse_or}, /* nonstandard */
{"ok", parse_ok},
{"perm", parse_perm},
{"permmask", parse_permmask}, /* nonstandard */
{"print", parse_print},
{"prune", parse_prune},
{"regex", parse_regex}, /* nonstandard */
{"size", parse_size},
{"type", parse_type},
{"user", parse_user},
{"version", parse_version},
{"xdev", parse_xdev},
{0, 0}
};
/* Return a pointer to the parser function to invoke for predicate
SEARCH_NAME.
Return NULL if SEARCH_NAME is not a valid predicate name. */
#ifdef MSDOS
PARSE_FCT
#else
PFB
#endif
find_parser (search_name)
char *search_name;
{
int i;
if (*search_name == '-')
search_name++;
for (i = 0; parse_table[i].parser_name != 0; i++)
if (strcmp (parse_table[i].parser_name, search_name) == 0)
return (parse_table[i].parser_func);
return (NULL);
}
/* The parsers are responsible to continue scanning ARGV for
their arguments. Each parser knows what is and isn't
allowed for itself.
ARGV is the argument array.
*ARG_PTR is the index to start at in ARGV,
updated to point beyond the last element consumed.
The predicate structure is updated with the new information. */
boolean
parse_atime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_atime));
}
boolean
parse_close (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred ();
our_pred->pred_func = pred_close;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_close);
#endif /* DEBUG */
our_pred->p_type = CLOSE_PAREN;
our_pred->p_prec = NO_PREC;
return (true);
}
boolean
parse_ctime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_ctime));
}
boolean
parse_depth (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
do_dir_first = false;
return (true);
}
boolean
parse_exec (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_exec_ok (pred_exec, argv, arg_ptr));
}
boolean
parse_fulldays (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct tm *local;
if (full_days == false)
{
cur_day_start += DAYSECS;
local = localtime (&cur_day_start);
cur_day_start -= local->tm_sec + local->tm_min * 60
+ local->tm_hour * 3600;
full_days = true;
}
return (true);
}
boolean
parse_fstype (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_fstype);
our_pred->args.str = argv[*arg_ptr];
(*arg_ptr)++;
read_mtab ();
return (true);
}
boolean
parse_group (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct group *cur_gr;
struct pred_struct *our_pred;
int gid, gid_len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
cur_gr = getgrnam (argv[*arg_ptr]);
endgrent ();
if (cur_gr != NULL)
gid = cur_gr->gr_gid;
else
{
gid_len = strspn (argv[*arg_ptr], "0123456789");
if ((gid_len == 0) || (argv[*arg_ptr][gid_len] != '\0'))
return (false);
gid = atoi (argv[*arg_ptr]);
}
our_pred = insert_victim (pred_group);
our_pred->args.gid = (short) gid;
(*arg_ptr)++;
return (true);
}
boolean
parse_inum (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_num (argv, arg_ptr, pred_inum));
}
boolean
parse_links (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_num (argv, arg_ptr, pred_links));
}
boolean
parse_ls (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_ls);
our_pred->side_effects = true;
return (true);
}
boolean
parse_mtime (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
return (insert_time (argv, arg_ptr, pred_mtime));
}
boolean
parse_name (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_name);
our_pred->args.str = argv[*arg_ptr];
(*arg_ptr)++;
return (true);
}
boolean
parse_negate (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred_chk_op ();
our_pred->pred_func = pred_negate;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_negate);
#endif /* DEBUG */
our_pred->p_type = UNI_OP;
our_pred->p_prec = NEGATE_PREC;
return (true);
}
boolean
parse_newer (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
struct stat stat_newer;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (lstat (argv[*arg_ptr], &stat_newer))
error (1, errno, "%s", argv[*arg_ptr]);
our_pred = insert_victim (pred_newer);
our_pred->args.time = stat_newer.st_mtime;
(*arg_ptr)++;
return (true);
}
boolean
parse_nogroup (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_nogroup);
return (true);
}
boolean
parse_nouser (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_nouser);
return (true);
}
boolean
parse_ok (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
boolean insert_exec_ok ();
return (insert_exec_ok (pred_ok, argv, arg_ptr));
}
boolean
parse_open (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred_chk_op ();
our_pred->pred_func = pred_open;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_open);
#endif /* DEBUG */
our_pred->p_type = OPEN_PAREN;
our_pred->p_prec = NO_PREC;
return (true);
}
boolean
parse_or (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = get_new_pred ();
our_pred->pred_func = pred_or;
#ifdef DEBUG
our_pred->p_name = find_pred_name (pred_or);
#endif /* DEBUG */
our_pred->p_type = BI_OP;
our_pred->p_prec = OR_PREC;
return (true);
}
boolean
parse_perm (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long perm_val;
int mode_start = 0;
struct mode_change *change;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (argv[*arg_ptr][0] == '-')
mode_start = 1;
change = mode_compile (argv[*arg_ptr] + mode_start, MODE_MASK_PLUS);
if (change == MODE_INVALID)
error (1, 0, "invalid mode `%s'", argv[*arg_ptr]);
else if (change == MODE_MEMORY_EXHAUSTED)
error (1, 0, "virtual memory exhausted");
perm_val = mode_adjust (0, change);
mode_free (change);
our_pred = insert_victim (pred_perm);
if (mode_start)
/* Set magic flag to compare suid, sgid, sticky bits as well;
also, true if at least the given bits are set. */
our_pred->args.perm = (perm_val & 07777) | 010000;
else
our_pred->args.perm = perm_val & 0777;
(*arg_ptr)++;
return (true);
}
boolean
parse_permmask (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long mask_val;
struct mode_change *change;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
change = mode_compile (argv[*arg_ptr], MODE_MASK_PLUS);
if (change == MODE_INVALID)
error (1, 0, "invalid mode mask `%s'", argv[*arg_ptr]);
else if (change == MODE_MEMORY_EXHAUSTED)
error (1, 0, "virtual memory exhausted");
mask_val = mode_adjust (0, change);
mode_free (change);
our_pred = insert_victim (pred_permmask);
our_pred->args.perm = mask_val;
(*arg_ptr)++;
return (true);
}
boolean
parse_print (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_print);
/* -print has the side effect of printing. This prevents us
from doing undesired multiple printing when the user has
already specified -print. */
our_pred->side_effects = true;
return (true);
}
boolean
parse_prune (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
our_pred = insert_victim (pred_prune);
return (true);
}
boolean
parse_regex (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
struct re_pattern_buffer *re;
char *error_message;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
our_pred = insert_victim (pred_regex);
re = (struct re_pattern_buffer *)
xmalloc (sizeof (struct re_pattern_buffer));
our_pred->args.regex = re;
re->allocated = 100;
#ifdef MSDOS
re->buffer = xmalloc ((size_t) re->allocated);
#else /* not MSDOS */
re->buffer = xmalloc (re->allocated);
#endif /* not MSDOS */
re->fastmap = NULL;
re->translate = NULL;
error_message = re_compile_pattern (argv[*arg_ptr], strlen (argv[*arg_ptr]),
re);
if (error_message)
error (1, 0, "%s", error_message);
(*arg_ptr)++;
return (true);
}
boolean
parse_size (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct pred_struct *our_pred;
unsigned long num;
short c_type;
boolean blk;
int len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
len = strlen (argv[*arg_ptr]);
if (len == 0)
error (1, 0, "invalid null argument to -size");
switch (argv[*arg_ptr][len - 1])
{
case 'c':
blk = false;
argv[*arg_ptr][len - 1] = '\0';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
blk = true;
break;
default:
error (1, 0, "invalid -size type `%c'", argv[*arg_ptr][len - 1]);
}
if (!get_num (argv[*arg_ptr], &num, &c_type))
return (false);
our_pred = insert_victim (pred_size);
our_pred->args.size.kind = c_type;
our_pred->args.size.block = blk;
our_pred->args.size.size = num;
(*arg_ptr)++;
return (true);
}
boolean
parse_type (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
unsigned long type_cell;
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL)
|| (strlen (argv[*arg_ptr]) != 1))
return (false);
switch (argv[*arg_ptr][0])
{
#ifdef S_IFBLK
case 'b': /* block special */
type_cell = S_IFBLK;
break;
#endif
case 'c': /* character special */
type_cell = S_IFCHR;
break;
case 'd': /* directory */
type_cell = S_IFDIR;
break;
case 'f': /* regular file */
type_cell = S_IFREG;
break;
#ifdef S_IFLNK
case 'l': /* symbolic link */
type_cell = S_IFLNK;
break;
#endif
#ifdef S_IFIFO
case 'p': /* pipe */
type_cell = S_IFIFO;
break;
#endif
#ifdef S_IFSOCK
case 's': /* socket */
type_cell = S_IFSOCK;
break;
#endif
default: /* none of the above ... nuke em */
return (false);
}
our_pred = insert_victim (pred_type);
our_pred->args.type = type_cell;
(*arg_ptr)++; /* move on to next argument */
return (true);
}
boolean
parse_user (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
struct passwd *cur_pwd;
struct pred_struct *our_pred;
int uid, uid_len;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
cur_pwd = getpwnam (argv[*arg_ptr]);
endpwent ();
if (cur_pwd != NULL)
uid = cur_pwd->pw_uid;
else
{
uid_len = strspn (argv[*arg_ptr], "0123456789");
if ((uid_len == 0) || (argv[*arg_ptr][uid_len] != '\0'))
return (false);
uid = atoi (argv[*arg_ptr]);
}
our_pred = insert_victim (pred_user);
our_pred->args.uid = (short) uid;
(*arg_ptr)++;
return (true);
}
boolean
parse_version (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
extern char *version_string;
fprintf (stderr, "%s", version_string);
return true;
}
boolean
parse_xdev (argv, arg_ptr)
char *argv[];
int *arg_ptr;
{
stay_on_filesystem = true;
return true;
}
boolean
insert_exec_ok (func, argv, arg_ptr)
boolean (*func) ();
char *argv[];
int *arg_ptr;
{
int start, end; /* Indexes in ARGV of start & end of cmd. */
int num_paths; /* Number of "{}" insertions to do. */
int path_pos; /* Index in array of "{}" insertions. */
int vec_pos; /* Index in array of arg words. */
struct pred_struct *our_pred;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
start = *arg_ptr;
for (end = start, num_paths = 0;
(argv[end] != NULL)
&& ((argv[end][0] != ';') || (argv[end][1] != '\0'));
end++)
if (strcmp (argv[end], "{}") == 0)
num_paths++;
/* Fail if no command given or no semicolon found. */
if ((end == start) || (argv[end] == NULL))
{
*arg_ptr = end;
return (false);
}
our_pred = insert_victim (func);
our_pred->side_effects = true;
our_pred->args.exec_vec.path_loc =
(short *) xmalloc (sizeof (short) * (num_paths + 1));
our_pred->args.exec_vec.vec =
(char **) xmalloc (sizeof (char *) * (end - start + 1));
for (end = start, path_pos = vec_pos = 0;
(argv[end] != NULL)
&& ((argv[end][0] != ';') || (argv[end][1] != '\0'));
end++)
{
if (strcmp (argv[end], "{}") == 0)
our_pred->args.exec_vec.path_loc[path_pos++] = vec_pos;
our_pred->args.exec_vec.vec[vec_pos++] = argv[end];
}
our_pred->args.exec_vec.path_loc[path_pos] = -1;
our_pred->args.exec_vec.vec[vec_pos] = NULL;
if (argv[end] == NULL)
*arg_ptr = end;
else
*arg_ptr = end + 1;
return (true);
}
/* Get a number of days and comparison type.
STR is the ASCII representation.
Set *NUM_DAYS to the number of days, taken as being from
the current moment (or possibly midnight). Thus the sense of the
comparison type appears to be reversed.
Set *COMP_TYPE to the kind of comparison that is requested.
Return true if all okay, false if input error.
Used by -atime, -ctime and -mtime (parsers) to
get the appropriate information for a time predicate processor. */
boolean
get_num_days (str, num_days, comp_type)
char *str;
unsigned long *num_days;
enum comparison_type *comp_type;
{
int len_days; /* length of field */
if (str == NULL)
return (false);
switch (str[0])
{
case '+':
*comp_type = COMP_LT;
str++;
break;
case '-':
*comp_type = COMP_GT;
str++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*comp_type = COMP_EQ;
break;
default:
return (false);
}
/* We know the first char has been reasonable. Find the
number of days to play with. */
len_days = strspn (str, "0123456789");
if ((len_days == 0) || (str[len_days] != '\0'))
return (false);
*num_days = (unsigned long) atol (str);
return (true);
}
/* Insert a time predicate PRED.
ARGV is a pointer to the argument array.
ARG_PTR is a pointer to an index into the array, incremented if
all went well.
Return true if input is valid, false if not.
A new predicate node is assigned, along with an argument node
obtained with malloc.
Used by -atime, -ctime, and -mtime parsers. */
boolean
insert_time (argv, arg_ptr, pred)
char *argv[];
int *arg_ptr;
#ifdef MSDOS
PRED_FCT pred;
#else
PFB pred;
#endif
{
struct pred_struct *our_pred;
unsigned long num_days;
enum comparison_type c_type;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (!get_num_days (argv[*arg_ptr], &num_days, &c_type))
return (false);
our_pred = insert_victim (pred);
our_pred->args.info.kind = c_type;
our_pred->args.info.l_val = cur_day_start - num_days * DAYSECS
+ ((c_type == COMP_GT) ? DAYSECS - 1 : 0);
(*arg_ptr)++;
#ifdef DEBUG
printf ("inserting %s\n", our_pred->p_name);
printf (" type: %s %s ",
(c_type == COMP_GT) ? "gt" :
((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
(c_type == COMP_GT) ? " >" :
((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? ">=" : " ?")));
printf ("%ld %s", our_pred->args.info.l_val,
ctime (&our_pred->args.info.l_val));
if (c_type == COMP_EQ)
{
our_pred->args.info.l_val += DAYSECS;
printf (" < %ld %s", our_pred->args.info.l_val,
ctime (&our_pred->args.info.l_val));
our_pred->args.info.l_val -= DAYSECS;
}
#endif /* DEBUG */
return (true);
}
/* Get a number with comparision information.
The sense of the comparision information is 'normal'; that is,
'+' looks for inums or links > than the number and '-' less than.
STR is the ASCII representation of the number.
Set *NUM to the number.
Set *COMP_TYPE to the kind of comparison that is requested.
Return true if all okay, false if input error.
Used by the -inum and -links predicate parsers. */
boolean
get_num (str, num, comp_type)
char *str;
unsigned long *num;
short *comp_type;
{
int len_num; /* length of field */
if (str == NULL)
return (false);
switch (str[0])
{
case '+':
*comp_type = COMP_GT;
str++;
break;
case '-':
*comp_type = COMP_LT;
str++;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
*comp_type = COMP_EQ;
break;
default:
return (false);
}
/* We know the first char has been reasonable. Find the number of
days to play with. */
len_num = strspn (str, "0123456789");
if ((len_num == 0) || (str[len_num] != '\0'))
return (false);
*num = (unsigned long) atol (str);
return (true);
}
/* Insert a number predicate.
ARGV is a pointer to the argument array.
*ARG_PTR is an index into ARGV, incremented if all went well.
*PRED is the predicate processor to insert.
Return true if input is valid, false if error.
A new predicate node is assigned, along with an argument node
obtained with malloc.
Used by -inum and -links parsers. */
boolean
insert_num (argv, arg_ptr, pred)
char *argv[];
int *arg_ptr;
#ifdef MSDOS
PRED_FCT pred;
#else
PFB pred;
#endif
{
struct pred_struct *our_pred;
unsigned long num;
short c_type;
if ((argv == NULL) || (argv[*arg_ptr] == NULL))
return (false);
if (!get_num (argv[*arg_ptr], &num, &c_type))
return (false);
our_pred = insert_victim (pred);
our_pred->args.info.kind = c_type;
our_pred->args.info.l_val = num;
(*arg_ptr)++;
#ifdef DEBUG
printf ("inserting %s\n", our_pred->p_name);
printf (" type: %s %s ",
(c_type == COMP_GT) ? "gt" :
((c_type == COMP_LT) ? "lt" : ((c_type == COMP_EQ) ? "eq" : "?")),
(c_type == COMP_GT) ? " >" :
((c_type == COMP_LT) ? " <" : ((c_type == COMP_EQ) ? " =" : " ?")));
printf ("%ld\n", our_pred->args.info.l_val);
#endif /* DEBUG */
return (true);
}
#ifdef STRSPN_MISSING
int
strspn (str, class)
char *str, *class;
{
register char *cl = class;
register char *st = str;
while (index (class, *st))
++st;
return st - str;
}
#endif