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