home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / mush6.0 / part02 / expr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-12  |  4.0 KB  |  158 lines

  1. /* @(#)expr.c    2.3    (c) copyright 10/15/86 (Dan Heller) */
  2.  
  3. #include "mush.h"
  4.  
  5. char *eval_expr();
  6.  
  7. /* Parse a string (p) to interpret numbers and ranges of numbers (n-m)
  8.  * delimited by whitespace or comma's. Set msg_list bitfields using
  9.  * macros in mush.h.
  10.  * Return the address of the end of whatever we parsed (in case there's
  11.  * more that the calling routine cares to deal with).
  12.  * Finally, remember that user specifies one more than actual message number
  13.  */
  14. char *
  15. do_range(p, list1)
  16. register char *p, *list1;
  17. {
  18.     register int num1 = -1, num2 = -1, except = 0;
  19.     register char *p2;
  20.     char list2[MAXMSGS_BITS];
  21.  
  22.     if (!p)
  23.     return "";
  24.     while (*p) {
  25.     if (isdigit(*p) || *p == '$' || *p == '.' || *p == '^') {
  26.         if (isdigit(*p)) {
  27.         char c;
  28.         p2 = p;
  29.         skipdigits(0);  /* find the end of the digits */
  30.         c = *p, *p = 0; /* temporarily plug a null */
  31.         if (!(num2 = chk_msg(p2))) {
  32.             clear_msg_list(list1);
  33.             return NULL;
  34.         }
  35.         *p = c;
  36.         } else if (*p == '$')
  37.         p++, num2 = msg_cnt;
  38.         else if (*p == '.')
  39.         p++, num2 = current_msg+1;
  40.         else if (*p == '^')
  41.         p++, num2 = 1;
  42.         if (except)
  43.         unset_msg_bit(list1, num2-1);
  44.         else
  45.         set_msg_bit(list1, num2-1);
  46.         if (num1 >= 0) {
  47.         if (num1 > num2) {
  48.             print("syntax error: range sequence order reversed.\n");
  49.             clear_msg_list(list1);
  50.             return NULL;
  51.         }
  52.         while (++num1 < num2)
  53.             if (except)
  54.             unset_msg_bit(list1, num1-1);
  55.             else
  56.             set_msg_bit(list1, num1-1);
  57.         num1 = num2 = -1;
  58.         }
  59.     }
  60.     /* expressions to evaluate start with a `
  61.      * p2 points to first char passed the last char parsed.
  62.      */
  63.     if (*p == '`') {
  64.         clear_msg_list(list2);
  65.         if (!(p = eval_expr(p, list2))) {
  66.         clear_msg_list(list1);
  67.         return NULL;
  68.         } else {
  69.         if (except)
  70.             bitput(list2, list1, msg_cnt, &=~) /* MACRO */
  71.         else
  72.             bitput(list2, list1, msg_cnt, |=) /* MACRO */
  73.         }
  74.     }
  75.     /* NOT operator: `* {5}' (everything except for 5)
  76.      * `4-16 {8-10}'  (4 thru 16 except for 8,9,10)
  77.      */
  78.     if (*p == '{' || *p == '}') {
  79.         if (*p == '{' && (except || num1 >= 0))
  80.         break;
  81.         if (*p == '}' && !except) {
  82.         print("syntax error: missing {\n"); /* } */
  83.         break;
  84.         }
  85.         except = !except;
  86.     } else if (*p == '-')
  87.         if (num1 >= 0 || !index(" \t{},.*`$", *(p+1)) && !isdigit(*(p+1)))
  88.         break;
  89.         else
  90.         num1 = num2;
  91.     else if (*p == ',' || *p == '*') {
  92.         if (num1 >= 0)
  93.         break;
  94.         else if (*p == '*') {
  95.         if (except)
  96.             clear_msg_list(list1);
  97.         else
  98.             for (num1 = 0; num1 < msg_cnt; num1++)
  99.             set_msg_bit(list1, num1);
  100.         num1 = -1;
  101.         }
  102.     } else if (!index(" \t`", *p))
  103.         break;
  104.     if (*p)
  105.         skipspaces(1); /* don't make user type stuff squished together */
  106.     }
  107.     if (num1 >= 0 || except) {
  108.     if (except)
  109.   /* { */   print("syntax error: unmatched }\n");
  110.     else
  111.         print("syntax error: unfinished range\n");
  112.     clear_msg_list(list1);
  113.     return NULL;
  114.     }
  115.     return p;
  116. }
  117.  
  118. /* evaluate expressions:
  119.  * mail> delete `pick -f root`     deletes all messages from root.
  120.  * mail> save { `pick -s "Re:"` }  save all message that don't have "Re:"
  121.  *                   in the subject header.
  122.  * mail> save `pick -x -s "Re:"`   same
  123.  * args as follows:
  124.  *   p should point to the first ` -- check for it.
  125.  *   on tells whether to turn bits on or off if messages match.
  126.  */
  127. char *
  128. eval_expr(p, new_list)
  129. register char *p, new_list[];
  130. {
  131.     register char *p2, **argv;
  132.     int       argc;
  133.     u_long      save_flags = glob_flags;
  134.  
  135.     if (!(p2 = index(++p, '`'))) {
  136.     print("unmatched backquote (`)\n");
  137.     return NULL;
  138.     }
  139.     *p2 = 0;
  140.  
  141.     skipspaces(0);
  142.     if (!*p) {
  143.     print("Invalid null command\n");
  144.     return NULL;
  145.     }
  146.     turnon(glob_flags, DO_PIPE);
  147.     /* ignore sigs only because if user interrupts the do_command,
  148.      * the long jump will corrupt the stack and the program is hosed.
  149.      * fix is to have layers of jumpbuf's to return to different levels.
  150.      */
  151.     turnon(glob_flags, IGN_SIGS);
  152.     if (*p && (argv = make_command(p, TRPL_NULL, &argc)))
  153.     (void) do_command(argc, argv, new_list);
  154.     glob_flags = save_flags;
  155.     *p2 = '`';
  156.     return p2+1;
  157. }
  158.