home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / misc / b186_1 / Source / c / command < prev    next >
Text File  |  1994-02-16  |  12KB  |  532 lines

  1. /*
  2.  
  3.        This file is part of the PDP software package.
  4.          
  5.        Copyright 1987 by James L. McClelland and David E. Rumelhart.
  6.        
  7.        Please refer to licensing information in the file license.txt,
  8.        which is in the same directory with this source file and is
  9.        included here by reference.
  10. */
  11.  
  12.  
  13. /* command.c
  14.  
  15.     the root command routines.
  16.     
  17.     First version implemented by Elliot Jaffe.
  18.     
  19.     Date of last revision:  8-12-87/JLM.
  20. */
  21.  
  22. /* 
  23.     The command routines are mostly table driven.
  24. */
  25.  
  26. #include "general.h"
  27. #include "io.h"
  28. #include "command.h"
  29. #include "curses.h"
  30.  
  31. int maxcommands = MAXCOMMANDS;
  32. /* maxcommands is automatically increased if necessary */
  33.  
  34. static int  Current_Menu;
  35. int endline = 1;
  36. int error_flag = 0;
  37. int file_err = 0;
  38. int last_entry = 0;
  39.  
  40. /* This function is the top level of the command interface.
  41.    it takes a string, that it will use as the prompt, and a table
  42.    pointer, that will be used to parse the command.  The function prints
  43.    the prompt.  Then, it gets a string. Matches the string on the names
  44.    in the Command table, and if there is a match, it will call the
  45.    appropiate function.  Specialized command routines are set up by
  46.    puting there name in the command table and having a command call them.
  47. */
  48.  
  49. do_command(str, current_menu)
  50. char   *str;
  51. int    *current_menu;
  52. {
  53.     char   *get_command ();
  54.     char   *strcat ();
  55.     char   *command_string;
  56.     char    new_command[128];
  57.     int     matches, lastmatch, matchlen,tlen,i;
  58.     
  59.     Interrupt_flag = 0;
  60.  
  61.     Current_Menu = (int) current_menu;
  62.     if (endline) {
  63.       do_help(str,Current_Menu);
  64.     }
  65.  
  66.     command_string = get_command(str);
  67.  
  68.     if (command_string == (char *) NULL) {
  69.       if (Current_Menu == BASEMENU) return(POP);
  70.     return(BREAK);
  71.     }
  72.  
  73.     matches = 0;
  74.  
  75.     for (i = 0; i < last_entry; ++i) {
  76.       if ((!Command[i].menutype) || (Command[i].menutype == Current_Menu)) {
  77.         if (!strcmp(Command[i].command, command_string)) {
  78.         matches = 1;
  79.         lastmatch = i;
  80.         break;
  81.         }
  82.     }
  83.     }
  84.     if (!matches) {        /* no exact matches, try partials */
  85.     matchlen = strlen(command_string);
  86.     for (i = 0; i < last_entry; ++i) {
  87.         if ((!Command[i].menutype) ||
  88.                   (Command[i].menutype == Current_Menu)) {
  89.         tlen = strlen(Command[i].command) -1;
  90.         if (Command[i].command[tlen] == '/') {
  91.             if (tlen > matchlen) tlen = matchlen;
  92.         }
  93.         else tlen = matchlen;
  94.         if (!strncmp(Command[i].command, command_string, tlen)) {
  95.             ++matches;
  96.             lastmatch = i;
  97.         }
  98.         }
  99.     }
  100.     }
  101.     if (matches > 1) {
  102.       if( Current_Menu == DISPLAYMENU) {
  103.         matchlen = strlen(command_string);
  104.         for (i = 0; i < last_entry; ++i) {
  105.               if ((Command[i].menutype == Current_Menu)) {
  106.             if (!strncmp(Command[i].command,command_string,matchlen)){
  107.                 *new_command = '\0';
  108.               (void) strcat(new_command, str);
  109.               (void) strcat(new_command, " ");
  110.               (void) strcat(new_command,Command[lastmatch].command);
  111.               if ((*Command[i].func)(new_command,Command[i].arg) 
  112.                                       == BREAK) {
  113.             return(BREAK);
  114.               }
  115.             }
  116.             }
  117.         }
  118.     }
  119.     else {
  120.         sprintf(err_string,"ambiguous command: '%s'.  Choose one of: ",
  121.                             command_string);
  122.         for (i = 0; i < last_entry; ++i) {
  123.             if ((!Command[i].menutype) ||
  124.                       (Command[i].menutype == Current_Menu)) {
  125.            if (!strncmp(Command[i].command,command_string,matchlen)){
  126.                 strcat(err_string, Command[i].command);
  127.                 strcat(err_string, " ");
  128.             }
  129.             }
  130.         }
  131.         return(put_error(err_string));
  132.     }
  133.     }
  134.     else
  135.     if (matches == 0) {
  136.         sprintf(err_string,"Unrecognized command: %s.", command_string);
  137.         return(put_error(err_string));
  138.     }
  139.     else {
  140.     *new_command = '\0';
  141.     (void) strcat(new_command, str);
  142.     (void) strcat(new_command, " ");
  143.     (void) strcat(new_command, Command[lastmatch].command);
  144.     /* now that the new command string is done, call the function. */
  145.     return((*Command[lastmatch].func)(new_command,Command[lastmatch].arg));
  146.     }
  147. }
  148.  
  149. /* comparison routine for sorting command lists -- jlm */
  150.  
  151. comcomp (p1, p2) char **p1, **p2; {
  152.     int h1 = 0; /* high-level command, ends in '/' */
  153.     int h2 = 0; 
  154.     char *c1, *c2;
  155.     char *e1, *e2;
  156.     c1 = *p1;
  157.     c2 = *p2;
  158.     for (e1 = c1; *e1; e1++); e1--;
  159.     for (e2 = c2; *e2; e2++); e2--;
  160.     if (*e1 == '/') h1 = 1;
  161.     if (*e2 == '/') h2 = 1;
  162.     if (h1 > h2) return (-1);
  163.     if (h2 > h1) return (1);
  164.     return(strcmp(c1,c2));
  165. }
  166.  
  167. /* ARGSUSED */
  168. int lasthelpline = 1;
  169.  
  170. do_help(str, menu_type) char   *str; int     menu_type; {
  171.     int     i,j,k;
  172.     int        foundone;
  173.     int     len, listlen;
  174.     int        xpos;
  175.     char    **tcommand;
  176.  
  177.     if (in_stream != stdin)
  178.     return;
  179.  
  180.     clear_help();
  181.     tcommand = ((char **) emalloc ((unsigned)((sizeof(char *)) * last_entry)));
  182.     
  183.     for (i = 0, j = 0; i < last_entry; i++) {
  184.     if (Command[i].menutype == menu_type) {
  185.         tcommand[j++] = Command[i].command;
  186.     }
  187.     }
  188.     listlen = j;
  189.     if (menu_type > 0) {
  190.     qsort(tcommand,listlen,sizeof(char *),comcomp);
  191.     }
  192.     for (i = 0, xpos = 0; i < listlen; i++) {
  193.             if (i && !strcmp(tcommand[i],tcommand[i-1]))
  194.             continue;
  195.         len = strlen(tcommand[i]);
  196.         if ((xpos + 2 + len) > 79) {
  197.             io_move(++lasthelpline,0);
  198.             xpos = 0;
  199.         }
  200.         if (xpos == 0) {
  201.             io_printw("%s",tcommand[i]);
  202.             xpos += len;
  203.         }
  204.         else {
  205.             io_printw("  %s",tcommand[i]);
  206.             xpos += len + 2;
  207.         }
  208.     }
  209.     io_refresh();
  210.     free(tcommand);
  211. }
  212.  
  213.  
  214. clear_help() {
  215.     int     i;
  216.  
  217.     for (i = 1; i <= lasthelpline; i++) {
  218.     io_move(i, 0);
  219.     io_clrtoeol();
  220.     }
  221.     io_move(1, 0);
  222.     io_refresh();
  223.     lasthelpline = 1;
  224. }
  225.  
  226. put_error(s)
  227. char   *s;
  228. {
  229.     error_flag = 1;
  230.     if(start_up) {
  231.      fprintf(stderr,"%s\n", s);
  232.      exit(0);
  233.     }
  234.     clear_help();
  235. #ifdef MSDOS
  236.     io_printw("Error: %s", s);
  237. #else
  238.     io_printw("Error: %s", s);
  239. #endif
  240.     scs();
  241.     if (in_stream != stdin) return(file_error());
  242.     return(CONTINUE);
  243. }
  244.  
  245. scs() {
  246.     io_refresh();
  247. /*    sleep(3); */
  248.     getch();
  249.     clear_help();
  250.     io_refresh();
  251. }
  252.  
  253. init_commands() {
  254.     extern struct Command_table *Command;
  255.     int i;
  256.     
  257.     Command = (struct Command_table *)
  258.               emalloc((unsigned)(maxcommands * sizeof(struct Command_table)));
  259.     for (i = 0; i < maxcommands; i++) Command[i].command = 0;
  260. }
  261.  
  262. /* declare this as void so we don't have to cast all calls to install_command 
  263.       abh - 2/15/88 
  264. */
  265.  
  266. void install_command(str, func, menu, intp)
  267. char   *str;
  268. int     (*func)();
  269. int     menu;
  270. int    *intp;
  271. {
  272.     int     i,j;
  273.  
  274.     if (last_entry == maxcommands-1) {
  275.         i = maxcommands;
  276.     maxcommands += 20; /* increase maxcommands if necessary */
  277.     Command = (struct Command_table *) erealloc((char *)Command, 
  278.            (unsigned)((maxcommands -20)*sizeof(struct Command_table)),
  279.                (unsigned)(maxcommands * sizeof(struct Command_table)));
  280.     for (j = i; j < maxcommands; j++) Command[j].command = 0;
  281.     }
  282.  
  283.     Command[last_entry].command = str;
  284.     Command[last_entry].func = func;
  285.     Command[last_entry].menutype = menu;
  286.     Command[last_entry].arg = intp;
  287.  
  288.     last_entry++;
  289. }
  290.  
  291. /* get_command and readline:  clear the command line, set the 
  292.    command prompt, and get input from the screen.  the input 
  293.    string from the screen is stored in the global string 
  294.    Input_string[20].  This is  the pointer that get_command returns. */
  295.  
  296. static char Input_string[BUFSIZ];
  297. static char Line_Buf[BUFSIZ];
  298.  
  299. #ifdef MSDOS
  300. char *
  301. readline() {
  302.     char *lp = Line_Buf;
  303.     char *rp;
  304.     if (in_stream != stdin) {
  305.         rp = fgets(Line_Buf,BUFSIZ,in_stream);
  306.     }
  307.     else {
  308.     rp = gets(lp);
  309.     rp[strlen(rp)] = '\n';
  310.     }
  311.     return (rp);
  312. }
  313. #else   (if not MSDOS)
  314. char *
  315. readline() {
  316.     int ch;
  317.     char *lp = Line_Buf;
  318.     char * rp;
  319.  
  320.     if (in_stream != stdin) {
  321.         rp = fgets(Line_Buf,BUFSIZ,in_stream);
  322.     }
  323.  
  324.     else {
  325.       rp = Line_Buf;
  326. /*      while ( (ch = getc(in_stream)) != '\n' && ch != EOF) { */
  327.       while ( (ch = getch()) != '\n' && ch != EOF) { 
  328.     if (ch == (char)8 || ch == '\b') {
  329.       if (lp > Line_Buf) {
  330. /*        io_addch((char)127);
  331.         io_addch(' ');
  332.         io_addch((char)127);*/
  333.         io_addch('\b');
  334.         io_refresh();
  335.         lp--;
  336.       }
  337.       continue;
  338.     }
  339.     *lp++ =ch;
  340.     io_addch(ch);
  341.     io_refresh();
  342.       }
  343.       io_addch(' ');
  344.       io_refresh();
  345.       *lp = '\n';
  346.     }
  347.     return(rp);
  348. }
  349. #endif (not MSDOS)
  350.  
  351. char  *
  352. get_command (prompt)
  353. char  *prompt;
  354. {
  355.     static char *lp;
  356.     char *ip = Input_string;
  357.  
  358.     if ( (file_err) || (endline && (in_stream == stdin))) {
  359.     io_move(command_y, command_x);
  360.     io_clrtoeol();
  361.     io_refresh();
  362.     io_move(command_y, command_x);
  363.     io_printw("%s ", prompt);
  364.     io_refresh();
  365.     endline = 1;
  366.     }
  367.     if ( !endline && error_flag && (in_stream == stdin)) {
  368.         /* the line contains an error so the rest is treated
  369.        as garbage */
  370.     endline = 1;
  371.     error_flag = 0;
  372.     return ((char *) NULL);
  373.     }
  374.     
  375.     error_flag = 0;
  376.     
  377.     if (endline) {
  378.         lp = (char *) readline();
  379.     if (lp == (char *) NULL) {
  380.         endline = 1;
  381.         return((char *) NULL);
  382.     }
  383.     else endline = 0;
  384.     }
  385.  
  386.  /* eat all extra spaces */
  387.     while (*lp == ' ' || *lp == '\t') lp++;
  388.     if (*lp == EOF || *lp == '\n') {
  389.     endline = 1;
  390.     return((char *) NULL);
  391.     }
  392.  
  393.     while (*lp != ' ' && *lp != '\t' && *lp != '\n') {
  394.         *ip++ = *lp++;
  395.     }
  396.     *ip = '\0';
  397.     
  398.     while (*lp == ' ' || *lp == '\t') *lp++;
  399.                     /* eat all extra blanks */
  400.  
  401.     if (*lp == '\n') {
  402.     endline = 1;
  403.     }
  404.  
  405.     return(Input_string);
  406. }
  407.  
  408. char subprompt[40];
  409. int intlevel = 0;
  410.  
  411. contin_test() {
  412.     char *str;
  413.     FILE *save_in_stream;
  414.     
  415.     save_in_stream = in_stream;
  416.  
  417.     if (in_stream != stdin) {
  418.     in_stream = stdin;
  419.     }
  420.     endline = 1;
  421. cont_again:
  422.     str = get_command("p to push/b to break/<cr> to continue: ");
  423.     if (str && *str == 'b') {
  424.     in_stream = save_in_stream;
  425.         return(BREAK);
  426.     }
  427.     else if (str && *str == 'p') {
  428.         sprintf(subprompt,"[%d] %s",++intlevel,Prompt);
  429.     while (TRUE) {
  430.             if (do_command(subprompt, (int *) BASEMENU) == POP) break;
  431.     }
  432.     --intlevel;
  433.     goto cont_again;
  434.     }
  435.     in_stream = save_in_stream;
  436. /*  update_display(); */
  437.     return(CONTINUE);
  438. }
  439.  
  440. do_comfile() {
  441.     char *str;
  442.     char savename[BUFSIZ];
  443.     int echeck,i;
  444.     int nreps = 0;
  445.     FILE *save_in_stream,*tmp_stream;
  446.     
  447.     
  448.     str = get_command("command file name: ");
  449.     if (!str) return(CONTINUE);
  450.  
  451.     strcpy(savename,str);
  452.  
  453.     if ( (tmp_stream = fopen(str,"r")) == NULL) {    
  454.             sprintf(err_string,"Cannot open %s.",str);
  455.         return(put_error(err_string));
  456.         }
  457.     echeck = 0;
  458.     if (str) echeck = sscanf(str,"%d",&nreps);
  459.     if (echeck == 0) {
  460.       return(put_error("Integer argument missing in do command."));
  461.     }
  462.     nreps = 1;
  463.     str = get_command("How many times? ");
  464.     echeck = 0;
  465.     if (str) echeck = sscanf(str,"%d",&nreps);
  466.     if (echeck == 0) {
  467.       return(put_error("Integer argument missing in do command."));
  468.     }
  469.     in_stream = tmp_stream;
  470.     for (i = 0; i < nreps; i++) {
  471.       while (!feof(in_stream)) {
  472.         if (do_command(Prompt, (int *) BASEMENU) == BREAK) {
  473.         if (!feof(in_stream)) goto end_do_exec;
  474.         }
  475.       }
  476. #ifdef MSDOS
  477.       if ( (in_stream = freopen(savename,"r",tmp_stream)) == NULL) {
  478.         sprintf(err_string,"Cannot reopen %s.",savename);
  479.         in_stream = save_in_stream;
  480.         return(put_error(err_string));
  481.       }
  482. #else    
  483.       fseek(in_stream,0L,0);
  484. #endif
  485.     }
  486. end_do_exec:
  487.     fclose(in_stream);
  488.     in_stream = save_in_stream;
  489.     return(CONTINUE);
  490. }
  491.  
  492. file_error() {
  493.     FILE *save_in_stream;
  494.     char *str;
  495.     save_in_stream = in_stream;
  496.     in_stream = stdin;
  497.     file_err = 1;
  498. error_again:
  499.     str = get_command("p to push/b to break/<cr> to continue: ");
  500.     if (str && *str == 'b') {
  501.     in_stream = save_in_stream;
  502.     file_err = 0;
  503.         return(BREAK);
  504.     }
  505.     else if (str && *str == 'p') {
  506.         sprintf(subprompt,"[%d] %s",++intlevel,Prompt);
  507.     while (TRUE) {
  508.             if (do_command(subprompt, (int *) BASEMENU) == BREAK) break;
  509.     }
  510.     --intlevel;
  511.     goto error_again;
  512.     }
  513.     in_stream = save_in_stream;
  514.     file_err = 0;
  515.     return(CONTINUE);
  516. }
  517. do_exec() {
  518.     char *str;
  519.     int echeck;
  520.     char tbuf[BUFSIZ];
  521.     
  522.     str = get_command("command: ");
  523.     if (!str) return(CONTINUE);
  524.     strcpy(tbuf, str);
  525.     while ((str = get_command("args: ")) != NULL) {
  526.         if (strcmp(str,"end") == 0) break;
  527.         strcat(tbuf," ");
  528.         strcat(tbuf,str);
  529.     }
  530.     system(tbuf);
  531. }
  532.