home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #1 / NN_1993_1.iso / spool / comp / lang / c / 19255 < prev    next >
Encoding:
Text File  |  1993-01-05  |  4.3 KB  |  150 lines

  1. Newsgroups: comp.lang.c
  2. Path: sparky!uunet!uunet.ca!canrem!telly!druid!darcy
  3. From: darcy@druid.uucp (D'Arcy J.M. Cain)
  4. Subject: Re: strtok
  5. Message-ID: <1993Jan5.123430.5849@druid.uucp>
  6. Date: Tue, 5 Jan 1993 12:34:30 GMT
  7. Distribution: usa
  8. References: <1992Dec31.045902.2025@mcs.drexel.edu> <bibhas.725836376@femto.engr.mun.ca> <1iab2aINNlmn@parlo.hal.COM>
  9. Organization: D'Arcy Cain Consulting
  10. Lines: 138
  11.  
  12. paul@hal.COM (Paul Sander) writes:
  13. >Robert Osborne posted a strtok replacement to comp.lang.c on September 12,
  14. >1991 that returns strtok's global state in a parameter to the caller, making
  15. >it reentrant.  The message-ID is 1395@isgtec.UUCP, and I have copies of it
  16. >if anyone is interested.
  17.  
  18. Here's one I wrote based on Henry Spencer's strtok code.  I had to change
  19. the name since the semantics are completely different than the standard.
  20.  
  21. /*
  22.  * xstrtok.c
  23.  * Written by D'Arcy J.M. Cain
  24.  * based on code by Henry Spencer
  25.  * modified to assume an ANSI compiler by D'Arcy J.M. Cain
  26.  * because strtok is a little brain dead about multiple calls
  27.  * this is a modified version which carries the pertinent information
  28.  * in a structure.  This allows more than one string to be parsed
  29.  * at the same time (the code is re-entrant.)
  30.  *
  31.  * Get next token from string x->s (NULL on 2nd, 3rd, etc. calls),
  32.  * where tokens are nonempty strings separated by runs of
  33.  * chars from delim.  Writes NULs into s to end tokens.  delim need not
  34.  * remain constant from call to call.   If quote is set then quotes (single
  35.  * or double) are respected.
  36.  *
  37.  * structure in string.h should look like this:
  38.  * typedef struct {
  39.  *    char        *scanpoint;        / * filled in by xstrtok * /
  40.  *    char        *str2parse;        / * string to parse - set for first call * /
  41.  *    const char    *delim;            / * string of delimiters * /
  42.  *    int            quote;            / * respect quoting if set * /
  43.  * } XSTRTOK;
  44.  */
  45.  
  46. #include    <string.h>
  47.  
  48. char    *xstrtok(XSTRTOK *xinfo)
  49. {
  50.     char        *scan;
  51.     char        *tok;
  52.     char        qchar = 0;
  53.     const char    *dscan;
  54.  
  55.     /* figure out what stage we are at */
  56.     if (xinfo->str2parse == NULL && xinfo->scanpoint == NULL)
  57.         return(NULL);            /* last one went last time */
  58.  
  59.     if (xinfo->str2parse != NULL)
  60.     {
  61.         scan = xinfo->str2parse;    /* this is the first time */
  62.         xinfo->str2parse = NULL;
  63.     }
  64.     else
  65.         scan = xinfo->scanpoint;    /* we have already started */
  66.  
  67.     /* Skip leading delimiters.  */
  68.     for (; *scan; scan++)
  69.     {
  70.         for (dscan = xinfo->delim; *dscan; dscan++)
  71.             if (*scan == *dscan)    /* found a delimiter */
  72.                 break;                /* from inner loop */
  73.  
  74.         if (*dscan == '\0')            /* this character not a delimiter */
  75.             break;                    /* from outer loop */
  76.     }
  77.  
  78.     /* are we finished with the line? */
  79.     if (*scan == '\0')
  80.     {
  81.         xinfo->scanpoint = NULL;
  82.         return(NULL);
  83.     }
  84.  
  85.     /* otherwise we now point to the next token */
  86.     tok = scan;
  87.  
  88.     /* find the end of the token */
  89.     /* three versions for speedup rather than testing within loop */
  90.  
  91.     /* first find empty string such as "" */
  92.     if (xinfo->quote && (*tok == '\"' || *tok == '\'') && tok[0] == tok[1])
  93.     {
  94.         *tok = 0;
  95.         xinfo->scanpoint = tok + 2;
  96.         return(tok);
  97.     }
  98.  
  99.     /* non-empty string respecting quotes */
  100.     if (xinfo->quote) for (; *scan != '\0'; scan++)
  101.     {
  102.         for (dscan = xinfo->delim; *dscan != '\0';)    /* increment is in body */
  103.         {
  104.             /* have we found a delimiter? */
  105.             if (*scan == *dscan++)
  106.             {
  107.                 xinfo->scanpoint = scan + 1;    /* point to next character */
  108.                 *scan = '\0';                /* terminate the token */
  109.                 return(tok);                /* and return it */
  110.             }
  111.  
  112.             /* is it a quote character */
  113.             if (*scan == '\'' || *scan == '\"')
  114.             {
  115.                 qchar = *scan;                /* search for same close quote */
  116.                 strcpy(scan, scan + 1);        /* don't return quotes */
  117.  
  118.                 while (*scan && *scan != qchar)
  119.                     scan++;
  120.  
  121.                 strcpy(scan, scan + 1);        /* don't return quotes */
  122.             }
  123.         }
  124.     }
  125.     /* normal strtok semantics */
  126.     else for (; *scan != '\0'; scan++)
  127.     {
  128.         for (dscan = xinfo->delim; *dscan != '\0';)    /* increment is in body */
  129.         {
  130.             /* have we found a delimiter? */
  131.             if (*scan == *dscan++)
  132.             {
  133.                 xinfo->scanpoint = scan + 1;    /* point to next character */
  134.                 *scan = '\0';                    /* terminate the token */
  135.                 return(tok);                    /* and return it */
  136.             }
  137.         }
  138.     }
  139.  
  140.     /* Reached end of string.  */
  141.     xinfo->scanpoint = NULL;
  142.     return(tok);
  143. }
  144.  
  145. -- 
  146. D'Arcy J.M. Cain (darcy@druid.com)  |
  147. D'Arcy Cain Consulting              |   There's no government
  148. Toronto, Ontario, Canada            |   like no government!
  149. +1 416 424 2871          DoD#0082   |
  150.