[comp.lang.c] Need strtok source!

ssdken@jarthur.Claremont.EDU (Ken Nelson) (01/17/90)

Hello,

  I need source code for the ansi function 'strtok'.  We are porting
  from a system that has it, to one that doesn't.


			Thanks for any help.


			Ken Nelson
			Principal Engineer
			Software Systems Design
			3627 Padua Avenue
			Claremont, CA 91711
			(714) 624-2402

Lynn.Lively@p4694.f506.n106.z1.fidonet.org (Lynn Lively) (01/20/90)

In an article of <16 Jan 90 22:40:10 GMT>, ssdken@jarthur.Claremont.EDU (Ken Nelson) writes:

 KN>From: ssdken@jarthur.Claremont.EDU (Ken Nelson)
 KN>Date: 16 Jan 90 22:40:10 GMT
 KN>Organization: Harvey Mudd College, Claremont, CA
 KN>Message-ID: <3796@jarthur.Claremont.EDU>
 KN>Newsgroups: comp.lang.c
 KN>
 KN>Hello,
 KN>
 KN>  I need source code for the ansi function 'strtok'.  We are porting
 KN>  from a system that has it, to one that doesn't.
 KN>
 KN>
 KN>                        Thanks for any help.
 KN>
 KN>
 KN>                        Ken Nelson
 KN>                        Principal Engineer
 KN>                        Software Systems Design
 KN>                        3627 Padua Avenue
 KN>                        Claremont, CA 91711
 KN>                        (714) 624-2402

 Ken,
     Here is a function that should be able to stand in for strtok()
took me about half an hour to write. I'm including a test program too.
It seems to work as expected, but you may want to check it out a bit more
before you trust it in production.
 Your Servant,
      Lynn

-------------------------------------------------------------------------

#include <stdio.h>
#include <string.h>

char * mytok (char * object, char * delims);

void main ()
  {
    char s[256];
    char delims[256];
    char * wk_ptr;
    while (1)
      {
        printf ("Enter String to search:\n");
        gets (s);
        printf ("Enter Delimeters to search for:\n");
        gets (delims);

        wk_ptr = s;
        while ((wk_ptr = mytok (wk_ptr, delims)) != NULL)
          {
            printf ("String found: '%s'\n", wk_ptr);
            wk_ptr = NULL;
          }
      }
  }

/*
 * Works like strtok()
 */

char * mytok (char * object, char * delims)
  {
    static char * obj_ptr = NULL;
    static char * end_ptr = NULL;

    char * wk_ptr;
    char * min_ptr;

    if (object != NULL)
      {
        obj_ptr = object;
        end_ptr = object + strlen (object);
      }

    if (obj_ptr == end_ptr)
      {
        return (NULL);
      }

    min_ptr = end_ptr;
    while (*delims != '\0')
      {
        wk_ptr = strchr (obj_ptr, *delims++);
        if (wk_ptr != NULL)
          {
            min_ptr = (wk_ptr < min_ptr) ? wk_ptr : min_ptr;
          }
      }

    if (min_ptr != end_ptr)
      {
        wk_ptr   = obj_ptr;
        obj_ptr = min_ptr + 1;
        while (obj_ptr < end_ptr)
          {
            if (*obj_ptr == *min_ptr)
              {
                *obj_ptr++ = '\0';
              }
            else
              {
                break;
              }
          }

        *min_ptr = '\0';
      }
    else
      {
        wk_ptr   = obj_ptr;
        obj_ptr = end_ptr;
      }

    return (wk_ptr);
  }

chris@mimsy.umd.edu (Chris Torek) (01/21/90)

Since I dislike functions with hidden state, my strtok() consists
of the state plus a call to a more fundamental function which I call
`strtoken'.  Here are both of those, plus strsep().  The comments
should enable readers to figure out what these do.

Note that strsep, intended for things like /etc/passwd lines, and strtoken,
intended for use within the C library itself (which may not use strtok
since strtok has hidden state), are not ANSI standard functions.  Indeed,
strtoken cannot be an ANSI standard function, since its six character
monocase equivalent name is `strtok'.

(Despite the Berkeley copyright, these particular implementations are
not yet on any Berkeley machine.  Well, maybe they are; I might have
forgotten putting them there.)

[strsep.c]
/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <string.h>
#include <sys/stdc.h>

#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "%W% (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */

/*
 * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
 * where tokens are possibly empty strings separated by any character
 * from delim.  Writes NULs into s to end tokens.  delim need not
 * remain constant from call to call.
 */
char *
strsep(s, delim)
	char *s;
	const char *delim;
{
	static char *last;

	if (s != NULL)
		last = s;
	return (strtoken(&last, delim, 0));
}

[strtok.c]
/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <string.h>
#include <sys/stdc.h>

#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "%W% (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */

/*
 * Get next token from string s (NULL on 2nd, 3rd, etc. calls),
 * where tokens are nonempty strings separated by runs of
 * chars from delim.  Writes NULs into s to end tokens.  delim need not
 * remain constant from call to call.
 */
char *
strtok(s, delim)
	char *s;
	const char *delim;
{
	static char *last;

	if (s != NULL)
		last = s;
	return (strtoken(&last, delim, 1));
}

[strtoken.c]
/*
 * Copyright (c) 1989 The Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#include <string.h>
#include <sys/stdc.h>

#if defined(LIBC_SCCS) && !defined(lint)
static const char sccsid[] = "%W% (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */

/*
 * Get next token from string *stringp, where tokens are (possibly empty)
 * strings separated by characters from delim.  Tokens are separated
 * by exactly one delimiter iff the skip parameter is false; otherwise
 * they are separated by runs of characters from delim, because we
 * skip over any initial `delim' characters.
 *
 * Writes NULs into the string at *stringp to end tokens.
 * delim will usually, but need not, remain constant from call to call.
 * On return, *stringp points past the last NUL written (if there might
 * be further tokens), or is NULL (if there are definitely no more tokens).
 *
 * If *stringp is NULL, strtoken returns NULL.
 */
char *
strtoken(stringp, delim, skip)
	register char **stringp;
	register const char *delim;
	int skip;
{
	register char *s;
	register const char *spanp;
	register int c, sc;
	char *tok;

	if ((s = *stringp) == NULL)
		return (NULL);

	if (skip) {
		/*
		 * Skip (span) leading delimiters (s += strspn(s, delim)).
		 */
	cont:
		c = *s;
		for (spanp = delim; (sc = *spanp++) != 0;) {
			if (c == sc) {
				s++;
				goto cont;
			}
		}
		if (c == 0) {		/* no token found */
			*stringp = NULL;
			return (NULL);
		}
	}

	/*
	 * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
	 * Note that delim must have one NUL; we stop if we see that, too.
	 */
	for (tok = s;;) {
		c = *s++;
		spanp = delim;
		do {
			if ((sc = *spanp++) == c) {
				if (c == 0)
					s = NULL;
				else
					s[-1] = 0;
				*stringp = s;
				return (tok);
			}
		} while (sc != 0);
	}
	/* NOTREACHED */
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@cs.umd.edu	Path:	uunet!mimsy!chris