home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / SH162_2S.ZIP / SH10.C < prev    next >
C/C++ Source or Header  |  1990-08-03  |  12KB  |  631 lines

  1. /* MS-DOS SHELL - Function Processing
  2.  *
  3.  * MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
  4.  *
  5.  * This code is subject to the following copyright restrictions:
  6.  *
  7.  * 1.  Redistribution and use in source and binary forms are permitted
  8.  *     provided that the above copyright notice is duplicated in the
  9.  *     source form and the copyright notice in file sh6.c is displayed
  10.  *     on entry to the program.
  11.  *
  12.  * 2.  The sources (or parts thereof) or objects generated from the sources
  13.  *     (or parts of sources) cannot be sold under any circumstances.
  14.  *
  15.  *    $Header: sh10.c 1.3 90/05/31 09:51:06 MS_user Exp $
  16.  *
  17.  *    $Log:    sh10.c $
  18.  * Revision 1.3  90/05/31  09:51:06  MS_user
  19.  * Add some signal lockouts to prevent corruption
  20.  *
  21.  * Revision 1.2  90/04/25  22:34:04  MS_user
  22.  * Fix case in TELIF where then and else parts are not defined
  23.  *
  24.  * Revision 1.1  90/01/25  13:40:54  MS_user
  25.  * Initial revision
  26.  *
  27.  */
  28.  
  29. #include <sys/types.h>
  30. #include <sys/stat.h>
  31. #include <stdio.h>
  32. #include <process.h>
  33. #include <signal.h>
  34. #include <errno.h>
  35. #include <setjmp.h>
  36. #include <ctype.h>
  37. #include <string.h>
  38. #include <unistd.h>
  39. #include <stdlib.h>
  40. #include <fcntl.h>
  41. #include <limits.h>
  42. #include "sh.h"
  43.  
  44. /* Function declarations */
  45.  
  46. static void    Print_Command (C_Op *);
  47. static void    Print_IO (IO_Actions *);
  48. static void    Print_Case (C_Op *);
  49. static void    Print_IString (char *, int);
  50. static void    Set_Free_ExTree (C_Op *, void (*)(char *));
  51. static void    Set_Free_Command (C_Op *, void (*)(char *));
  52. static void    Set_Free_Case (C_Op *, void (*)(char *));
  53. static void    Set_ExTree (char *);
  54. static void    Free_ExTree (char *);
  55.  
  56. static int    Print_indent;            /* Current indent level    */
  57.  
  58. /*
  59.  * print the execute tree - used for displaying functions
  60.  */
  61.  
  62. void        Print_ExTree (t)
  63. register C_Op    *t;
  64. {
  65.     char        **wp;
  66.  
  67.     if (t == (C_Op *)NULL)
  68.     return;
  69.  
  70. /* Check for start of print */
  71.  
  72.     if (t->type == TFUNC)
  73.     {
  74.     Print_indent = 0;
  75.     v1_puts (*t->words);
  76.     v1a_puts (" ()");
  77.     Print_ExTree (t->left);
  78.     return;
  79.     }
  80.  
  81. /* Otherwise, process the tree and print it */
  82.  
  83.     switch (t->type)
  84.     {
  85.     case TPAREN:            /* ()            */
  86.     case TCOM:            /* A command process    */
  87.         Print_Command (t);
  88.         return;
  89.  
  90.     case TPIPE:            /* Pipe processing        */
  91.         Print_ExTree (t->left);
  92.         Print_IString ("|\n", 0);
  93.         Print_ExTree (t->right);
  94.         return;
  95.  
  96.     case TLIST:            /* Entries in a for statement    */
  97.         Print_ExTree (t->left);
  98.         Print_ExTree (t->right);
  99.         return;
  100.  
  101.     case TOR:            /* || and &&            */
  102.     case TAND:
  103.         Print_ExTree (t->left);
  104.  
  105.         if (t->right != (C_Op *)NULL)
  106.         {
  107.         Print_IString ((t->type == TAND) ? "&&\n" : "||\n", 0);
  108.         Print_ExTree (t->right);
  109.         }
  110.  
  111.         return;
  112.  
  113.     case TFOR:            /* First part of a for statement*/
  114.         Print_IString ("for ", 0);
  115.         v1_puts (t->str);
  116.  
  117.         if ((wp = t->words) != (char **)NULL)
  118.         {
  119.         v1_puts (" in");
  120.  
  121.         while (*wp != (char *)NULL)
  122.         {
  123.             v1_putc (SP);
  124.             v1_puts (*wp++);
  125.         }
  126.         }
  127.  
  128.         v1_putc (NL);
  129.         Print_IString ("do\n", 1);
  130.         Print_ExTree (t->left);
  131.         Print_IString ("done\n", -1);
  132.         return;
  133.  
  134.     case TWHILE:            /* WHILE and UNTIL functions    */
  135.     case TUNTIL:
  136.         Print_IString ((t->type == TWHILE) ? "while " : "until ", 1);
  137.         Print_ExTree (t->left);
  138.         Print_IString ("do\n", 0);
  139.         Print_ExTree (t->right);
  140.         Print_IString ("done\n", -1);
  141.         return;
  142.  
  143.     case TIF:            /* IF and ELSE IF functions    */
  144.     case TELIF:
  145.         if (t->type == TIF)
  146.         Print_IString ("if\n", 1);
  147.  
  148.         else
  149.         Print_IString ("elif\n", 1);
  150.  
  151.         Print_ExTree (t->left);
  152.  
  153.         if (t->right != (C_Op *)NULL)
  154.         {
  155.         Print_indent -= 1;
  156.         Print_IString ("then\n", 1);
  157.         Print_ExTree (t->right->left);
  158.  
  159.         if (t->right->right != (C_Op *)NULL)
  160.         {
  161.             Print_indent -= 1;
  162.  
  163.             if (t->right->right->type != TELIF)
  164.             Print_IString ("else\n", 1);
  165.  
  166.             Print_ExTree (t->right->right);
  167.         }
  168.         }
  169.  
  170.         if (t->type == TIF)
  171.         Print_IString ("fi\n", -1);
  172.  
  173.         return;
  174.  
  175.     case TCASE:            /* CASE function        */
  176.         Print_IString ("case ", 1);
  177.         v1_puts (t->str);
  178.         v1a_puts (" do");
  179.         Print_Case (t->left);
  180.         Print_IString (" esac\n", -1);
  181.         return;
  182.  
  183.     case TBRACE:            /* {} statement            */
  184.         Print_IString ("{\n", 1);
  185.         if (t->left != (C_Op *)NULL)
  186.         Print_ExTree (t->left);
  187.  
  188.         Print_IString ("}\n", -1);
  189.         return;
  190.     }
  191. }
  192.  
  193. /*
  194.  * Print a command line
  195.  */
  196.  
  197. static void    Print_Command (t)
  198. register C_Op    *t;
  199. {
  200.     char    *cp;
  201.     IO_Actions    **iopp;
  202.     char    **wp = t->words;
  203.     char    **owp = wp;
  204.  
  205.     if (t->type == TCOM)
  206.     {
  207.     while ((cp = *wp++) != (char *)NULL)
  208.         ;
  209.  
  210.     cp = *wp;
  211.  
  212. /* strip all initial assignments not correct wrt PATH=yyy command  etc */
  213.  
  214.     if ((cp == (char *)NULL) && (t->ioact == (IO_Actions **)NULL))
  215.     {
  216.         Print_IString (null, 0);
  217.  
  218.         while (*owp != (char *)NULL)
  219.         v1a_puts (*(owp++));
  220.  
  221.         return;
  222.     }
  223.     }
  224.  
  225. /* Parenthesis ? */
  226.  
  227.     if (t->type == TPAREN)
  228.     {
  229.     Print_IString ("(\n", 1);
  230.     Print_ExTree (t->left);
  231.     Print_IString (")", -1);
  232.     }
  233.  
  234.     else
  235.     {
  236.     Print_IString (null, 0);
  237.  
  238.     while (*owp != (char *)NULL)
  239.     {
  240.         v1_puts (*owp++);
  241.  
  242.         if (*owp != (char *)NULL)
  243.         v1_putc (SP);
  244.     }
  245.     }
  246.  
  247. /* Set up anyother IO required */
  248.  
  249.     if ((iopp = t->ioact) != (IO_Actions **)NULL)
  250.     {
  251.     while (*iopp != (IO_Actions *)NULL)
  252.         Print_IO (*iopp++);
  253.     }
  254.  
  255.     v1_putc (NL);
  256. }
  257.  
  258. /*
  259.  * Print the IO re-direction
  260.  */
  261.  
  262. static void        Print_IO (iop)
  263. register IO_Actions    *iop;
  264. {
  265.     int        unit = iop->io_unit;
  266.     static char    *cunit = " x";
  267.  
  268.     if (unit == IODEFAULT)    /* take default */
  269.     unit = (iop->io_flag & (IOREAD | IOHERE)) ? STDIN_FILENO
  270.                           : STDOUT_FILENO;
  271.  
  272. /* Output unit number */
  273.  
  274.     cunit[1] = (char)(unit + '0');
  275.     v1_puts (cunit);
  276.  
  277.     switch (iop->io_flag)
  278.     {
  279.     case IOHERE:
  280.     case IOHERE | IOXHERE:
  281.         v1_putc ('<');
  282.  
  283.     case IOREAD:
  284.         v1_putc ('<');
  285.         break;
  286.  
  287.     case IOWRITE | IOCAT:
  288.         v1_putc ('>');
  289.  
  290.     case IOWRITE:
  291.         v1_putc ('>');
  292.         break;
  293.  
  294.     case IODUP:
  295.         v1_puts (">&");
  296.         v1_putc (*iop->io_name);
  297.         return;
  298.     }
  299.  
  300.     v1_puts (iop->io_name);
  301. }
  302.  
  303. /*
  304.  * Print out the contents of a case statement
  305.  */
  306.  
  307. static void    Print_Case (t)
  308. C_Op        *t;
  309. {
  310.     register C_Op    *t1;
  311.     register char    **wp;
  312.  
  313.     if (t == (C_Op *)NULL)
  314.     return;
  315.  
  316. /* type - TLIST - go down the left tree first and then processes this level */
  317.  
  318.     if (t->type == TLIST)
  319.     {
  320.     Print_Case (t->left);
  321.     t1 = t->right;
  322.     }
  323.  
  324.     else
  325.     t1 = t;
  326.  
  327. /* Output the conditions */
  328.  
  329.     Print_IString (null, 0);
  330.  
  331.     for (wp = t1->words; *wp != (char *)NULL;)
  332.     {
  333.     v1_puts (*(wp++));
  334.  
  335.     if (*wp != (char *)NULL)
  336.         v1_puts (" | ");
  337.     }
  338.  
  339.     v1a_puts (" )");
  340.     Print_indent += 1;
  341.  
  342. /* Output the commands */
  343.  
  344.     Print_ExTree (t1->left);
  345.     Print_IString (";;\n", -1);
  346. }
  347.  
  348. /*
  349.  * Print an indented string
  350.  */
  351.  
  352. static void    Print_IString (cp, indent)
  353. char        *cp;
  354. int        indent;
  355. {
  356.     int        i;
  357.  
  358.     if (indent < 0)
  359.     Print_indent += indent;
  360.  
  361.     for (i = 0; i < (Print_indent / 2); i++)
  362.     v1_putc ('\t');
  363.  
  364.     if (Print_indent % 2)
  365.     v1_puts ("    ");
  366.  
  367.     v1_puts (cp);
  368.  
  369.     if (indent > 0)
  370.     Print_indent += indent;
  371. }
  372.  
  373. /*
  374.  * Look up a function in the save tree
  375.  */
  376.  
  377. Fun_Ops        *Fun_Search (name)
  378. char        *name;
  379. {
  380.     Fun_Ops    *fp;
  381.  
  382.     for (fp = fun_list; fp != (Fun_Ops *)NULL; fp = fp->next)
  383.     {
  384.     if (strcmp (*(fp->tree->words), name) == 0)
  385.         return fp;
  386.     }
  387.  
  388.     return (Fun_Ops *)NULL;
  389. }
  390.  
  391. /*
  392.  * Save or delete a function tree
  393.  */
  394.  
  395. void    Save_Function (t, delete_only)
  396. C_Op    *t;
  397. bool    delete_only;            /* True - delete        */
  398. {
  399.     char        *name = *t->words;
  400.     register Fun_Ops    *fp = Fun_Search (name);
  401.     Fun_Ops        *p_fp = (Fun_Ops *)NULL;
  402.     void        (*save_signal)(int);
  403.  
  404. /* Find the entry */
  405.  
  406.     for (fp = fun_list; (fp != (Fun_Ops *)NULL) &&
  407.             (strcmp (*(fp->tree->words), name) != 0);
  408.             p_fp = fp, fp = fp->next);
  409.  
  410. /* Disable signals */
  411.  
  412.     save_signal = signal (SIGINT, SIG_IGN);
  413.  
  414. /* If it already exists, free the tree and delete the entry */
  415.  
  416.     if (fp != (Fun_Ops *)NULL)
  417.     {
  418.     Set_Free_ExTree (fp->tree, Free_ExTree);
  419.  
  420.     if (p_fp == (Fun_Ops *)NULL)
  421.         fun_list = fp->next;
  422.  
  423.     else
  424.         p_fp->next = fp->next;
  425.  
  426.     DELETE (fp);
  427.     }
  428.  
  429. /* Restore signals */
  430.  
  431.     signal (SIGINT, save_signal);
  432.  
  433. /* If delete only - exit */
  434.  
  435.     if (delete_only)
  436.     return;
  437.  
  438. /* Create new entry */
  439.  
  440.     if ((fp = (Fun_Ops *)space (sizeof (Fun_Ops))) == (Fun_Ops *)NULL)
  441.     return;
  442.  
  443. /* Disable signals */
  444.  
  445.     save_signal = signal (SIGINT, SIG_IGN);
  446.  
  447. /* Set up the tree */
  448.  
  449.     setarea ((char *)fp, 0);
  450.     Set_Free_ExTree (t, Set_ExTree);
  451.  
  452.     fp->tree = t;
  453.     fp->next = fun_list;
  454.     fun_list = fp;
  455.  
  456. /* Restore signals */
  457.  
  458.     signal (SIGINT, save_signal);
  459. }
  460.  
  461. /*
  462.  * Set ExTree areas to zero function
  463.  */
  464.  
  465. static void    Set_ExTree (s)
  466. char        *s;
  467. {
  468.     setarea (s, 0);
  469. }
  470.  
  471. /*
  472.  * Free the ExTree function
  473.  */
  474.  
  475. static void    Free_ExTree (s)
  476. char        *s;
  477. {
  478.     DELETE (s);
  479. }
  480.  
  481. /*
  482.  * Set/Free function tree area by recursively processing of tree
  483.  */
  484.  
  485. static void    Set_Free_ExTree (t, func)
  486. C_Op        *t;
  487. void        (*func)(char *);
  488. {
  489.     char        **wp;
  490.  
  491.     if (t == (C_Op *)NULL)
  492.     return;
  493.  
  494. /* Check for start of print */
  495.  
  496.     if (t->type == TFUNC)
  497.     {
  498.     (*func)(*t->words);
  499.     (*func)((char *)t->words);
  500.     Set_Free_ExTree (t->left, func);
  501.     }
  502.  
  503. /* Otherwise, process the tree and print it */
  504.  
  505.     switch (t->type)
  506.     {
  507.     case TPAREN:            /* ()            */
  508.     case TCOM:            /* A command process    */
  509.         Set_Free_Command (t, func);
  510.         break;
  511.  
  512.     case TPIPE:            /* Pipe processing        */
  513.     case TLIST:            /* Entries in a for statement    */
  514.     case TOR:            /* || and &&            */
  515.     case TAND:
  516.     case TWHILE:            /* WHILE and UNTIL functions    */
  517.     case TUNTIL:
  518.         Set_Free_ExTree (t->left, func);
  519.         Set_Free_ExTree (t->right, func);
  520.         break;
  521.  
  522.     case TFOR:            /* First part of a for statement*/
  523.         (*func)(t->str);
  524.  
  525.         if ((wp = t->words) != (char **)NULL)
  526.         {
  527.         while (*wp != (char *)NULL)
  528.             (*func) (*wp++);
  529.  
  530.         (*func)((char *)t->words);
  531.         }
  532.  
  533.         Set_Free_ExTree (t->left, func);
  534.         break;
  535.  
  536.     case TIF:            /* IF and ELSE IF functions    */
  537.     case TELIF:
  538.         if (t->right != (C_Op *)NULL)
  539.         {
  540.         Set_Free_ExTree (t->right->left, func);
  541.         Set_Free_ExTree (t->right->right, func);
  542.         (*func)((char *)t->right);
  543.         }
  544.  
  545.     case TBRACE:            /* {} statement            */
  546.         Set_Free_ExTree (t->left, func);
  547.         break;
  548.  
  549.     case TCASE:            /* CASE function        */
  550.         (*func)(t->str);
  551.         Set_Free_Case (t->left, func);
  552.         break;
  553.     }
  554.  
  555.     (*func)((char *)t);
  556. }
  557.  
  558. /*
  559.  * Set/Free a command line
  560.  */
  561.  
  562. static void    Set_Free_Command (t, func)
  563. C_Op        *t;
  564. void        (*func)(char *);
  565. {
  566.     IO_Actions    **iopp;
  567.     char    **wp = t->words;
  568.  
  569. /* Parenthesis ? */
  570.  
  571.     if (t->type == TPAREN)
  572.     Set_Free_ExTree (t->left, func);
  573.  
  574.     else
  575.     {
  576.     while (*wp != (char *)NULL)
  577.         (*func)(*wp++);
  578.  
  579.     (*func) ((char *)t->words);
  580.     }
  581.  
  582. /* Process up any IO required */
  583.  
  584.     if ((iopp = t->ioact) != (IO_Actions **)NULL)
  585.     {
  586.     while (*iopp != (IO_Actions *)NULL)
  587.     {
  588.         (*func)((char *)(*iopp)->io_name);
  589.         (*func)((char *)*iopp);
  590.         iopp++;
  591.     }
  592.  
  593.     (*func)((char *)t->ioact);
  594.     }
  595. }
  596.  
  597. /*
  598.  * Set/Free the contents of a case statement
  599.  */
  600.  
  601. static void    Set_Free_Case (t, func)
  602. C_Op        *t;
  603. void        (*func)(char *);
  604. {
  605.     register C_Op    *t1;
  606.     register char    **wp;
  607.  
  608.     if (t == (C_Op *)NULL)
  609.     return;
  610.  
  611. /* type - TLIST - go down the left tree first and then processes this level */
  612.  
  613.     if (t->type == TLIST)
  614.     {
  615.     Set_Free_Case (t->left, func);
  616.     t1 = t->right;
  617.     }
  618.  
  619.     else
  620.     t1 = t;
  621.  
  622. /* Set/Free the conditions */
  623.  
  624.     for (wp = t1->words; *wp != (char *)NULL;)
  625.     (*func)(*(wp++));
  626.  
  627.     (*func)((char *)t1->words);
  628.  
  629.     Set_Free_ExTree (t1->left, func);
  630. }
  631.