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