home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / mmdf / mmdf-IIb.43 / lib / util / str2arg.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-02-01  |  4.6 KB  |  192 lines

  1.  
  2. #include "util.h"
  3.  
  4. /*  convert string into argument list
  5.  *
  6.  *  stash a pointer to each field into the passed array.
  7.  *  any common seperators split the words.  extra white-space
  8.  *  between fields is ignored.
  9.  *
  10.  *  if the separator is '=', then the current argument position in
  11.  *  the array points to "=", the next the one is the key and the
  12.  *  value follows it.  This permits detecting variable assignment,
  13.  *  in addition to positional arguments.
  14.  *      i.e.,  key=value ->  = key value
  15.  *
  16.  *  specially-interpreted characters:
  17.  *      space, tab, double-quote, backslash, comma, equal, slash, period,
  18.  *      semi-colon, colon, carriage return, and line-feed (newline).
  19.  *      preceding a special char with a backslash removes its
  20.  *      interpretation.  a backslash not followed by a special is used
  21.  *      to preface an octal specification for one character
  22.  *
  23.  *      a string begun with double-quote has only double-quote and
  24.  *      backslash as special characters.
  25.  *
  26.  *  a field which begins with semi-colon or a hash (#) is interpreted
  27.  *  as marking the rest of the line as a comment and it is skipped, as
  28.  *  are blank lines
  29.  */
  30.  
  31. extern int errno;
  32.  
  33. str2arg (srcptr, max, argv, dlm)/* convert srcptr to argument list */
  34.     register char *srcptr;  /* source data */
  35.     int max;                /* maximum number of permitted fields */
  36.     char *argv[];           /* where to put the pointers */
  37.     char dlm[];             /* list of delimiting characters */
  38. {
  39.     char gotquote;      /* currently parsing quoted string */
  40.     char lastdlm;       /* last delimeter character     */
  41.     register int ind;
  42.     register char *destptr;
  43.  
  44.     if (srcptr == 0)
  45.     {
  46.     errno = EINVAL;     /* emulate system-call failure */
  47.     return (NOTOK);
  48.     }
  49.  
  50.     for (lastdlm = (char) NOTOK, ind = 0, max -= 2; *srcptr != '\0'; ind++)
  51.     {
  52.     if (ind >= max)
  53.     {
  54.         errno = E2BIG;      /* emulate system-call failure */
  55.         return (NOTOK);
  56.     }
  57.     for (argv[ind] = destptr = srcptr; isspace (*srcptr); srcptr++)
  58.         ;               /* skip leading white space         */
  59. /* */
  60.  
  61.     for (gotquote = FALSE; ; )
  62.     {
  63.         switch (*srcptr)
  64.         {
  65.         default:        /* just copy it                     */
  66.             *destptr++ = *srcptr++;
  67.             break;
  68.  
  69.         case '\"':      /* beginning or end of string       */
  70.             gotquote = (gotquote) ? FALSE : TRUE;
  71.             srcptr++;   /* just toggle */
  72.             break;
  73.  
  74.         case '\\':      /* quote next character             */
  75.             srcptr++;   /* just skip the back-slash         */
  76.             switch (*srcptr)
  77.             {           /* convert octal values             */
  78.             case 'r':
  79.                 *destptr++ = '\r';
  80.                 srcptr++;
  81.                 break;
  82.  
  83.             case 'n':
  84.                 *destptr++ = '\n';
  85.                 srcptr++;
  86.                 break;
  87.  
  88.             case 'b':
  89.                 *destptr++ = '\b';
  90.                 srcptr++;
  91.                 break;
  92.  
  93.             case 'f':
  94.                 *destptr++ = '\f';
  95.                 srcptr++;
  96.                 break;
  97.  
  98.             default:
  99.                 if (*srcptr >= '0' && *srcptr <= '7')
  100.                 {
  101.                 *destptr = '\0';
  102.                 do
  103.                     *destptr = (*destptr << 3) | (*srcptr++ - '0');
  104.                 while (*srcptr >= '0' && *srcptr <= '7');
  105.                 destptr++;
  106.                 break;
  107.                 }    /* otherwise DROP ON THROUGH */
  108.             case '\\':
  109.             case '\"':
  110.             case ' ':
  111.             case ',':
  112.             case '\t':
  113.             case ';':
  114.             case '#':
  115.             case ':':
  116.             case '=':
  117.             case '/':
  118.             case '|':
  119.                 *destptr++ = *srcptr++;
  120.                 break; /* just copy it */
  121.             }       /* DROP ON THROUGH */
  122.             break;
  123.  
  124.         case '=':   /* make '=' prefix to pair  */
  125.             if (gotquote)
  126.             {
  127.             *destptr++ = *srcptr++;
  128.             break;
  129.             }
  130.  
  131.             ind++;      /* put value ahead of '=' */
  132.  
  133.             if ( dlm != (char *) 0)
  134.             {
  135.             dlm[ind - 1] =
  136.                 dlm[ind] = '=';
  137.             }
  138.             argv[ind] = argv[ind - 1];
  139.             lastdlm = '=';
  140.             argv[ind - 1] = "=";
  141.             *destptr = '\0';
  142.             srcptr++;
  143.             goto nextarg;
  144.  
  145.         case ' ':
  146.         case '\t':
  147.         case '\n':
  148.         case '\r':
  149.         case ',':
  150.         case ';':
  151.         case '#':
  152.         case ':':
  153.         case '/':
  154.         case '|':
  155.             if (gotquote)
  156.             {           /* don't interpret the char */
  157.             *destptr++ = *srcptr++;
  158.             break;
  159.             }
  160.  
  161.             if (isspace (lastdlm))
  162.             {
  163.             if (isspace (*srcptr))
  164.             {           /* shouldn't be possible */
  165.                 errno = EINVAL;
  166.                 return (NOTOK);
  167.             }
  168.             else
  169.                 if (*srcptr != ';' && *srcptr != '#')
  170.                 ind--;  /* "xxx , yyy" is only 2 fields */
  171.             }
  172.             lastdlm = *srcptr;
  173.             if ( dlm != (char *) 0)
  174.             dlm[ind] = *srcptr;
  175.             srcptr++;
  176.         case '\0':
  177.             *destptr = '\0';
  178.             goto nextarg;
  179.         }
  180.  
  181.         lastdlm = (char) NOTOK;     /* disable when field started */
  182.     }
  183.  
  184.     nextarg:
  185.     if (argv[ind][0] == '\0' && (lastdlm == ';' || lastdlm == '#'))
  186.         break;      /* rest of line is comment                  */
  187.     }
  188.  
  189.     argv[ind] = (char *) 0;
  190.     return (ind);
  191. }
  192.