home *** CD-ROM | disk | FTP | other *** search
/ APDL Public Domain 1 / APDL_PD1A.iso / deskutils / _a_l / boota / C-source / c / argfuncs < prev    next >
Encoding:
Text File  |  1993-06-02  |  14.0 KB  |  342 lines

  1. /* > c.argfuncs - (c) Paul Witheridge - Version 1.02 - 02 June 1993  */
  2.  
  3. /*===================================================================*/
  4. /*                                                                   */
  5. /*  This file includes the following functions:                      */
  6. /*                                                                   */
  7. /*       arganal      -   analyse standard arguments                 */
  8. /*       displaytext  -   display help text etc                      */
  9. /*                                                                   */
  10. /*===================================================================*/
  11.  
  12. #include "kernel.h"                   /* ARC specifics               */
  13. #include "swis.h"                     /* SWI names                   */
  14.  
  15. #include <ctype.h>                    /* Character handling          */
  16. #include <stddef.h>                   /* Standard definitions        */
  17. #include <stdlib.h>                   /* General utilities           */
  18. #include <stdio.h>                    /* Input/output                */
  19. #include <string.h>                   /* String handling             */
  20.  
  21. #include "Beep.h"                     /* Beep header                 */
  22. #include "Useful.h"                   /* Useful defs                 */
  23. #include "Argfuncs.h"                 /* For checking                */
  24.  
  25. /*===================================================================*/
  26. /*                                                                   */
  27. /*  analargs  -  analyse command line arguments                      */
  28. /*  --------                                                         */
  29. /*                                                                   */
  30. /*  This function analyses standard command line arguments which can */
  31. /*  be any combination of the following three types:                 */
  32. /*                                                                   */
  33. /*  (1) positional arguments (cannot begin with '-')                 */
  34. /*  (2) option switches (single character preceded by '-')           */
  35. /*  (3) option value (follows option switch, cannot begin with '-')  */
  36. /*                                                                   */
  37. /*  The arguments provided by the caller comprise:                   */
  38. /*                                                                   */
  39. /*   -  count of command line arguments                              */
  40. /*   -  array of ptrs to command line arguments                      */
  41. /*   -  max number of position arguments allowed                     */
  42. /*   -  array of ptrs to ptrs for storing address of pos. args       */
  43. /*   -  string of allowable option characters (upper case and        */
  44. /*      terminated by null byte)                                     */
  45. /*   -  pointer to flag byte                                         */
  46. /*   -  array of flag masks (unsigned char) for setting flags in     */
  47. /*      flag byte corresponding to option characters                 */
  48. /*   -  array of ptrs to ptrs for storing address of option value    */
  49. /*      args                                                         */
  50. /*                                                                   */
  51. /*===================================================================*/
  52.  
  53. void analargs(
  54.   const int argc,                     /* Number of arguments         */
  55.   const char *argv[],                 /* Array of pointers to args   */
  56.   const int posnc,                    /* Number of positional args   */
  57.   const char **(**posnptr)[],         /* Ptr to positional arg ptrs  */
  58.   const char options[],               /* Option characters           */
  59.   unsigned char *flags,               /* Pointer to flag byte        */
  60.   const unsigned char optflags[],     /* Option flag settings        */
  61.   const char **optval[])              /* Ptrs to value ptrs          */
  62. {
  63.   /*-----------------------------------------------------------------*/
  64.   /*  Local definitions.                                             */
  65.   /*-----------------------------------------------------------------*/
  66.  
  67.   int argi ;                          /* Argument index              */
  68.   int opti ;                          /* Option index                */
  69.   int posni ;                         /* Positional argument index   */
  70.   const char *p ;                     /* Working pointer             */
  71.  
  72.   /*-----------------------------------------------------------------*/
  73.   /*  Executable statements                                          */
  74.   /*                                                                 */
  75.   /*  Make one or two passes through arguments.                      */
  76.   /*                                                                 */
  77.   /*  One pass is enough if caller has supplied array of pointers    */
  78.   /*  to positional parameter pointers.                              */
  79.   /*                                                                 */
  80.   /*  Two passes are required if caller did not supply an array but  */
  81.   /*  wants us to build him one. First pass counts the number of     */
  82.   /*  positional parameters while the second fills them in.          */
  83.   /*                                                                 */
  84.   /*  Multiple positional operands allowed up to maximum number      */
  85.   /*  specified by caller - recognised because they do not start     */
  86.   /*  with '-' and are not preceded by an option character which     */
  87.   /*  takes a value.                                                 */
  88.   /*                                                                 */
  89.   /*  Multiple option arguments allowed - recognised because they    */
  90.   /*  do begin with '-' which must be followed by a single           */
  91.   /*  character which must be one of the charcters in the "options"  */
  92.   /*  array and specifies the option selected.                       */
  93.   /*                                                                 */
  94.   /*  Option can set a global flag - flag setting specified by the   */
  95.   /*  corresponding entry in the "optflags" array.                   */
  96.   /*                                                                 */
  97.   /*  Option may be followed by a value if corresponding pointer     */
  98.   /*  in "optvals" array is non-null. Pointer points to actual       */
  99.   /*  pointer which must be set to point to the value.               */
  100.   /*                                                                 */
  101.   /*-----------------------------------------------------------------*/
  102.  
  103.   do
  104.   {
  105.     posni = 0 ;
  106.     for ( argi = 1 ; argi < argc ; argi++ )
  107.     {
  108.       /*-------------------------------------------------------------*/
  109.       /*  If arg starts with "-" it must be option.                  */
  110.       /*                                                             */
  111.       /*  Reject it if not immediately followed by one of valid      */
  112.       /*  option characters. Otherwise set flag in caller's flag     */
  113.       /*  byte corresponding to that option. Then check for any      */
  114.       /*  value immediately following (without space). If so,        */
  115.       /*  reject it if no value allowed for this option. Otherwise   */
  116.       /*  store pointer to value for caller. If no immediately       */
  117.       /*  value, and value is expected, check if value follows       */
  118.       /*  after space (i.e., next argument). If so, and it does not  */
  119.       /*  start with "-", store pointer to value for caller.         */
  120.       /*-------------------------------------------------------------*/
  121.  
  122.       if ( argv[argi][0] == '-' )
  123.       {
  124.         if ( (p = strchr(options,toupper(argv[argi][1]))) == NULL )
  125.         {
  126.           goto badopts ;
  127.         }
  128.         opti = p - options ;
  129.         *flags |= optflags[opti] ;
  130.         if ( optval[opti] == NULL )
  131.         {
  132.           if ( argv[argi][2] != '\0' )
  133.           {
  134.             goto badopts ;
  135.           }
  136.         }
  137.         else
  138.         {
  139.           if ( argv[argi][2] == '\0' )
  140.           {
  141.             argi++ ;
  142.             if ( argi < argc && argv[argi][0] != '-' )
  143.             {
  144.               *optval[opti] = argv[argi] ;
  145.             }
  146.             else
  147.             {
  148.               argi-- ;
  149.             }
  150.           }
  151.           else
  152.           {
  153.             *optval[opti] = &argv[argi][2] ;
  154.           }
  155.         }
  156.       }
  157.  
  158.       /*-------------------------------------------------------------*/
  159.       /*  If arg does not start with "-" it must be positional       */
  160.       /*                                                             */
  161.       /*  If no array provided by caller then on first pass just     */
  162.       /*  count number of positional parameters.                     */
  163.       /*                                                             */
  164.       /*  If array provided, or on on second pass using array we     */
  165.       /*  have created, either fill-in caller's pointers to the      */
  166.       /*  positional arguments, or set up the array of pointers      */
  167.       /*  to point to the appropriate "argv" pointer.                */
  168.       /*-------------------------------------------------------------*/
  169.  
  170.       else
  171.       {
  172.         if ( posni < posnc )
  173.         {
  174.           if ( *posnptr != NULL )
  175.           {
  176.             if ( (**posnptr)[posni] == NULL )
  177.             {
  178.               (**posnptr)[posni] = &argv[argi] ;
  179.             }
  180.             else
  181.             {
  182.               *(**posnptr)[posni] = argv[argi] ;
  183.             }
  184.           }
  185.           posni++ ;
  186.         }
  187.         else
  188.         {
  189.           p = "positional argument" ;
  190.           goto badargs ;
  191.         }
  192.       }
  193.     }
  194.  
  195.     /*---------------------------------------------------------------*/
  196.     /*  At end of first pass, if caller did not provide and array    */
  197.     /*  of pointers, allocate storage for one ourselves.             */
  198.     /*---------------------------------------------------------------*/
  199.     
  200.     if ( *posnptr != NULL )
  201.     {
  202.       break ;
  203.     }
  204.     else
  205.     {
  206.       if ( ( *posnptr = calloc(posni + 1,sizeof(char **)) ) == NULL )
  207.       {
  208.         puts("Too many arguments - out of memory") ;
  209.         beep() ;
  210.         exit(8) ;
  211.       }
  212.     }
  213.   } FOREVER ;
  214.  
  215.   /*-----------------------------------------------------------------*/
  216.   /*  All done. Return.                                              */
  217.   /*-----------------------------------------------------------------*/
  218.  
  219.   return ;
  220.   
  221.   /*-----------------------------------------------------------------*/
  222.   /*  If bad argument found sound beep and exit with code 8          */
  223.   /*-----------------------------------------------------------------*/
  224.  
  225.   badopts:
  226.     
  227.     p = "option" ;
  228.  
  229.   badargs:
  230.     
  231.     printf("ERROR - invalid %s: %s\n\n",p,argv[argi]) ;
  232.     beep() ;
  233.     exit(8) ;
  234. }
  235.  
  236. /*===================================================================*/
  237. /*                                                                   */
  238. /*  displaytext  -   display help/syntax text                        */
  239. /*  -----------                                                      */
  240. /*                                                                   */
  241. /*  This function displays text according to the current text        */
  242. /*  window width. It is passed pointers to a text string and an      */
  243. /*  array of tab settings.                                           */
  244. /*                                                                   */
  245. /*  Control characters (codes less than 0x20) have the following     */
  246. /*  special effects:                                                 */
  247. /*                                                                   */
  248. /*    0x00       =  end of string                                    */
  249. /*                                                                   */
  250. /*    0x01-0x1e  =  indices into tab settings array                  */
  251. /*                                                                   */
  252. /*    0x1f       =  new line required                                */
  253. /*                                                                   */
  254. /*  The array of tab settings is an array of unsigned characters.    */
  255. /*  The first character is the indent to be used at the start of     */
  256. /*  each line. Other characters are indexed by characters 0x01 to    */
  257. /*  0x1e in the text.                                                */
  258. /*                                                                   */
  259. /*===================================================================*/
  260.  
  261. void displaytext(
  262.   const char *text,                   /* Ptr to help text            */
  263.   const unsigned char tabs[])         /* Ptr to array of tab values  */
  264.  
  265. {
  266.   int c ;                             /* Working character           */
  267.   int i = 0 ;                         /* Offset into current line    */
  268.   int b ;                             /* Count of blanks             */
  269.   int t ;                             /* Current indent              */ 
  270.   int l ;                             /* Line length                 */
  271.   const char *p ;                     /* Working pointer             */
  272.  
  273.   static const int varkeys[] =
  274.   {
  275.     132,
  276.     134,
  277.     -1
  278.   } ;
  279.  
  280.   int varvals[2] ;
  281.  
  282.   _kernel_swi_regs swiregs ;
  283.  
  284.   swiregs.r[0] = (int)varkeys ;
  285.   swiregs.r[1] = (int)varvals ;
  286.   _kernel_swi(OS_ReadVduVariables,&swiregs,&swiregs) ;
  287.   
  288.   l = varvals[1] - varvals[0] ;
  289.  
  290.   b = t = tabs[0] ;
  291.  
  292.   while ( (c = *text) != '\0' )
  293.   {
  294.     if ( c <= 0x20 )
  295.     {
  296.       switch ( c )
  297.       {
  298.         case 0x20 :             /* Process blank                     */
  299.  
  300.           b++ ;
  301.           break;
  302.  
  303.         case 0x1f :             /* Process new line                  */
  304.     
  305.           putchar('\n') ;
  306.           i = 0 ;
  307.           t = b = tabs[0] ;
  308.           break;
  309.  
  310.         default :               /* Process tab                       */
  311.     
  312.           t = tabs[c] ;
  313.           if ( t > i + b )
  314.           {
  315.             b = t - i ;
  316.           }
  317.       }
  318.       text++ ;
  319.     }
  320.     else
  321.     {
  322.       for ( p = text ; *p > 0x20 ; p++ ) ;
  323.       if ( i + b + p - text > l )
  324.       {
  325.         putchar('\n') ;
  326.         i = 0 ;
  327.         b = t ;
  328.       }
  329.       for ( ; b > 0 ; b--, i++ )
  330.       {
  331.         putchar(' ') ;
  332.       }
  333.       for ( ; text < p ; text++, i++ )
  334.       {
  335.         putchar(*text) ;
  336.       }
  337.     }
  338.   }
  339. }
  340.  
  341. /*====================================================================*/
  342.