home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff284.lzh / Dme / src / command.c < prev    next >
C/C++ Source or Header  |  1989-11-27  |  20KB  |  748 lines

  1.  
  2. /*
  3.  * COMMAND.C
  4.  *
  5.  *    (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
  6.  *
  7.  * )c             single character (typing)
  8.  * 'c                single character (typing)
  9.  * `string'          string of characters w/ embedded `' allowed!
  10.  * (string)             same thing w/ embedded () allowed!
  11.  * \c             override
  12.  *
  13.  * name arg arg      command name. The arguments are interpreted as strings
  14.  *             for the command.
  15.  *
  16.  * $scanf         macro insert scanf'd variable
  17.  * $filename         macro insert current file name
  18.  *
  19.  * Any string arguments not part of a command are considered to be typed
  20.  * text.
  21.  */
  22.  
  23. #include "defs.h"
  24. #include <stdio.h>
  25.  
  26. #if AREXX
  27. extern int foundcmd;       /* control for implicit ARexx macro invocation   */
  28. extern int cmderr;       /* global command error flag for do_rexx()'s use */
  29. #endif
  30.  
  31. #define CF_COK    1   /*    Can be executed while in command line mode    */
  32. #define CF_PAR    2   /*    ESCIMM special flag.. save rest of command line */
  33.             /*    so it can be executed after user entry        */
  34.  
  35. #define CF_ICO    4   /*    OK to execute if iconified, else uniconify first*/
  36.  
  37. #define BTOCP(val, type)    ((type)((long)val << 2))
  38.  
  39. extern char *breakout();
  40.  
  41. typedef void (*FPTR) ARGS((long));
  42.  
  43. typedef struct {
  44.    char *name;        /* command name      */
  45.    ubyte args;
  46.    ubyte flags;
  47.    void (*func) ARGS((long));  /* function           */
  48. } COMM;
  49.  
  50. /*
  51.  
  52. extern void do_map(),       do_unmap(),     do_up(),        do_down(),
  53.         do_left(),      do_right(),     do_return(),    do_bs(),
  54.         do_del(),       do_esc(),       do_downadd(),   do_lastcolumn(),
  55.         do_firstcolumn(),do_edit(),     do_tab(),       do_backtab(),
  56.         do_save(),      do_saveas(),    do_deline(),    do_insline(),
  57.         do_top(),       do_bottom(),    do_source(),    do_firstnb(),
  58.         do_quit(),      do_find(),      do_page(),      do_savetabs(),
  59.         do_split(),     do_goto(),      do_screentop(), do_screenbottom(),
  60.         do_repeat(),    do_tabstop(),   do_insertmode(),
  61.         do_block(),     do_bdelete(),   do_bcopy(),     do_bmove(),
  62.         do_bsave(),     do_wleft(),     do_wright(),    do_remeol(),
  63.         do_savemap(),   do_if(),        do_tlate(),
  64.         do_bsource(),   do_findr(),     do_findstr(),   do_newwindow(),
  65.         do_windowparm(),do_resize(),    do_margin(),    do_wordwrap(),
  66.         do_reformat(),  do_execute(),   do_chfilename(),do_scrollup(),
  67.         do_scrolldown(),do_recall(),    do_scanf(),     do_iconify(),
  68.         do_tomouse(),   do_refs(),      do_arpload(),   do_arpsave(),
  69.         do_arpinsfile(),do_setfont(),   do_ignorecase(),do_ctags(),
  70.         do_addpath(),   do_rempath(),   do_set(),       do_setenv(),
  71.         do_unset(),     do_unsetenv(),  do_ipc(),       do_cd();
  72.  
  73. extern void do_menu(), do_menuclear(), do_menuadd(), do_menudel(),
  74.         do_menudelhdr(), do_menuon(), do_menuoff();
  75.  
  76. extern void do_null(), do_rx();
  77.  
  78. extern void do_popmark(),   do_swapmark(),  do_purgemark(),
  79.         do_ping(),      do_pong(),      do_undo();
  80.  
  81. extern int  do_pushmark(),  do_rexx(),      do_join(),
  82.         do_toggle(),    do_command(),   do_col();
  83.  
  84. #if AREXX
  85. extern void do_rx(),        do_rx1(),       do_rx2();
  86. #endif
  87.  
  88. */
  89.  
  90. /*============================================================================*/
  91.  
  92. /*
  93.  *  WLEFT/WRIGHT will check command line mode themselves, and thus can
  94.  *  be marked flags=1 even though they can change the line number.
  95.  *
  96.  *  No more than 255 commands may exist unless you change the type of hindex[]
  97.  *
  98.  *  Command names MUST be sorted by their first character
  99.  */
  100.  
  101. unsigned char hindex[26];   /*    alpha hash into table    */
  102.  
  103.     /*      args flags    */
  104.  
  105. COMM Comm[] = {
  106. #ifndef NO_DO2
  107.     "addpath",       1, CF_COK, (FPTR)do_addpath,
  108. #endif
  109.     "arpinsfile",    0,      0, (FPTR)do_arpinsfile,
  110.     "arpload",       0,      0, (FPTR)do_arpload,
  111.     "arpsave",       0,      0, (FPTR)do_arpsave,
  112.     "back",          0, CF_COK, (FPTR)do_bs,
  113.     "backtab",       0, CF_COK, (FPTR)do_backtab,
  114.     "bcopy",         0,      0, (FPTR)do_bcopy,
  115.     "bdelete",       0,      0, (FPTR)do_bdelete,
  116.     "block",         0,      0, (FPTR)do_block,    /* checks com name for mode */
  117.     "bmove",         0,      0, (FPTR)do_bmove,
  118.     "bottom",        0,      0, (FPTR)do_bottom,
  119.     "bs",            0, CF_COK, (FPTR)do_bs,
  120.     "bsave",         1, CF_COK, (FPTR)do_bsave,
  121.     "bsource",       0,      0, (FPTR)do_bsource,
  122.     "cd",            1, CF_COK, (FPTR)do_cd,
  123.     "chfilename",    1,      0, (FPTR)do_chfilename,
  124.     "col",           1, CF_COK, (FPTR)do_col,
  125. #ifndef NO_DO_CTAGS
  126.     "ctags",         0, CF_ICO, (FPTR)do_ctags,
  127. #endif
  128.     "del",           0, CF_COK, (FPTR)do_del,
  129.     "deline",        0,      0, (FPTR)do_deline,
  130.     "down",          0,      0, (FPTR)do_down,
  131.     "downadd",       0,      0, (FPTR)do_downadd,
  132.     "esc",           0, CF_COK, (FPTR)do_esc,
  133.     "escimm",        1, CF_PAR, (FPTR)do_esc,
  134.     "execute",       1, CF_ICO, (FPTR)do_execute,
  135.     "find",          1,      0, (FPTR)do_find,     /* checks com name for mode */
  136.     "findr",         2,      0, (FPTR)do_findr,    /* checks com name for mode */
  137.     "findstr",       1, CF_COK, (FPTR)do_findstr,  /* checks com name for mode */
  138.     "first",         0, CF_COK, (FPTR)do_firstcolumn,
  139.     "firstnb",       0, CF_COK, (FPTR)do_firstnb,
  140.     "goto",          1,      0, (FPTR)do_goto,
  141.     "height",        1, CF_COK, (FPTR)do_windowparm,
  142.     "iconify",       0, CF_ICO, (FPTR)do_iconify,
  143.     "if",            2, CF_COK, (FPTR)do_if,
  144.     "ifelse",        3, CF_COK, (FPTR)do_if,
  145.     "ignorecase",    1, CF_COK, (FPTR)do_ignorecase,
  146.     "insertmode",    1, CF_COK, (FPTR)do_insertmode,
  147.     "insfile",       1,      0, (FPTR)do_edit,
  148.     "insline",       0,      0, (FPTR)do_insline,
  149. #ifndef NODRES
  150.     "ipc",           3, CF_COK, (FPTR)do_ipc,
  151. #endif
  152.     "join",          0,      0, (FPTR)do_join,
  153.     "last",          0, CF_COK, (FPTR)do_lastcolumn,
  154.     "left",          0, CF_COK, (FPTR)do_left,
  155.     "leftedge",      1, CF_COK, (FPTR)do_windowparm,
  156.     "map",           2, CF_COK, (FPTR)do_map,
  157.     "margin",        1, CF_COK, (FPTR)do_margin,
  158.     "menuon",        0,      0, (FPTR)do_menuon,
  159.     "menuoff",       0,      0, (FPTR)do_menuoff,
  160.     "menuadd",       3,      0, (FPTR)do_menuadd,
  161.     "menudel",       2,      0, (FPTR)do_menudel,
  162.     "menudelhdr",    1,      0, (FPTR)do_menudelhdr,
  163.     "menuclear",     0,      0, (FPTR)do_menuclear,
  164.     "newfile",       1,      0, (FPTR)do_edit,     /* checks com name for mode */
  165.     "newwindow",     0, CF_ICO, (FPTR)do_newwindow,
  166.     "next",          0,      0, (FPTR)do_find,
  167.     "nextr",         0,      0, (FPTR)do_findr,
  168.     "null",          0, CF_COK, (FPTR)do_null,
  169.     "pagedown",      0,      0, (FPTR)do_page,
  170.     "pageset",       1,      0, (FPTR)do_page,
  171.     "pageup",        0,      0, (FPTR)do_page,
  172.     "ping",          1, CF_ICO, (FPTR)do_ping,
  173.     "pong",          1,      0, (FPTR)do_pong,
  174.     "prev",          0,      0, (FPTR)do_find,
  175.     "prevr",         0,      0, (FPTR)do_findr,
  176.     "popmark",       0,      0, (FPTR)do_popmark,
  177.     "purgemark",     0,      0, (FPTR)do_purgemark,
  178.     "pushmark",      0,      0, (FPTR)do_pushmark,
  179.     "quit",          0, CF_ICO, (FPTR)do_quit,
  180.     "recall",        0, CF_COK, (FPTR)do_recall,
  181. #ifndef NO_DO_REF
  182.     "ref",           0,      0, (FPTR)do_refs,
  183. #endif
  184.     "reformat",      0,      0, (FPTR)do_reformat,
  185.     "remeol",        0, CF_COK, (FPTR)do_remeol,
  186. #ifndef NO_DO2
  187.     "rempath",       1, CF_COK, (FPTR)do_rempath,
  188. #endif
  189.     "repeat",        2, CF_ICO|CF_COK, (FPTR)do_repeat,
  190.     "repstr",        1, CF_COK, (FPTR)do_findstr,
  191.     "resettoggle",   1, CF_COK, (FPTR)do_toggle,
  192.     "resize",        2,      0, (FPTR)do_resize,
  193.     "return",        0, CF_COK, (FPTR)do_return,   /* special meaning in command line mode */
  194.     "right",         0, CF_COK, (FPTR)do_right,
  195. #if AREXX
  196.     "rx",            1,      0, (FPTR)do_rx,       /* explicit ARexx macro invocation      */
  197.     "rx1",           2,      0, (FPTR)do_rx1,      /* explicit, with 1 arg  to ARexx macro */
  198.     "rx2",           3,      0, (FPTR)do_rx2,      /* explicit, with 2 args to ARexx macro */
  199. #endif
  200.     "saveas",        1, CF_ICO|CF_COK, (FPTR)do_saveas,
  201.     "savemap",       1, CF_ICO|CF_COK, (FPTR)do_savemap,  /* checks com name for mode */
  202.     "saveold",       0, CF_ICO|CF_COK, (FPTR)do_save,
  203.     "savesmap",      1, CF_ICO|CF_COK, (FPTR)do_savemap,
  204.     "savetabs",      1, CF_ICO|CF_COK, (FPTR)do_savetabs,
  205.     "scanf",         1, CF_COK, (FPTR)do_scanf,
  206.     "screenbottom",  0,      0, (FPTR)do_screenbottom,
  207.     "screentop",     0,      0, (FPTR)do_screentop,
  208.     "scrollup",      0,      0, (FPTR)do_scrollup,
  209.     "scrolldown",    0,      0, (FPTR)do_scrolldown,
  210.     "set",           2, CF_ICO|CF_COK, (FPTR)do_set,
  211.     "setenv",        2, CF_ICO|CF_COK, (FPTR)do_setenv,
  212.     "setfont",       2,      0, (FPTR)do_setfont,
  213.     "settoggle",     1, CF_COK, (FPTR)do_toggle,
  214.     "source",        1, CF_COK, (FPTR)do_source,
  215.     "split",         0,      0, (FPTR)do_split,
  216.     "swapmark",      0,      0, (FPTR)do_swapmark,
  217.     "tab",           0, CF_COK, (FPTR)do_tab,
  218.     "tabstop",       1, CF_COK, (FPTR)do_tabstop,
  219.     "tlate",         1, CF_COK, (FPTR)do_tlate,
  220.     "tmpheight",     1, CF_COK, (FPTR)do_windowparm,
  221.     "tmpwidth",      1, CF_COK, (FPTR)do_windowparm,
  222.     "toggle",        1, CF_COK, (FPTR)do_toggle,
  223.     "tomouse",       0,      0, (FPTR)do_tomouse,
  224.     "top",           0,      0, (FPTR)do_top,
  225.     "topedge",       1, CF_COK, (FPTR)do_windowparm,
  226.     "unblock",       0,      0, (FPTR)do_block,
  227.     "undo",          0,      0, (FPTR)do_undo,
  228.     "unmap",         1, CF_ICO|CF_COK, (FPTR)do_unmap,
  229.     "unset",         1, CF_ICO|CF_COK, (FPTR)do_unset,
  230.     "unsetenv",      1, CF_ICO|CF_COK, (FPTR)do_unsetenv,
  231.     "up",            0,      0, (FPTR)do_up,
  232.     "while",         2, CF_ICO|CF_COK, (FPTR)do_if,
  233.     "width",         1, CF_COK, (FPTR)do_windowparm,
  234.     "wleft",         0, CF_COK, (FPTR)do_wleft,
  235.     "wordwrap",      1, CF_COK, (FPTR)do_wordwrap,
  236.     "wright",        0, CF_COK, (FPTR)do_wright,
  237.     NULL, 0, 0, NULL
  238. };
  239.  
  240. void
  241. init_command()
  242. {
  243.     register short hi;
  244.     register COMM *comm;
  245.  
  246.     hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
  247.     comm = Comm + hi;
  248.  
  249.     while (hi >= 0) {
  250.     hindex[comm->name[0] - 'a'] = hi;
  251.     --hi;
  252.     --comm;
  253.     }
  254. }
  255.  
  256. #define MAXIA    5
  257.  
  258. do_command(str)
  259. char *str;
  260. {
  261.     register char *arg;
  262.     char *aux1, *aux2;
  263.     char *repstr[MAXIA];
  264.     char quoted;
  265.     short repi = 0;
  266.     register short i, j;
  267.     static int level;
  268.  
  269.     if (++level > 20) {
  270.     title("Recursion Too Deep!");
  271.     --level;
  272. #if AREXX
  273.     foundcmd = 1;    /* to prevent us from trying an ARexx macro */
  274. #endif
  275.     return(0);
  276.     }
  277.     while (arg = breakout(&str, "ed, &aux1)) {
  278.     if (quoted) {
  279.         if (Ep->iconmode)
  280.         uniconify();
  281.         text_write(arg);
  282.         goto loop;
  283.     }
  284.     for (i = 0; arg[i]; ++i) {
  285.         if (arg[i] >= 'A' && arg[i] <= 'Z')
  286.         arg[i] += 'a' - 'A';
  287.     }
  288.  
  289.     if (arg[0] >= 'a' && arg[0] <= 'z') {
  290.         register COMM *comm = &Comm[hindex[arg[0]-'a']];
  291.         for (; comm->name && comm->name[0] == arg[0]; ++comm) {
  292.         if (strcmp(arg, comm->name) == 0) {
  293. #if AREXX
  294.             foundcmd = 1;
  295. #endif
  296.             av[0] = (ubyte *)comm->name;
  297.             for (j = 1; j <= comm->args; ++j) {
  298.             av[j] = (ubyte *)breakout(&str, "ed, &aux2);
  299.             if (aux2) {
  300.                 if (repi == MAXIA) {
  301.                 free(aux2);
  302.                 title("Command too complex");
  303.                 goto fail;
  304.                 } else {
  305.                 repstr[repi++] = aux2;
  306.                 }
  307.             }
  308.             if (!av[j]) {
  309.                 title("Bad argument");
  310.                 goto fail;
  311.             }
  312.             }
  313.             av[j] = NULL;   /* end of arglist */
  314.             if ((comm->flags & CF_COK) || !Comlinemode) {
  315.             if (comm->flags & CF_PAR) {
  316.                 if (Partial)
  317.                 free(Partial);
  318.                 Partial = (char *)malloc(strlen(str)+1);
  319.                 strcpy(Partial, str);
  320.                 str += strlen(str);     /*  skip string */
  321.             }
  322.             if (Ep->iconmode && !(comm->flags & CF_ICO))
  323.                 uniconify();
  324.             (*comm->func)(-1);
  325.             }
  326.             if (Abortcommand)
  327.             goto fail;
  328.             goto loop;
  329.         }
  330.         }
  331.     }
  332.  
  333.     /* Command not found, check for macro    */
  334.  
  335.     {
  336.         char *str;
  337.         int ret;
  338.         if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) {
  339.         str = (char *)strcpy(malloc(strlen(str)+1), str);
  340.         ret = do_command(str);
  341.         free(str);
  342. #if AREXX
  343.         if (ret) {
  344.             foundcmd = 1;   /* dunno about this yet for ARexx macros */
  345.             goto loop;
  346.         }
  347. #else
  348.         if (ret)
  349.             goto loop;
  350. #endif
  351.         goto fail;
  352.         }
  353.     }
  354.  
  355.     /* Command still not found, check for public macro  */
  356.     /* code to be added */
  357.  
  358. #if AREXX
  359.     do_rxImplied(arg, str);
  360. #else
  361.     title("Unknown Command");
  362. #endif
  363. fail:
  364.     --level;
  365.     while (--repi >= 0)
  366.         free(repstr[repi]);
  367.     if (aux1)
  368.         free(aux1);
  369.     return(0);
  370. loop:
  371.     if (aux1)
  372.         free(aux1);
  373.     }
  374.     --level;
  375.     while (--repi >= 0)
  376.     free(repstr[repi]);
  377.     return(1);
  378. }
  379.  
  380. void
  381. do_null()
  382. {
  383. }
  384.  
  385. void
  386. do_source()
  387. {
  388.     char buf[256];
  389.     void *xfi;
  390.     register char *str;
  391.     long oldlock = CurrentDir(DupLock(Ep->dirlock));
  392.  
  393.     if (xfi = xfopen(av[1], "r", 512)) {
  394.     while (xfgets(xfi, buf, 256) >= 0) {
  395.         if (buf[0] == '#')
  396.         continue;
  397.         for (str = buf; *str; ++str) {
  398.         if (*str == 9)
  399.             *str = ' ';
  400.         }
  401.         do_command(buf);
  402.     }
  403.     xfclose(xfi);
  404.     } else {
  405.     if (av[0])
  406.         title("File not found");
  407.     }
  408.     UnLock(CurrentDir(oldlock));
  409. }
  410.  
  411.  
  412. void
  413. do_quit()
  414. {
  415.     extern char Quitflag;
  416.  
  417.     Quitflag = 1;
  418. }
  419.  
  420. void
  421. do_execute()
  422. {
  423.     long oldlock = CurrentDir(Ep->dirlock);
  424.     long NilFH = Open("null:", 1006);
  425.     PROC *proc = (PROC *)FindTask(NULL);
  426.  
  427.     if (NilFH) {
  428.     proc->pr_ConsoleTask = (APTR)BTOCP(NilFH, struct FileHandle *)->fh_Port;
  429.     Execute(av[1], NilFH, NilFH);
  430.     Close(NilFH);
  431.     } else {
  432.     title("NULL: device required for (execute)");
  433.     }
  434.     CurrentDir(oldlock);
  435. }
  436.  
  437. /*
  438.  * repeat X command
  439.  *
  440.  * Since repeat takes up 512+ stack, it should not be nested more than
  441.  * twice.
  442.  *
  443.  * (if X is not a number it can be abbr. with 2 chars)
  444.  *
  445.  * X =    N     -number of repeats
  446.  *    line  -current line # (lines begin at 1)
  447.  *    lbot  -#lines to the bottom, inc. current
  448.  *    cleft -column # (columns begin at 0)
  449.  *        (thus is also chars to the left)
  450.  *    cright-#chars to eol, including current char
  451.  *    tr    -#char positions to get to next tab stop
  452.  *    tl    -#char positions to get to next backtab stop
  453.  */
  454.  
  455. #define SC(a,b) ((a)<<8|(b))
  456.  
  457. void
  458. do_repeat()
  459. {
  460.     register ubyte *ptr = av[1];
  461.     register unsigned long n;
  462.     char buf1[256];
  463.     char buf2[256];
  464.  
  465.     breakreset();
  466.     strcpy(buf1, av[2]);
  467.     switch((ptr[0]<<8)+ptr[1]) {
  468.     case SC('l','i'):
  469.     n = text_lineno();
  470.     break;
  471.     case SC('l','b'):
  472.     n = text_lines() - text_lineno() + 1;
  473.     break;
  474.     case SC('c','l'):
  475.     n = text_colno();
  476.     break;
  477.     case SC('c','r'):
  478.     n = text_cols() - text_colno();
  479.     break;
  480.     case SC('t','r'):
  481.     n = text_tabsize()-(text_colno() % text_tabsize());
  482.     break;
  483.     case SC('t','l'):
  484.     n = text_colno() % text_tabsize();
  485.     if (n == 0)
  486.         n = text_tabsize();
  487.     break;
  488.     default:
  489.     n = atoi(av[1]);
  490.     break;
  491.     }
  492.     while (n > 0) {
  493.     strcpy(buf2, buf1);
  494.     if (do_command(buf2) == 0 || breakcheck()) {
  495.         Abortcommand = 1;
  496.         break;
  497.     }
  498.     --n;
  499.     }
  500. }
  501.  
  502. /*
  503.  *  BREAKOUT()
  504.  *
  505.  *  Break out the next argument.  The argument is space delimited and
  506.  *  might be quoted with `' or (), or single quoted as 'c or )c
  507.  *
  508.  *  Also:    $var        -variable insertion
  509.  *        ^c        -control character
  510.  */
  511.  
  512. char *
  513. breakout(ptr, quoted, paux)
  514. register char **ptr;
  515. char **paux;
  516. char *quoted;
  517. {
  518.     register char *str = *ptr;
  519.     char *base;
  520.     short count = 0;
  521.     char opc = 0;
  522.     char clc = 0;
  523.     char immode = 0;
  524.     char isaux = 0;
  525.     char buf[256];
  526.     short di = 0;
  527.  
  528.     *quoted = 0;
  529.     *paux = NULL;
  530.     while (*str == ' ')
  531.     ++str;
  532.     if (!*str)
  533.     return(NULL);
  534.  
  535.     *ptr = str;
  536.     base = str;
  537.     while (*str) {
  538.     if (immode) {
  539.         if (di != sizeof(buf)-1)
  540.         buf[di++] = *str;
  541.         ++str;
  542.         continue;
  543.     }
  544.     if (count == 0) {
  545.         if (*str == ' ')
  546.         break;
  547.         if (*str == '\'' || *str == ')')
  548.         clc = *str;
  549.         if (*str == '`') {
  550.         opc = '`';
  551.         clc = '\'';
  552.         }
  553.         if (*str == '(') {
  554.         opc = '(';
  555.         clc = ')';
  556.         }
  557.     }
  558.     if (*str == opc) {
  559.         ++count;
  560.         if (str == *ptr) {
  561.         *quoted = 1;
  562.         base = ++str;
  563.         continue;
  564.         }
  565.     }
  566.     if (*str == clc) {
  567.         --count;
  568.         if (count == 0 && *quoted)     /*  end of argument     */
  569.         break;
  570.         if (str == *ptr && count < 0) {
  571.         immode = 1;
  572.         *quoted = 1;
  573.         base = ++str;
  574.         continue;
  575.         }
  576.     }
  577.  
  578.     /*
  579.      *  $varname $(varname) $`varname'.  I.E. three forms are allowed,
  580.      *  which allows one to insert the string almost anywhere.  The
  581.      *  first form names are limited to alpha-numerics, '-', and '_'.
  582.      */
  583.  
  584.     if (*str == '$') {
  585.         register char *ptr;
  586.         char *tmpptr;
  587.         char c, ce;
  588.         short len;
  589.  
  590.         ce = 0;                /*    first form  */
  591.         ++str;                /*    skip $        */
  592.         if (*str == '(') {              /*  second form */
  593.         ce = ')';
  594.         ++str;
  595.         } else if (*str == '`') {       /*  third form  */
  596.         ce = '\'';
  597.         ++str;
  598.         }
  599.         ptr = str;                /*    start of varname    */
  600.         if (ce) {                       /*  until end char OR   */
  601.         while (*ptr && *ptr != ce)
  602.             ++ptr;
  603.         } else {                /*    smart end-varname   */
  604.         while ((*ptr >= 'a' && *ptr <= 'z') ||
  605.             (*ptr >= 'A' && *ptr <= 'Z') ||
  606.             (*ptr >= '0' && *ptr <= '9') ||
  607.             *ptr == '-' || *ptr == '_' ) {
  608.             ++ptr;
  609.         }
  610.         }
  611.         len = ptr - str;            /*    length of variable  */
  612.  
  613.         c = *ptr; *ptr = 0;         /*    temp. terminate \0  */
  614.         if (strcmp(str, "scanf") == 0) {
  615.         *ptr = c;
  616.         isaux = 1;
  617.         if (di + strlen(String) < sizeof(buf)-1) {
  618.             strcpy(buf + di, String);
  619.             di += strlen(buf + di);
  620.         }
  621.         str += len;            /*    next string pos     */
  622.         if (ce)
  623.             ++str;
  624.         continue;
  625.         }
  626.         if (strcmp(str, "fpath") == 0) {
  627.         register short i;
  628.         for (i = strlen(Ep->Name); i >= 0; --i) {
  629.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  630.             break;
  631.         }
  632.         ++i;
  633.         *ptr = c;
  634.         isaux = 1;
  635.         if (di + i < sizeof(buf)-1) {
  636.             BMov(Ep->Name, buf + di, i);
  637.             di += i;
  638.             buf[di] = 0;
  639.         }
  640.         str += len;
  641.         if (ce)
  642.             ++str;
  643.         continue;
  644.         }
  645.         if (strcmp(str, "fname") == 0) {
  646.         register short i;
  647.         short j;
  648.         for (i = strlen(Ep->Name); i >= 0; --i) {
  649.             if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
  650.             break;
  651.         }
  652.         ++i;
  653.         j = strlen(Ep->Name + i);
  654.         *ptr = c;
  655.         isaux = 1;
  656.         if (di + j < sizeof(buf)-1) {
  657.             BMov(Ep->Name + i, buf + di, j);
  658.             di += j;
  659.             buf[di] = 0;
  660.         }
  661.         str += len;
  662.         if (ce)
  663.             ++str;
  664.         continue;
  665.         }
  666.         if (strcmp(str, "filename") == 0) {
  667.         *ptr = c;
  668.         isaux = 1;
  669.         if (di + strlen(Ep->Name) < sizeof(buf)-1) {
  670.             strcpy(buf + di, Ep->Name);
  671.             di += strlen(buf + di);
  672.         }
  673.         str += len;
  674.         if (ce)
  675.             ++str;
  676.         continue;
  677.         }
  678.         if (strcmp(str, "colno") == 0) {
  679.         *ptr = c;
  680.         isaux = 1;
  681.         if (di < sizeof(buf)-8) {
  682.             sprintf(buf + di, "%ld", Ep->Column + 1);
  683.             di += strlen(buf + di);
  684.         }
  685.         str += len;
  686.         if (ce)
  687.             ++str;
  688.         continue;
  689.         }
  690.         if (strcmp(str, "lineno") == 0) {
  691.         *ptr = c;
  692.         isaux = 1;
  693.         if (di < sizeof(buf)-8) {
  694.             sprintf(buf + di, "%ld", Ep->Line + 1);
  695.             di += strlen(buf + di);
  696.         }
  697.         str += len;
  698.         if (ce)
  699.             ++str;
  700.         continue;
  701.         }
  702.         if (tmpptr = getvar(str)) {
  703.         ptr = tmpptr;
  704.         str[len] = c;
  705.         isaux = 1;
  706.         if (di + strlen(ptr) < sizeof(buf)-1) {
  707.             strcpy(buf + di, ptr);
  708.             di += strlen(buf + di);
  709.         }
  710.         str += len;
  711.         if (ce)
  712.             ++str;
  713.         free(ptr);
  714.         continue;
  715.         }
  716.         *ptr = c;
  717.         --str;
  718.         if (ce)
  719.         --str;
  720.     }
  721.     if (*str == '^' && (str[1] & 0x1F)) {
  722.         ++str;
  723.         *str &= 0x1F;
  724.         isaux = 1;
  725.     }
  726.     if (*str == '\\' && str[1]) {
  727.         ++str;
  728.         isaux = 1;
  729.     }
  730.     buf[di++] = *str++;
  731.     }
  732.     buf[di++] = 0;
  733.     if (isaux) {
  734.     *paux = malloc(di);
  735.     strcpy(*paux, buf);
  736.     base = *paux;
  737.     }
  738.     if (*str) {             /*  space ended */
  739.     *str = '\0';
  740.     *ptr = str + 1;     /*    next arg    */
  741.     } else {
  742.     *ptr = str;        /*    last arg    */
  743.     }
  744.     return(base);
  745. }
  746.  
  747.  
  748.