home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 10: Diskmags / nf_archive_10.iso / MAGS / ST_USER / 1990 / USERJA90.MSA / CLI_CLI.C < prev    next >
C/C++ Source or Header  |  1989-10-26  |  24KB  |  1,220 lines

  1. /* ==================================================================== */
  2. /*   Nova Command Line Interpreter            V 1.2        */
  3. /* ==================================================================== */
  4.  
  5. /* -------------------------------------------------------------------- */
  6. /*    Mod History                            */
  7. /* -------------------------------------------------------------------- */
  8. /*                                    */
  9. /*    V1.2    i)    Build command tails for Pexec correctly, with    */
  10. /*            count byte at head of string            */
  11. /*        ii)    Fix building of target file name in copy    */
  12. /*            command; no longer includes source drive id    */
  13. /*            as part of new file name            */
  14. /*        iii)    Allow multiple file names on erase command, and    */
  15. /*            don't bother reporting an error if the file    */
  16. /*            isn't there to delete                */
  17. /*                                    */
  18. /* -------------------------------------------------------------------- */
  19.  
  20. #include    "lib\gem.h"
  21. #include    "lib\stdio.h"
  22. #include    "lib\tos.h"
  23.  
  24. #define    CR    13
  25. #define    LF    10
  26.  
  27. char    version[]="1.2";        /* Program version number    */
  28.  
  29. struct     {                /* Terminal input buffer    */
  30.     char    max_length;        /* Maximum no of characters    */
  31.     char    length;            /* Number of characters read    */
  32.     char    in[128];        /* Character buffer        */
  33.     }    input;
  34.  
  35. struct    {                /* Disc transfer address buffer    */
  36.     char    os[21];            /* Gemdos reserved        */
  37.     char    attributes;        /* File attributes        */
  38.     int    timestamp;        /* Time stamp            */
  39.     int    datestamp;        /* Date stamp            */
  40.     long    filesize;        /* Size of file in bytes    */
  41.     char    filename[14];        /* Name.extension of file    */
  42.     }    *dta;
  43.  
  44. char    macros[1024];            /* Macro buffer            */
  45. int    rez;                /* Screen resolution 0,1 or 2    */
  46. char    *arg_ptr[8];            /* Pointers to cmd arguments    */
  47. int    arg_count;            /* Number of arguments        */
  48. int    cmd_length;            /* Length of cmd name string    */
  49. char    output_buffer[64];        /* Console output        */
  50. char    last_file[14];            /* Previous file in generic set */
  51. char    current_path[64];        /* Current access path name    */
  52. char    select[64];            /* Generic file selector    */
  53. char    cmd_image[128];            /* Packed case-shifted command    */
  54. char    current_drive;            /* Current drive id - alpha    */
  55. int    exit_flag;            /* Set to 1 by quit command    */
  56. int    macro_mode;            /* Set to 1 during macro execn    */
  57. int    count;                /* Number of names per line    */
  58. int    max_count=4;            /* Maximum names per line    */
  59.  
  60. char    commands[80]            /* Command string        */
  61.  
  62. int    work_in[12];            /* VDI workspace in        */
  63. int    work_out[57];            /* VDI workspace out        */
  64. int    handle;                /* VDI screen handle        */
  65.  
  66.  
  67. /* ==================================================================== */
  68. /*   Main                                */
  69. /* ==================================================================== */
  70.  
  71. main()  {
  72.  
  73.     char *ptr,*cmd,*tail;
  74.  
  75.     initialise();
  76.  
  77.     while (!exit_flag) {
  78.         get_command_line();
  79.         upshift(input.in);
  80.         execute_command_line(input.in,&ptr,&cmd,&tail);
  81.         }
  82.  
  83.     return 0;
  84.  
  85.     }
  86.  
  87.  
  88. /* -------------------------------------------------------------------- */
  89. /*    Initialise at start of run                    */
  90. /* -------------------------------------------------------------------- */
  91.  
  92. initialise() {
  93.  
  94.     char *x;
  95.     int n;
  96.  
  97.     for (n=0; n<10; work_in[n++]=1); work_in[10]=2;
  98.  
  99.     v_opnvwk(work_in,&handle,work_out);
  100.     v_hide_c(handle);
  101.     v_clrwk(handle);
  102.     v_enter_cur(handle);
  103.     v_curhome(handle);
  104.  
  105.     c_conws("----------------------------------------");
  106.     c_conws("----------------------------------------"); newline();
  107.     c_conws("  NOVA -- Version "); c_conws(version); newline();
  108.     c_conws("----------------------------------------");
  109.     c_conws("----------------------------------------");
  110.  
  111.     newline(); newline(); newline();
  112.  
  113.     if ((trap(14,23)&0xffffL)==0L)
  114.         set_time();
  115.  
  116.     exit_flag = 0;  macro_mode = 0;
  117.  
  118.     current_drive = (char)d_getdrv() + 65;
  119.     d_getpath(current_path,0);
  120.  
  121.     dta=f_getdta();
  122.  
  123.     max_count = (rez=getrez()) ? 4 : 2;
  124.  
  125.     move_string("COPY:DIRECTORY:ERASE:HELP:KILL:MAKE:",commands);
  126.     extd_string("PATH:QUIT:RENAME:STATUS:TIME:XECUTE:",commands);
  127.     x = commands;
  128.     while (*x) {
  129.         if (*x==':')
  130.             *x='\0';
  131.         x++;
  132.         }
  133.  
  134.     load_macros();
  135.  
  136.     }
  137.  
  138.  
  139. /* -------------------------------------------------------------------- */
  140. /*    Load macro file (if it's there!)                */
  141. /* -------------------------------------------------------------------- */
  142.  
  143. load_macros() {
  144.  
  145.     char *buffer;
  146.     char *i,*j,*k;
  147.     long size;
  148.  
  149.     if (load_file("NOVA\\MACROS",&buffer,&size)<0) {
  150.         c_conws("Macros not loaded"); newline();
  151.         return;
  152.         }
  153.  
  154.     i = buffer; j = macros;
  155.  
  156.     while (*i!='#') i++;
  157.  
  158.     while (*i!='@') {
  159.         k = j; *k = 1; i++; j++;
  160.         while (*i!='#' && *i!='@') {
  161.             if (*i!=CR) {
  162.                 *j = (*i==LF) ? 0 : *i;
  163.                 j++; (*k)++;
  164.                 }
  165.             i++;
  166.             }
  167.         *j++ = 0; (*k)++;
  168.         }
  169.  
  170.     *j=0;
  171.  
  172.     m_free(buffer);
  173.  
  174.     }
  175.  
  176.  
  177. /* -------------------------------------------------------------------- */
  178. /*    Issue prompt and get response                    */
  179. /* -------------------------------------------------------------------- */
  180.     
  181. get_command_line() {
  182.  
  183.     newline();
  184.     output_buffer[0] = current_drive;
  185.     output_buffer[1] = 175;
  186.     output_buffer[2] = 32;
  187.     output_buffer[3] = '\0';
  188.  
  189.     c_conws(output_buffer);
  190.  
  191.     input.max_length = 128;  input.length = 0;  input.in[0] = '\0';
  192.  
  193.     c_conrs(&input);
  194.  
  195.     input.in[input.length] = '\0';
  196.  
  197.     newline();
  198.  
  199.     }
  200.  
  201.  
  202. /* -------------------------------------------------------------------- */
  203. /*    Execute keyboard or macro command line                */
  204. /* -------------------------------------------------------------------- */
  205.  
  206. execute_command_line(line,ptr,cmd,tail) char *line,**ptr,**cmd,**tail; {
  207.  
  208.     *ptr = line;
  209.  
  210.     while (parse(ptr,cmd,tail)) {
  211.         if (!check_for_macro(*cmd,*tail)) {
  212.             if (!execute_internal(*cmd,*tail)) {
  213.                 execute_external(*cmd,*tail);
  214.                 }
  215.             }
  216.         }
  217.     }
  218.  
  219.  
  220. /* -------------------------------------------------------------------- */
  221. /*    Parse command line returning command/tail pointers        */
  222. /* -------------------------------------------------------------------- */
  223.  
  224. parse(ptr,cmd,tail) char **ptr,**cmd,**tail; {
  225.  
  226.     char *x;
  227.  
  228.     x=*ptr; cmd_length=0;
  229.     while (*x==' ') x++;
  230.     if (*x=='\0') return 0;
  231.     *cmd = x; *tail = NULL;
  232.     while (*x && !one_of(" ;\r",*x)) { cmd_length++; x++; }
  233.     if (*x=='\0' || *x=='\r') {*ptr=x; return 1; }
  234.     if (*x==';')  {*x='\0'; *ptr=x+1; return 1; }
  235.     *x++='\0';
  236.     while (*x==' ') x++;
  237.     *tail=x;
  238.     while (*x && *x!=';') x++;
  239.     if (*x=='\0') {*ptr=x; return 1; }
  240.     *x='\0'; *ptr=x+1; return 1;
  241.  
  242.     }
  243.  
  244.  
  245. /* -------------------------------------------------------------------- */
  246. /*    Check whether entered command is a macro            */
  247. /* -------------------------------------------------------------------- */
  248.  
  249. check_for_macro(cmd,tail) char *cmd,*tail; {
  250.  
  251.     char *m;
  252.  
  253.     if (macro_mode) return 0;
  254.  
  255.     m = macros;
  256.  
  257.     while (*m) {
  258.         if (comp_string(cmd,m+1)) {
  259.             macro_mode = 1;    
  260.             execute_macro(m+1,tail);
  261.             macro_mode = 0;
  262.             return 1;
  263.             }
  264.         m = m+*m;
  265.         }
  266.  
  267.     return 0;
  268.  
  269.     }
  270.  
  271.  
  272. /* -------------------------------------------------------------------- */
  273. /*    Execute a macro command                        */
  274. /* -------------------------------------------------------------------- */
  275.  
  276. execute_macro(m,tail) char *m,*tail; {
  277.  
  278.     char *x,*ptr,*cmd,*arg;
  279.  
  280.     x = m;  while(*x) x++; x++;
  281.  
  282.     extract_parameters(tail);
  283.  
  284.     while (*x) {
  285.         expand_line(&x);
  286.         execute_command_line(cmd_image,&ptr,&cmd,&arg);
  287.         }
  288.  
  289.     }
  290.  
  291.  
  292. /* -------------------------------------------------------------------- */
  293. /*    Set up pointers to macro parameters                */
  294. /* -------------------------------------------------------------------- */
  295.  
  296. extract_parameters(tail) char *tail; {
  297.  
  298.     char *x;
  299.  
  300.     for (arg_count=0; arg_count<8; arg_count++)
  301.         arg_ptr[arg_count] = NULL;
  302.  
  303.     arg_count = 0; x = tail;
  304.  
  305.     if (x==NULL)
  306.         return;
  307.  
  308.     while (*x) {
  309.         arg_ptr[arg_count++] = x;
  310.         if (arg_count<8) {
  311.             while (*x && *x!=' ') x++;
  312.             while (*x == ' ') x++;
  313.             }
  314.         else {
  315.             c_conws("Too many arguments");
  316.             newline();
  317.             x="";
  318.             }
  319.         }
  320.  
  321.     }
  322.  
  323.  
  324. /* -------------------------------------------------------------------- */
  325. /*    Expand macro line inserting parameters                */
  326. /* -------------------------------------------------------------------- */
  327.  
  328. expand_line(m) char **m; {
  329.  
  330.     char *x,*y,*z;
  331.  
  332.     x = *m; y = cmd_image;
  333.  
  334.     while (*x) {
  335.         while (*x && *x!='%') *y++ = *x++;
  336.         if (*x) {
  337.             z = arg_ptr[(int)(*(++x)-49)];
  338.             if (z!=NULL)
  339.                 while (*z && *z!=' ') *y++ = *z++;
  340.             x++;
  341.             }
  342.         }
  343.     *y = 0;
  344.     *m = ++x;
  345.  
  346.     }
  347.  
  348.  
  349. /* -------------------------------------------------------------------- */
  350. /*    Execute an internal command                    */
  351. /* -------------------------------------------------------------------- */
  352.     
  353. execute_internal(cmd,tail) char *cmd,*tail; {
  354.  
  355.     if (cmd_length==2 && *(cmd+1)==':' && tail==NULL) {
  356.         change_drive(*cmd);
  357.         return 1;
  358.         }
  359.  
  360.     switch (decode_command(cmd)) {
  361.  
  362.         case 'C':    copy_file(tail);
  363.                 return 1;
  364.         case 'D':    list_directory(tail);
  365.                 return 1;
  366.         case 'E':    delete_file(tail);
  367.                 return 1;
  368.         case 'H':    display_help();
  369.                 return 1;
  370.         case 'K':    kill_directory(tail);
  371.                 return 1;
  372.         case 'M':    create_directory(tail);
  373.                 return 1;
  374.         case 'P':    set_default_path(tail);
  375.                 return 1;
  376.         case 'Q':    setup_exit();
  377.                 return 1;
  378.         case 'R':    rename_file(tail);
  379.                 return 1;
  380.         case 'S':    show_status();
  381.                 return 1;
  382.         case 'T':    set_time();
  383.                 return 1;
  384.         case 'X':    execute_program(tail);
  385.                 return 1;
  386.         
  387.         }
  388.  
  389.     return 0;
  390.  
  391.     }
  392.  
  393.  
  394. /* -------------------------------------------------------------------- */
  395. /*    Reduce command to single letter if internal            */
  396. /* -------------------------------------------------------------------- */
  397.  
  398. char * decode_command(cmd) char *cmd; {
  399.  
  400.     char *x,*y,*z;
  401.  
  402.     if (cmd_length==1)
  403.         return (*cmd);
  404.  
  405.     x=commands;
  406.  
  407.     while (*x) {
  408.         y=x; z=cmd;
  409.         while (*z && *z==*y) {
  410.             y++; z++;
  411.             }
  412.         if (!*z)
  413.             return (*cmd);
  414.         while (*x) x++;
  415.         x++;
  416.         }
  417.  
  418.     return ('\0');
  419.  
  420.     }
  421.  
  422.  
  423. /* -------------------------------------------------------------------- */
  424. /*    Display standard format error message                */
  425. /* -------------------------------------------------------------------- */
  426.  
  427. error(message) char *message; {
  428.  
  429.     newline();
  430.  
  431.     move_string("*!*---\?  ",output_buffer);
  432.     char_string(7,output_buffer);
  433.     extd_string(message,output_buffer);
  434.     char_string(7,output_buffer);
  435.  
  436.     c_conws(output_buffer); newline();
  437.  
  438.     }
  439.  
  440.  
  441. /* -------------------------------------------------------------------- */
  442. /*    Change current drive                        */
  443. /* -------------------------------------------------------------------- */
  444.  
  445. change_drive(x) char x; {
  446.  
  447.     if (!range(x,'A','P')) {
  448.         error("Drive identifier out of range");
  449.         return;
  450.         }
  451.  
  452.     d_setdrv((int)x-65);
  453.     current_drive = (char)d_getdrv()+65;
  454.     d_getpath(current_path,0);
  455.     
  456.     }
  457.  
  458.  
  459. /* -------------------------------------------------------------------- */
  460. /*    Copy command                            */
  461. /* -------------------------------------------------------------------- */
  462.  
  463. copy_file(tail) char *tail; {
  464.  
  465.     char *x,*buffer;
  466.     long size;
  467.     int  flag;
  468.  
  469.     x=tail; unpack(&x);
  470.  
  471.     if (flag=load_file(tail,&buffer,&size)) {
  472.         switch (flag) {
  473.             case -1: error("No such file");
  474.                  break;
  475.             case -2: error("Insufficient memory");
  476.                  break;
  477.             case -3: error("Error reading file");
  478.                  break;
  479.             }
  480.         return;
  481.         }
  482.  
  483.     move_string(x,output_buffer);
  484.  
  485.     if (length(x)==2 && *(x+1)==':')
  486.         if (*(tail+1)==':')
  487.             extd_string(tail+2,output_buffer);
  488.         else
  489.             extd_string(tail,output_buffer);
  490.  
  491.     if (flag=save_file(output_buffer,&buffer,&size)) {
  492.         switch (flag) {
  493.             case -1: error("Unable to create file");
  494.                  break;
  495.             case -2: error("Error writing file");
  496.                  break;
  497.             }
  498.         }
  499.  
  500.     }
  501.  
  502.  
  503. /* -------------------------------------------------------------------- */
  504. /*    Exit command                            */
  505. /* -------------------------------------------------------------------- */
  506.  
  507. setup_exit() {
  508.  
  509.     v_exit_cur(handle); v_show_c(handle,0); v_clsvwk(handle);
  510.  
  511.     exit_flag = 1;
  512.  
  513.     }
  514.  
  515.  
  516. /* -------------------------------------------------------------------- */
  517. /*    Directory command                        */
  518. /* -------------------------------------------------------------------- */
  519.  
  520. list_directory(tail) char *tail; {
  521.  
  522.     int i;
  523.     char *c;
  524.  
  525.     if (tail!=NULL)
  526.         move_string(tail,select);
  527.     else
  528.         move_string("*.*",select);
  529.  
  530.     if (f_sfirst(select,0x10)<0)
  531.         return;
  532.  
  533.     last_file[0] = '\0';  count=0;  newline();
  534.  
  535.     while (!same_name()) {
  536.         display_file();
  537.         f_snext();
  538.         }
  539.  
  540.     newline();
  541.  
  542.     }
  543.  
  544.  
  545. same_name() {
  546.     int i;
  547.  
  548.     i=0;
  549.     while (dta->filename[i]!=0 && dta->filename[i]==last_file[i]) i++;
  550.     return (dta->filename[i]==last_file[i]? 1 : 0);
  551.     }
  552.  
  553.  
  554. display_file() {
  555.     int i,j,k,z;
  556.  
  557.     i = j = k = 0;
  558.  
  559.     z = rez ? 13 : 12;
  560.  
  561.     while ((last_file[j]=dta->filename[i++])!='\0') {
  562.         if (last_file[j]=='.') {
  563.             while (k<8) output_buffer[k++]=' ';
  564.             }
  565.         output_buffer[k++]=last_file[j++];
  566.         }
  567.  
  568.     while (k<z) output_buffer[k++]=' ';
  569.  
  570.     output_buffer[z] = '\0';
  571.  
  572.     if (count>max_count) {
  573.         count=0;
  574.         newline();
  575.         }
  576.  
  577.     count++;
  578.  
  579.     if (dta->attributes==0x10)
  580.         if (rez==2)
  581.             v_rvon(handle);
  582.         else
  583.             colour_text(1);
  584.  
  585.     c_conws(output_buffer);
  586.  
  587.     if (dta->attributes==0x10)
  588.         if (rez==2)
  589.             v_rvoff(handle);
  590.         else
  591.             colour_text(15);
  592.  
  593.     if (rez)
  594.         c_conws("  ");
  595.     else
  596.         c_conws(" ");
  597.  
  598.     }
  599.  
  600.  
  601. colour_text(c) {
  602.  
  603.     char x[4];
  604.  
  605.     x[0]=27; x[1]='b'; x[2]=(char)c; x[3]=0; c_conws(x);
  606.  
  607.     }
  608.  
  609.  
  610. /* -------------------------------------------------------------------- */
  611. /*    Make command                            */
  612. /* -------------------------------------------------------------------- */
  613.  
  614. create_directory(tail) char *tail; {
  615.  
  616.     if (tail==NULL)
  617.         error("Directory name?");
  618.     else
  619.         if (d_create(tail)<0)
  620.             error("Invalid directory specification");
  621.  
  622.     }
  623.  
  624.  
  625. /* -------------------------------------------------------------------- */
  626. /*    Kill command                            */
  627. /* -------------------------------------------------------------------- */
  628.  
  629. kill_directory(tail) char *tail; {
  630.  
  631.     if (tail==NULL)
  632.         error("Directory name?");
  633.     else
  634.         if (d_delete(tail)<0)
  635.             error("Invalid directory specification");
  636.  
  637.     }
  638.  
  639.  
  640. /* -------------------------------------------------------------------- */
  641. /*    Help command                            */
  642. /* -------------------------------------------------------------------- */
  643.  
  644. display_help() {
  645.  
  646.     char *i,*j,*k;
  647.     int c,l;
  648.  
  649.     newline();
  650.     newline(); c_conws("Commands:-"); newline(); newline();
  651.  
  652.     i=commands; l=4;
  653.  
  654.     while (*i) {
  655.         j=output_buffer; c=0;
  656.         while (*i) {
  657.             *j++=*i++; c++;
  658.             }
  659.         if (l>1)
  660.             while (c++<10) *j++=' ';
  661.         *j='\0';
  662.         c_conws(output_buffer);
  663.         if (!--l) {
  664.             l=4; newline();
  665.             }
  666.         i++;
  667.         }
  668.     newline();
  669.  
  670.     if (macros[0]==0) return;
  671.  
  672.     newline(); c_conws("Macros:-"); newline(); newline();
  673.  
  674.     i=macros; l=4;
  675.  
  676.     while (*i) {
  677.         j = i+1; k=output_buffer; c=0;
  678.         while (*j) {
  679.             *k++=*j++; c++;
  680.             }
  681.         if (l>1)
  682.             while (c++<10) *k++=' ';
  683.         *k='\0';
  684.         c_conws(output_buffer);
  685.         if (!--l) {
  686.             l=4; newline();
  687.             }
  688.         i = (i+*i);
  689.         }
  690.  
  691.     newline();
  692.  
  693.     }
  694.  
  695.  
  696. /* -------------------------------------------------------------------- */
  697. /*    Path command                            */
  698. /* -------------------------------------------------------------------- */
  699.  
  700. set_default_path(tail) char *tail; {
  701.     
  702.     if (tail==NULL)
  703.         move_string("..",current_path);
  704.     else
  705.         move_string(tail,current_path);
  706.  
  707.     move_string("*.*",select);
  708.  
  709.     if (d_setpath(current_path)<0)
  710.         error("Unable to set requested path");
  711.     if (d_getpath(current_path,0)<0)
  712.         error("Unable to get path");
  713.  
  714.     }
  715.  
  716.  
  717. /* -------------------------------------------------------------------- */
  718. /*    Rename command                            */
  719. /* -------------------------------------------------------------------- */
  720.  
  721. rename_file(tail) char *tail; {
  722.  
  723.     char *p;
  724.     
  725.     if (tail==NULL) {
  726.         error("File name missing");
  727.         return;
  728.         }
  729.  
  730.     p=tail; while (*p!=' ') p++; *p++='\0';
  731.     while (*p==' ') p++;
  732.  
  733.     if (*p=='\0') {
  734.         error("New name missing");
  735.         return;
  736.         }
  737.  
  738.     if (f_rename(0,tail,p)) error("Command rejected");
  739.  
  740.     }
  741.  
  742.  
  743. /* -------------------------------------------------------------------- */
  744. /*    Time command                            */
  745. /* -------------------------------------------------------------------- */
  746.  
  747. set_time() {
  748.  
  749.     int  date,time;
  750.  
  751.     get_current_time(&date,&time);
  752.  
  753.     get_time(&time);
  754.     get_date(&date);
  755.  
  756.     newline();
  757.  
  758.     settime(((date<<16)|time));
  759.  
  760.     t_settime(time);
  761.     t_setdate(date);
  762.  
  763.     }
  764.  
  765.  
  766. get_current_time(d,t) int *d,*t; {
  767.  
  768.     long current;
  769.  
  770.     current = gettime();
  771.  
  772.     *t = (int) (current & 0xffff);
  773.     *d = (int) ((current>>16) & 0xffff);
  774.  
  775.     }
  776.  
  777.  
  778. get_time(t) int *t; {
  779.  
  780.     int h,m;
  781.  
  782.     struct {
  783.         char    ml;
  784.         char    l;
  785.         char    x[8];
  786.     }        buf;
  787.  
  788.     newline();
  789.  
  790.     m = (*t>>5)  & 0x3f;
  791.     h = (*t>>11) & 0x1f;
  792.  
  793.     output_buffer[0] = (h/10)+48;
  794.     output_buffer[1] = (h%10)+48;
  795.     output_buffer[2] = ':';
  796.     output_buffer[3] = (m/10)+48;
  797.     output_buffer[4] = (m%10)+48;
  798.     output_buffer[5] = 0;
  799.  
  800.     c_conws("    Time: "); c_conws(output_buffer); c_conws("     ");
  801.  
  802.     buf.ml=8; buf.l=0; c_conrs(&buf);
  803.  
  804.     if (buf.l!=4)
  805.         return;
  806.  
  807.     h = (buf.x[0]-48)*10+(buf.x[1]-48);
  808.     m = (buf.x[2]-48)*10+(buf.x[3]-48);
  809.  
  810.     *t= ((h<<6)|m)<<5;
  811.  
  812.     }
  813.  
  814.  
  815. get_date(t) int *t; {
  816.  
  817.     int d,m,y;
  818.  
  819.     struct {
  820.         char    ml;
  821.         char    l;
  822.         char    x[8];
  823.     }        buf;
  824.  
  825.     newline();
  826.  
  827.     d = *t & 0x1f;
  828.     m = (*t>>5) & 0xf;
  829.     y = (d) ? (((*t>>9) & 0x7f) + 80) : 0;
  830.  
  831.     output_buffer[0] = (d/10)+48;
  832.     output_buffer[1] = (d%10)+48;
  833.     output_buffer[2] = '.';
  834.     output_buffer[3] = (m/10)+48;
  835.     output_buffer[4] = (m%10)+48;
  836.     output_buffer[5] = '.';
  837.     output_buffer[6] = (y/10)+48;
  838.     output_buffer[7] = (y%10)+48;
  839.     output_buffer[8] = 0;
  840.  
  841.     c_conws("    Date: "); c_conws(output_buffer); c_conws("  ");
  842.  
  843.     buf.ml=8; buf.l=0; c_conrs(&buf);
  844.  
  845.     if (buf.l!=6)
  846.         return;
  847.  
  848.     d = (buf.x[0]-48)*10+(buf.x[1]-48);
  849.     m = (buf.x[2]-48)*10+(buf.x[3]-48);
  850.     y = (buf.x[4]-48)*10+(buf.x[5]-48);
  851.  
  852.     *t= ((((y-80)<<4)|m)<<5)|d;
  853.  
  854.     }
  855.     
  856.     
  857. /* -------------------------------------------------------------------- */
  858. /*    Status command                            */
  859. /* -------------------------------------------------------------------- */
  860.  
  861. show_status() {
  862.  
  863.     char    string[8];
  864.     long    memory,
  865.         factor,
  866.         free_space,
  867.         used_space;
  868.     char    *s;
  869.  
  870.     struct {
  871.         long    free_clusters;
  872.         long    total_clusters;
  873.         long    bytes_per_sector;
  874.         long    sectors_per_cluster;
  875.     }        info;
  876.  
  877.     newline();
  878.  
  879.     memory=(long)trap(1,72,-1L); s=&string[7]; *s=0;
  880.  
  881.     d_free(&info,0);
  882.  
  883.     factor = info.sectors_per_cluster * info.bytes_per_sector;
  884.     free_space = factor * info.free_clusters;
  885.     used_space = factor * info.total_clusters - free_space;
  886.  
  887.     string[0]=current_drive; string[1]=string[2]=' ';
  888.     string[3]=':'; string[4]=string[5]=' '; string[6]=0;
  889.  
  890.     c_conws("  Path...... "); c_conws(string); c_conws(current_path);
  891.  
  892.     newline(); newline();
  893.  
  894.     convert(memory,string,&s);
  895.     c_conws("  Memory.... "); c_conws(s);
  896.  
  897.     newline(); newline();
  898.  
  899.     convert(used_space,string,&s);
  900.     c_conws("  Bytes used "); c_conws(s);
  901.  
  902.     convert(free_space,string,&s);
  903.     c_conws("  Free space "); c_conws(s);
  904.  
  905.     newline();
  906.     
  907.     }
  908.  
  909.  
  910. /* -------------------------------------------------------------------- */
  911. /*    Erase command                            */
  912. /* -------------------------------------------------------------------- */
  913.  
  914. delete_file(tail) char *tail; {
  915.  
  916.     char *x,*y;
  917.  
  918.     if (tail==NULL) {
  919.         error("Argument missing");
  920.         return;
  921.         }
  922.  
  923.     x=tail;
  924.  
  925.     while (*x) {
  926.         y=x;
  927.         unpack(&x);
  928.         f_delete(y);
  929.         }
  930.  
  931.     }
  932.  
  933.  
  934. /* -------------------------------------------------------------------- */
  935. /*    Xecute command                            */
  936. /* -------------------------------------------------------------------- */
  937.  
  938. execute_program(tail) char *tail; {
  939.  
  940.     char *p;
  941.  
  942.     p=tail;
  943.     while (*p && *p!=' ') p++;
  944.     if (*p==' ') *p++=0;
  945.     while (*p==' ') p++;
  946.  
  947.     execute_external(tail,p);
  948.  
  949.     }
  950.  
  951.  
  952. /* -------------------------------------------------------------------- */
  953. /*    Execute external program                    */
  954. /* -------------------------------------------------------------------- */
  955.  
  956. execute_external(cmd,tail) char *cmd,*tail; {
  957.  
  958.     int i,program_type;
  959.     char *x,*y;
  960.  
  961.     move_string(cmd,select);
  962.  
  963.     x=select; i=1;
  964.  
  965.     while (*x) {
  966.         if (*x=='.') {
  967.             i=0;
  968.             break;
  969.             }
  970.         x++;
  971.         }
  972.  
  973.     if (i)
  974.         extd_string(".*",select);
  975.  
  976.     dta->filename[0]=0;
  977.  
  978.     if (f_sfirst(select,0)<0) {
  979.         error("Unrecognised command");
  980.         return;
  981.         }
  982.  
  983.     last_file[0] = '\0';
  984.  
  985.     while (!(program_type=executable())) {
  986.         f_snext();
  987.         if (same_name()) {
  988.             error("Unrecognised command");
  989.             return;
  990.             }
  991.         for (i=0; (last_file[i]=dta->filename[i]); i++);
  992.         }
  993.  
  994.     x=y=select;
  995.  
  996.     while (*x) {
  997.         if (*x=='\\')
  998.             y=x+1;
  999.         x++;
  1000.         }
  1001.  
  1002.     move_string(dta->filename,y);
  1003.  
  1004.     if (tail==NULL) {
  1005.         output_buffer[0]=output_buffer[1]=0;
  1006.         }
  1007.     else {
  1008.         output_buffer[0]=(char)(length(tail));
  1009.         move_string(tail,output_buffer+1);
  1010.         }
  1011.  
  1012.     if (program_type==1) {
  1013.         v_exit_cur(handle);
  1014.         v_clrwk(handle);
  1015.         v_show_c(handle,0);
  1016.         }
  1017.  
  1018.     if (p_exec(0,select,output_buffer,0L)==0xd9L)
  1019.         error("Insufficient memory");
  1020.  
  1021.     if (program_type==1) {
  1022.         v_hide_c(handle);
  1023.         v_clrwk(handle);
  1024.         v_enter_cur(handle);
  1025.         v_curhome(handle);
  1026.         }
  1027.  
  1028.     }
  1029.  
  1030.  
  1031. /* -------------------------------------------------------------------- */
  1032. /*    Check file extension to see whether its executable        */
  1033. /* -------------------------------------------------------------------- */
  1034.  
  1035. executable() {
  1036.  
  1037.     char *p;
  1038.  
  1039.     p = dta->filename;
  1040.  
  1041.     while (*p && *p!='.') p++;
  1042.  
  1043.     if (!*p)
  1044.         return 0;
  1045.  
  1046.     if (comp_string(p,".PRG")) return 1;
  1047.     if (comp_string(p,".TOS")) return 2;
  1048.     if (comp_string(p,".TTP")) return 2;
  1049.  
  1050.     return 0;
  1051.  
  1052.     }
  1053.  
  1054.  
  1055. /* ******************************************************************** */
  1056. /*    Subroutines                            */
  1057. /* ******************************************************************** */
  1058.  
  1059. newline() {
  1060.     char string[3];
  1061.  
  1062.     string[0]=13; string[1]=10; string[2]=0;
  1063.     c_conws(string);
  1064.     }
  1065.  
  1066.  
  1067. move_string(from,to) char *from,*to; {
  1068.  
  1069.     while (*to++=*from++);
  1070.  
  1071.     }
  1072.  
  1073.  
  1074. extd_string(from,to) char *from,*to; {
  1075.  
  1076.     while (*to) to++;
  1077.     while (*to++=*from++);
  1078.  
  1079.     }
  1080.  
  1081.  
  1082. char_string(c,s) char c,*s; {
  1083.  
  1084.     while (*s) s++;
  1085.     *s++=c; *s++=0;
  1086.  
  1087.     }
  1088.  
  1089.  
  1090. comp_string(s1,s2) char *s1,*s2; {
  1091.  
  1092.     while (*s1 && (*s1==*s2)) { s1++; s2++; }
  1093.  
  1094.     if (*s1==*s2)
  1095.         return 1;
  1096.     else
  1097.         return 0;
  1098.  
  1099.     }
  1100.  
  1101.  
  1102. one_of(s1,s2) char *s1,s2; {
  1103.  
  1104.     while (*s1) if (*s1++==s2) return 1;
  1105.     return 0;
  1106.  
  1107.     }
  1108.  
  1109.  
  1110. range(s1,s2,s3) char s1,s2,s3; {
  1111.  
  1112.     return ((s1<s2)||(s1>s3)?0:1);
  1113.  
  1114.     }
  1115.  
  1116.  
  1117. upshift(s) char *s; {
  1118.  
  1119.     while (*s) {
  1120.         if (range(*s,'a','z')) *s-=32;
  1121.         s++;
  1122.         }
  1123.     }
  1124.  
  1125.  
  1126. convert(n,s,p) long n; char *s,**p; {
  1127.  
  1128.     char *x;
  1129.  
  1130.     x = s+7; *x = 0;
  1131.  
  1132.     while (n) {
  1133.         *(--x) = (char) (n%10+48); n/=10;
  1134.         }
  1135.  
  1136.     *p = x;
  1137.  
  1138.     }
  1139.  
  1140.  
  1141. unpack(s) char **s; {
  1142.  
  1143.     char *t;
  1144.  
  1145.     t=*s;
  1146.  
  1147.     while (*t && *t!=' ') t++;
  1148.  
  1149.     if (*t) {
  1150.         *t=0; t++;
  1151.         }
  1152.  
  1153.     if (*t==' ') t++;
  1154.  
  1155.     *s=t;
  1156.  
  1157.     }
  1158.  
  1159.  
  1160. length(s) char *s; {
  1161.  
  1162.     int n;
  1163.  
  1164.     n=0; while (*s++) n++;
  1165.  
  1166.     return n;
  1167.  
  1168.     }
  1169.  
  1170.  
  1171. /* -------------------------------------------------------------------- */
  1172. /*    File handling                            */
  1173. /* -------------------------------------------------------------------- */
  1174.  
  1175. load_file(path,buf,size) char *path,**buf; long *size; {
  1176.  
  1177.     int  file_handle;
  1178.     long count;
  1179.     char *buffer;
  1180.  
  1181.     if ((file_handle=(int)f_open(path,0))<0)
  1182.         return -1;
  1183.  
  1184.     f_sfirst(path,0); count=dta->filesize;
  1185.  
  1186.     buffer=m_alloc(count);
  1187.  
  1188.     if (buffer==NULL)
  1189.         return -2;
  1190.  
  1191.     *size=f_read(file_handle,count,buffer);
  1192.  
  1193.     if (*size<0)
  1194.         return -3;
  1195.  
  1196.     f_close(file_handle);
  1197.  
  1198.     *buf=buffer;
  1199.  
  1200.     return 0;
  1201.  
  1202.     }
  1203.  
  1204.  
  1205. save_file(path,buf,size) char *path,**buf; long *size; {
  1206.  
  1207.     int  file_handle;
  1208.  
  1209.     if ((file_handle=f_create(path,0))<0) 
  1210.         return -1;
  1211.  
  1212.     if (f_write(file_handle,*size,*buf)!=*size)
  1213.         return -2;
  1214.  
  1215.     f_close(file_handle);
  1216.  
  1217.     m_free(*buf);
  1218.  
  1219.     }
  1220.