home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / communic / pcmail / main / str.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-05  |  6.5 KB  |  249 lines

  1. /*++
  2. /* NAME
  3. /*    strcons,istrcmp,strvec,vecstr,split 3
  4. /* SUMMARY
  5. /*    string utility routines
  6. /* PROJECT
  7. /*    pc-mail
  8. /* PACKAGE
  9. /*    general stuff
  10. /* SYNOPSIS
  11. /*    #include "defs.h"
  12. /*
  13. /*    char *strcons(format,args)
  14. /*    char *format;
  15. /*
  16. /*    char *split(cpp, sep)
  17. /*    char **cpp;
  18. /*    char *sep;
  19. /*
  20. /*    int istrncmp(s1,s2,n)
  21. /*    char *s1,s2;
  22. /*    int n;
  23. /*
  24. /*    int istrcmp(s1,s2)
  25. /*    char *s1,s2;
  26. /*
  27. /*    char **strvec(string,separ)
  28. /*    char *string;
  29. /*    char *separ;
  30. /*
  31. /*    freevec(vec)
  32. /*    char **vec;
  33. /*
  34. /*    char *vecstr(vector,separ)
  35. /*    char **vector;
  36. /*    char *separ;
  37. /* DESCRIPTION
  38. /*    strcons() produces a formatted string, using printf()-like
  39. /*    arguments. Basically it is an sprintf() that returns a
  40. /*    pointer to the result. memory for the result is taken from
  41. /*    a small memory pool that is recycled upon successive calls.
  42. /*
  43. /*    split() searches the string pointed to by cpp for the occurrance
  44. /*    of the text token (a string not containing any of the characters
  45. /*    given in the "sep" argument). *cpp is updated if a token is
  46. /*    found; a null pointer is returned otherwise. This function
  47. /*    is an attempt to improve upon the strtok() function, which
  48. /*    can parse only one string at a time. It still modifies its
  49. /*    arguments, however.
  50. /*
  51. /*    istrcmp() is a case-insensitive version of the strcmp() function.
  52. /*
  53. /*    istrncmp() is a case-insensitive version of the strncmp() function.
  54. /*
  55. /*    strvec() breaks a null-terminated string using the separators given
  56. /*    in separ, and returns a null-terminated vector of pointers to the
  57. /*    resulting substrings. Memory for the vector and substrings are
  58. /*    allocated in dynamic memory. The original string is not modified.
  59. /*
  60. /*    freevec() frees storage allocated by strvec().
  61. /*
  62. /*    vecstr() takes a null-terminated vector of string pointers
  63. /*    and builds a string from the strings pointed to by the vector
  64. /*    argument, separated by the string in the separ argument.
  65. /*    Memory for the result is allocated in dynamic memory.
  66. /* FUNCTIONS AND MACROS
  67. /*    strtok(), malloc(), memcpy(), sprintf()
  68. /* DIAGNOSTICS
  69. /*    strvec(), vecstr() return a null pointer if there was not enough memory
  70. /*    avaliable to hold the result.
  71. /* BUGS
  72. /*    strcons() does not do smart garbage collection; it just uses
  73. /*    a circular buffer. The present implementation is not portable
  74. /*    to machines that pass arguments via registers.
  75. /*
  76. /*    strvec() cannot handle strings with more than BUFSIZ words.
  77. /*    strvec() uses strtok(), which may have side effects.
  78. /* AUTHOR(S)
  79. /*    W.Z. Venema
  80. /*    Eindhoven University of Technology
  81. /*    Department of Mathematics and Computer Science
  82. /*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  83. /* CREATION DATE
  84. /*    Tue Apr  5 20:59:29 MET 1988
  85. /* LAST MODIFICATION
  86. /*    90/01/22 13:02:43
  87. /* VERSION/RELEASE
  88. /*    2.1
  89. /*--*/
  90.  
  91. #include <stdio.h>
  92. #include <ctype.h>
  93. #include <varargs.h>
  94.  
  95. #include "defs.h"
  96.  
  97. #define    NBUF    4
  98.  
  99. /* strcons - quick-and-dirty string constructor */
  100.  
  101. /* VARARGS */
  102.  
  103. char   *strcons(va_alist) 
  104. va_dcl
  105. {
  106.     va_list ap;
  107.     static char strbuf[NBUF][BUFSIZ];
  108.     static int where = 0;
  109.     register char *cp;
  110.     char   *fmt;
  111.  
  112.     va_start(ap);
  113.     fmt = va_arg(ap, char *);
  114.     (void) vsprintf(cp = strbuf[where = (where + 1) % NBUF], fmt, ap);
  115.     va_end(ap);
  116.     return (cp);
  117. }
  118.  
  119. /* istrcmp - case-insensitive string comparison */
  120.  
  121. #define    LOW(c)    (isascii(c)&&isupper(c)?tolower(c):(c))
  122.  
  123. int     istrcmp(s1, s2)
  124. register char *s1;
  125. register char *s2;
  126. {
  127.     while (*s1 && (LOW(*s1) == LOW(*s2)))
  128.     s1++, s2++;
  129.     return (LOW(*s1) - LOW(*s2));
  130. }
  131.  
  132. /* istrncmp - case-insensitive string comparison */
  133.  
  134. #define    LOW(c)    (isascii(c)&&isupper(c)?tolower(c):(c))
  135.  
  136. int     istrncmp(s1, s2, n)
  137. register char *s1;
  138. register char *s2;
  139. register int n;
  140. {
  141.     while (n > 0 && *s1 && (LOW(*s1) == LOW(*s2)))
  142.     n--, s1++, s2++;
  143.     return (n > 0 ? LOW(*s1) - LOW(*s2) : 0);
  144. }
  145.  
  146. /* strvec - make vector of substring pointers */
  147.  
  148. char  **strvec(str, sep)
  149. char   *str;
  150. char   *sep;
  151. {
  152. #ifdef lint
  153.     static
  154. #endif
  155.     char   *tmp[BUFSIZ];        /* scratch substring pointer storage */
  156.     register char **cpp = tmp;
  157.     char   *sp;                /* ptr to private copy of original */
  158.     register int bytec;
  159.  
  160.     /* make a copy of the original string */
  161.  
  162.     if ((sp = malloc(strlen(str) + 1)) == 0)
  163.     return (0);
  164.     (void) strcpy(sp, str);
  165.  
  166.     /* chop our copy at sequences of one or more separators */
  167.  
  168.     for (*cpp = strtok(sp, sep); *cpp; *++cpp = strtok((char *) 0, sep))
  169.      /* void */ ;
  170.  
  171.     /* now construct the vector of pointers to the substrings */
  172.  
  173.     if ((cpp = (char **) malloc(bytec = (cpp - tmp + 1) * sizeof(*cpp))) == 0)
  174.     return (0);
  175.     return ((char **) memcpy((char *) cpp, (char *) tmp, bytec));
  176. }
  177.  
  178. /* freevec - release storage allocated by strvec() */
  179.  
  180. freevec(vec)
  181. char  **vec;
  182. {
  183.     free(vec[0]);
  184.     free((char *) vec);
  185. }
  186.  
  187. /* vecstr - from null-terminated vector of string pointers to one flat string */
  188.  
  189. public char *vecstr(vec, sep)
  190. char  **vec;
  191. char   *sep;
  192. {
  193.     register char **cpp;
  194.     register int len = 0;        /* length of final string */
  195.     register char *cp;
  196.     register int flen = strlen(sep);    /* filler between substrings */
  197.  
  198.     /* find out how big the resulting string will be */
  199.  
  200.     for (cpp = vec; *cpp; cpp++)
  201.     len += strlen(*cpp) + flen;
  202.  
  203.     /* allocate and initialize the result string */
  204.  
  205.     if ((cp = malloc(len + 1)) == 0)
  206.     return (0);
  207.     *cp = '\0';
  208.  
  209.     /* fill the resulting string */
  210.  
  211.     for (cpp = vec; *cpp; cpp++) {
  212.     (void) strcat(cp, *cpp);
  213.     (void) strcat(cp, sep);
  214.     }
  215.     return (cp);
  216. }
  217.  
  218. /* split - return next token in *cpp, update cpp */
  219.  
  220. public char *split(cpp, sep)
  221. register char **cpp;
  222. register char *sep;
  223. {
  224.     register char *start;
  225.     char   *end;
  226.     char   *strpbrk();
  227.  
  228.     /*
  229.      * Find the beginning of the first token. If none is found, just return a
  230.      * null value. Otherwise, if there is a separator that follows the token,
  231.      * nullify it and advance *cpp to the first character after the nullified
  232.      * separator. If the token is not followed by a separator advance *cpp to
  233.      * the null byte that follows the token.
  234.      */
  235.  
  236.     start = *cpp + strspn(*cpp, sep);
  237.  
  238.     if (start[0] == 0) {
  239.     return (0);                /* no token */
  240.     } else if (end = strpbrk(start, sep)) {    /* look for separator */
  241.     *end = '\0';                /* nullify */
  242.     *cpp = end + 1;                /* advance beyond end */
  243.     return (start);                /* return token */
  244.     } else {
  245.     *cpp = start + strlen(start);        /* advance to terminator */
  246.     return (start);                /* return token */
  247.     }
  248. }
  249.