home *** CD-ROM | disk | FTP | other *** search
/ ftp.freefriends.org / ftp.freefriends.org.tar / ftp.freefriends.org / arnold / Source / mush.rstevens.tar.gz / mush.tar / macros.c < prev    next >
C/C++ Source or Header  |  1990-05-03  |  9KB  |  403 lines

  1. /* (@)# macros.c    (c) copyright 9/19/88 (Bart Schaefer, Dan Heller) */
  2.  
  3. #include "bindings.h"
  4. #include "mush.h"
  5.  
  6. extern struct cmd_map map_func_names[];
  7.  
  8. struct cmd_map    *mac_stack, *mac_hide;
  9.  
  10. /*
  11.  * print current binding to macro mappings if "str" is NULL.
  12.  * else return the string "x_str" which the str is bound to.
  13.  */
  14. char *
  15. c_macro(name, str, opts)
  16. char *name;
  17. register char *str;
  18. register struct cmd_map *opts;
  19. {
  20.     register int    incurses = iscurses;
  21.     char buf[MAX_MACRO_LEN], buf2[sizeof buf * 3];
  22.  
  23.     if (!str) {
  24.     for (; opts; opts = opts->m_next)
  25.         if (opts->m_cmd == C_MACRO)
  26.         break;
  27.     if (!opts) {
  28.         print("No %s settings.\n", name);
  29.         return (char *)(-1);
  30.     }
  31.     if (incurses)
  32.         clr_bot_line(), iscurses = FALSE;
  33.     (void) do_pager(NULL, TRUE);
  34.     (void) do_pager(sprintf(buf, "\nCurrent %s settings:\n\n",name), FALSE);
  35.     }
  36.  
  37.     if (!opts)
  38.     return NULL;
  39.  
  40.     for (; opts; opts = opts->m_next) {
  41.     if (opts->m_cmd != C_MACRO)
  42.         continue;
  43.     if (!str) {
  44.         (void) do_pager(sprintf(buf, "%-20.20s  ",
  45.         ctrl_strcpy(buf2, opts->m_str, FALSE)), FALSE);
  46.         if (do_pager(sprintf(buf, "%s\n",
  47.         ctrl_strcpy(buf2, opts->x_str, TRUE)), FALSE) == EOF)
  48.         break;
  49.     } else {
  50.         if (strcmp(str, opts->m_str))
  51.         continue;
  52.         else
  53.         return opts->x_str;
  54.     }
  55.     }
  56.     iscurses = incurses;
  57.     if (str)
  58.     (void) do_pager(NULL, FALSE);
  59.     return NULL;
  60. }
  61.  
  62. mac_push(str)
  63. register char *str;
  64. {
  65.     register struct cmd_map *tmp;
  66.  
  67.     /* now make a new macro struct and set fields */
  68.     if (!(tmp = (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
  69.     error("calloc");
  70.     return -1;
  71.     }
  72.     tmp->m_next = mac_stack;
  73.     mac_stack = tmp;
  74.     tmp->x_str = savestr(str);    /* x_str is the text of the expansion */
  75.     tmp->m_str = tmp->x_str;    /* m_str is the current read position */
  76.  
  77.     /*
  78.      * Save the current state of the glob_flags so
  79.      * mac_push() can also serve as unget of stdin
  80.      */
  81.     tmp->m_cmd = glob_flags;
  82.     return 0;
  83. }
  84.  
  85. mac_queue(str)
  86. register char *str;
  87. {
  88.     register struct cmd_map **tmp; /* NOTE pointer to pointer! */
  89.  
  90.     /* Find the bottom of the macro stack */
  91.     for (tmp = &mac_stack; *tmp; tmp = &((*tmp)->m_next))
  92.     ;
  93.     /* now make a new macro struct and set fields */
  94.     if (!(*tmp =
  95.         (struct cmd_map *)calloc((unsigned)1,sizeof(struct cmd_map)))) {
  96.     error("calloc");
  97.     return -1;
  98.     }
  99.     (*tmp)->m_next = (struct cmd_map *)0; /* calloc should do this .... */
  100.     (*tmp)->x_str = savestr(str); /* x_str is the text of the expansion */
  101.     (*tmp)->m_str = (*tmp)->x_str; /* m_str is the current read position */
  102.  
  103.     /*
  104.      * Save the current state of the glob_flags
  105.      */
  106.     (*tmp)->m_cmd = glob_flags;
  107.     return 0;
  108. }
  109.  
  110. void
  111. mac_pop()
  112. {
  113.     register struct cmd_map *tmp;
  114.  
  115.     if (mac_stack) {
  116.     tmp = mac_stack;
  117.     mac_stack = tmp->m_next;
  118.     xfree(tmp->x_str);
  119.     xfree((char *) tmp);
  120.     }
  121.     /*
  122.      * Restore saved MACRO glob_flags only (see mac_push())
  123.      */
  124.     if (mac_stack) {
  125.     if (ison(mac_stack->m_cmd, IN_MACRO))
  126.         turnon(glob_flags, IN_MACRO);
  127.     else
  128.         turnoff(glob_flags, IN_MACRO);
  129.     if (ison(mac_stack->m_cmd, LINE_MACRO))
  130.         turnon(glob_flags, LINE_MACRO);
  131.     else
  132.         turnoff(glob_flags, LINE_MACRO);
  133.     if (ison(mac_stack->m_cmd, QUOTE_MACRO))
  134.         turnon(glob_flags, QUOTE_MACRO);
  135.     else
  136.         turnoff(glob_flags, QUOTE_MACRO);
  137.     }
  138. }
  139.  
  140. /* Abandon macro processing */
  141. void
  142. mac_flush()
  143. {
  144.     while (mac_stack)
  145.     mac_pop();
  146.     if (mac_hide) {
  147.     mac_stack = mac_hide;
  148.     mac_hide = NULL_MAP;
  149.     while (mac_stack)
  150.         mac_pop();
  151.     }
  152.     turnoff(glob_flags, IN_MACRO);
  153.     turnoff(glob_flags, LINE_MACRO);
  154.     turnoff(glob_flags, QUOTE_MACRO);
  155. }
  156.  
  157. /* Check for pending input from a macro. */
  158. mac_pending()
  159. {
  160.     register struct cmd_map *msp;
  161.  
  162.     for (msp = mac_stack; msp && !*(msp->m_str); msp = msp->m_next)
  163.     ;
  164.  
  165.     return !!msp;
  166. }
  167.  
  168. /* Get input and treat it as a macro.  */
  169. get_mac_input(newline)
  170. int newline;    /* 1 if newline to be appended, 0 otherwise */
  171. {
  172.     register int len;
  173.     char buf[MAX_MACRO_LEN];
  174.  
  175.     /* This call cannot be nested */
  176.     if (mac_hide)
  177.     return -1;
  178.  
  179.     /* Hide the mac_stack so input comes from stdin */
  180.     mac_hide = mac_stack; mac_stack = NULL_MAP;
  181.  
  182.     if ((len = Getstr(buf, MAX_MACRO_LEN - 1, 0)) < 0)
  183.     return len;
  184.     if (newline) {
  185.     buf[len++] = '\n';
  186.     buf[len] = 0;
  187.     }
  188.  
  189.     /* Restore the mac_stack */
  190.     if (mac_stack) {
  191.     /*
  192.      * Somehow, a push happened even though mac_hide was
  193.      * nonzero -- maybe by line wrap?  Fix it as best we can.
  194.      */
  195.     struct cmd_map *msp;
  196.     for (msp = mac_stack; msp->m_next; msp = msp->m_next)
  197.         ;
  198.     msp->m_next = mac_hide;
  199.     } else
  200.     mac_stack = mac_hide;
  201.     mac_hide = NULL_MAP;
  202.  
  203.     /* Restore saved flags */
  204.     if (mac_stack) {
  205.     if (ison(mac_stack->m_cmd, IN_MACRO))
  206.         turnon(glob_flags, IN_MACRO);
  207.     else
  208.         turnoff(glob_flags, IN_MACRO);
  209.     if (ison(mac_stack->m_cmd, LINE_MACRO))
  210.         turnon(glob_flags, LINE_MACRO);
  211.     else
  212.         turnoff(glob_flags, LINE_MACRO);
  213.     }
  214.     if (len > 0)
  215.     Ungetstr(buf);
  216.  
  217.     return 1;
  218. }
  219.  
  220. /* getchar() substitute -- reads from the current macro if one is active,
  221.  * otherwise does a getchar().
  222.  *
  223.  * NOTE:  In the mac_stack, x_str is the saved text of the current macro,
  224.  *  and m_str is the current read position within the macro.
  225.  */
  226. m_getchar()
  227. {
  228.     int c;
  229.  
  230.     while (mac_stack && (! *(mac_stack->m_str)))
  231.     mac_pop();
  232.     if (mac_stack) {
  233.     c = *((mac_stack->m_str)++);
  234.     return c;
  235.     } else {
  236.     turnoff(glob_flags, IN_MACRO);
  237.     turnoff(glob_flags, LINE_MACRO);
  238.     turnoff(glob_flags, QUOTE_MACRO);
  239.     while ((c = getchar()) == 0)    /* Ignore NUL chars from stdin */
  240.         ;                /* until better solution found */
  241.     return c;
  242.     }
  243. }
  244.  
  245. m_ungetc(c)
  246. char c;
  247. {
  248.     if (mac_stack && (mac_stack->m_str > mac_stack->x_str))
  249.     *(--(mac_stack->m_str)) = c;
  250.     else
  251.     (void) ungetc(c, stdin);
  252. }
  253.  
  254. /*
  255.  * Try to read a long command; assumes MAC_LONG_CMD already seen.
  256.  *  On immediate failure, return 0.
  257.  *  On failure after reading some input, return less than zero.
  258.  *  On success, return greater than 0.
  259.  * The absolute value of the return is the number of chars placed in buf.
  260.  */
  261. read_long_cmd (buf)
  262. char *buf;
  263. {
  264.     register char c, *p = buf;
  265.     register int count = 0;
  266.  
  267.     /*
  268.      * Test in_macro() in this loop because the _entire_
  269.      * long command _must_ be in the macro -- if we run
  270.      * out of macro in mid-long-command, it is an error.
  271.      */
  272.     while (in_macro() && (count < MAX_LONG_CMD - 1)
  273.         && ((c = m_getchar()) != MAC_LONG_END)) {
  274.     *p++ = c; ++count;
  275.     }
  276.     *p = '\0';
  277.     if (c != MAC_LONG_END)
  278.     return (-count);
  279.     return count;
  280. }
  281.  
  282. /*
  283.  * Identify and possibly execute a reserved long macro command
  284.  * Executes if do_exec is true.  Otherwise, just parse.
  285.  */
  286. reserved_cmd (buf, do_exec)
  287. char *buf;
  288. {
  289.     int ret = 1;
  290.  
  291.     if (!strcmp(buf, MAC_GET_STR)) {
  292.     if (do_exec)
  293.         ret = get_mac_input(0);
  294.     } else if (!strcmp(buf, MAC_GET_LINE)) {
  295.     if (do_exec)
  296.         ret = get_mac_input(1);
  297.     } else
  298.     ret = 0;
  299.     return ret;
  300. }
  301.  
  302. #ifdef CURSES
  303.  
  304. /*
  305.  * Identify (and possibly execute, if reserved) curses mode commands
  306.  *  that appear in macro strings enclosed by MAC_LONG_CMD and
  307.  *  MAC_LONG_END.  Return the binding of the command.
  308.  */
  309. long_mac_cmd (c, do_exec)
  310. int c;
  311. {
  312.     char buf[MAX_LONG_CMD];
  313.     register int count, binding;
  314.     int y, x;
  315.  
  316.     if (c != MAC_LONG_CMD)
  317.     return C_ERROR;
  318.  
  319.     if ((count = read_long_cmd(buf)) <= 0) {
  320.     print("Invalid long macro command");
  321.     if (ison(glob_flags, CNTD_CMD))
  322.         putchar('\n');
  323.     if (do_exec)
  324.         mac_flush();
  325.     return C_ERROR;
  326.     }
  327.  
  328.     if (do_exec) {
  329.     if (ison(glob_flags, CNTD_CMD))
  330.         clr_bot_line();
  331.     getyx(stdscr, y, x);
  332.     move(LINES - 1, 0);
  333.     }
  334.     if (reserved_cmd(buf, do_exec)) {
  335.     if (do_exec) {
  336.         if (isoff(glob_flags, CNTD_CMD))
  337.         move(y, x);
  338.         return getcmd();
  339.     } else
  340.         return C_NULL;
  341.     } else if (do_exec)
  342.     move(y, x);
  343.  
  344.     /* Can start at C_NULL because of "no-op" command */
  345.     for (count = 0; count <= C_HELP; count++) {
  346.     if (!strcmp(buf, map_func_names[count].m_str)) {
  347.         binding = (int)map_func_names[count].m_cmd;
  348.         break;
  349.     }
  350.     }
  351.     /* Don't allow C_MACRO to be called directly */
  352.     if (count > C_HELP || binding == C_MACRO) {
  353.     print("Invalid long macro command");
  354.     if (ison(glob_flags, CNTD_CMD))
  355.         putchar('\n');
  356.     return C_ERROR;
  357.     } else
  358.     return binding;
  359. }
  360.  
  361. #endif /* CURSES */
  362.  
  363. /*
  364.  * Check the validity of a macro binding as far as possible
  365.  */
  366. check_mac_bindings(buf)
  367. char *buf;
  368. {
  369.     int ok = TRUE;
  370.  
  371.     while (ok && buf && *buf) {
  372.     if (*buf == MAC_LONG_CMD) {
  373.         char *i;
  374. #ifdef CURSES
  375.         int count;
  376. #endif /* CURSES */
  377.  
  378.         if (ok)
  379.         ok = ((i = index(++buf, MAC_LONG_END)) != NULL);
  380.         if (i)
  381.             *i = '\0';      /* Don't worry, we'll fix it */
  382.         else
  383.             return ok;
  384. #ifdef CURSES
  385.         /* OK to start at C_NULL because of "no-op" command */
  386.         for (count = 0; count <= C_HELP; count++)
  387.             if (! strcmp(buf, map_func_names[count].m_str))
  388.                 break;
  389.         /* Don't allow C_MACRO to be called directly */
  390.         if (count == C_MACRO)
  391.             ok = FALSE;
  392.         else if (count > C_HELP)
  393. #endif /* CURSES */
  394.         if (ok && !(ok = reserved_cmd(buf, FALSE)))
  395.         wprint("Warning: unrecognized curses command: \"%s\"\n", buf);
  396.         buf = i;
  397.         *buf++ = MAC_LONG_END;
  398.     } else if (*buf++ == '\\' && *buf)
  399.         ++buf;
  400.     }
  401.     return ok;
  402. }
  403.