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