home *** CD-ROM | disk | FTP | other *** search
- /* @(#)expr.c 2.3 (c) copyright 10/15/86 (Dan Heller) */
-
- #include "mush.h"
-
- char *eval_expr();
-
- /* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
- * delimited by whitespace or comma's. Set msg_list bitfields using
- * macros in mush.h.
- * Return the address of the end of whatever we parsed (in case there's
- * more that the calling routine cares to deal with).
- * Finally, remember that user specifies one more than actual message number
- */
- char *
- do_range(p, list1)
- register char *p, *list1;
- {
- register int num1 = -1, num2 = -1, except = 0;
- register char *p2;
- char list2[MAXMSGS_BITS];
-
- if (!p)
- return "";
- while (*p) {
- if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
- if (isdigit(*p)) {
- char c;
- p2 = p;
- skipdigits(0); /* find the end of the digits */
- c = *p, *p = 0; /* temporarily plug a null */
- if (!(num2 = chk_msg(p2))) {
- clear_msg_list(list1);
- return NULL;
- }
- *p = c;
- } else if (*p == '$')
- p++, num2 = msg_cnt;
- else if (*p == '.')
- p++, num2 = current_msg+1;
- else if (*p == '^')
- p++, num2 = 1;
- if (except)
- unset_msg_bit(list1, num2-1);
- else
- set_msg_bit(list1, num2-1);
- if (num1 >= 0) {
- if (num1 > num2) {
- print("syntax error: range sequence order reversed.\n");
- clear_msg_list(list1);
- return NULL;
- }
- while (++num1 < num2)
- if (except)
- unset_msg_bit(list1, num1-1);
- else
- set_msg_bit(list1, num1-1);
- num1 = num2 = -1;
- }
- }
- /* expressions to evaluate start with a `
- * p2 points to first char passed the last char parsed.
- */
- if (*p == '`') {
- clear_msg_list(list2);
- if (!(p = eval_expr(p, list2))) {
- clear_msg_list(list1);
- return NULL;
- } else {
- if (except)
- bitput(list2, list1, msg_cnt, &=~) /* MACRO */
- else
- bitput(list2, list1, msg_cnt, |=) /* MACRO */
- }
- }
- /* NOT operator: `* {5}' (everything except for 5)
- * `4-16 {8-10}' (4 thru 16 except for 8,9,10)
- */
- if (*p == '{' || *p == '}') {
- if (*p == '{' && (except || num1 >= 0))
- break;
- if (*p == '}' && !except) {
- print("syntax error: missing {\n"); /* } */
- break;
- }
- except = !except;
- } else if (*p == '-')
- if (num1 >= 0 || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
- break;
- else
- num1 = num2;
- else if (*p == ',' || *p == '*') {
- if (num1 >= 0)
- break;
- else if (*p == '*') {
- if (except)
- clear_msg_list(list1);
- else
- for (num1 = 0; num1 < msg_cnt; num1++)
- set_msg_bit(list1, num1);
- num1 = -1;
- }
- } else if (!index(" \t`", *p))
- break;
- if (*p)
- skipspaces(1); /* don't make user type stuff squished together */
- }
- if (num1 >= 0 || except) {
- if (except)
- /* { */ print("syntax error: unmatched }\n");
- else
- print("syntax error: unfinished range\n");
- clear_msg_list(list1);
- return NULL;
- }
- return p;
- }
-
- /* evaluate expressions:
- * mail> delete `pick -f root` deletes all messages from root.
- * mail> save { `pick -s "Re:"` } save all message that don't have "Re:"
- * in the subject header.
- * mail> save `pick -x -s "Re:"` same
- * args as follows:
- * p should point to the first ` -- check for it.
- * on tells whether to turn bits on or off if messages match.
- */
- char *
- eval_expr(p, new_list)
- register char *p, new_list[];
- {
- register char *p2, **argv;
- int argc;
- u_long save_flags = glob_flags;
-
- if (!(p2 = index(++p, '`'))) {
- print("unmatched backquote (`)\n");
- return NULL;
- }
- *p2 = 0;
-
- skipspaces(0);
- if (!*p) {
- print("Invalid null command\n");
- return NULL;
- }
- turnon(glob_flags, DO_PIPE);
- /* ignore sigs only because if user interrupts the do_command,
- * the long jump will corrupt the stack and the program is hosed.
- * fix is to have layers of jumpbuf's to return to different levels.
- */
- turnon(glob_flags, IGN_SIGS);
- if (*p && (argv = make_command(p, TRPL_NULL, &argc)))
- (void) do_command(argc, argv, new_list);
- glob_flags = save_flags;
- *p2 = '`';
- return p2+1;
- }
-