1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  23 /*        All Rights Reserved   */
  24 
  25 
  26 #ident  "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.13  */
  27 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
  28 
  29 #include "string.h"
  30 #include "errno.h"
  31 #include "stdlib.h"
  32 
  33 #include "lp.h"
  34 
  35 #if     defined(__STDC__)
  36 static char             *unq_strdup ( char * , char * );
  37 #else
  38 static char             *unq_strdup();
  39 #endif
  40 
  41 /**
  42  ** getlist() - CONSTRUCT LIST FROM STRING
  43  **/
  44 
  45 /*
  46  * Any number of characters from "ws", or a single
  47  * character from "hardsep", can separate items in the list.
  48  */
  49 
  50 char **
  51 #if     defined(__STDC__)
  52 getlist (
  53         char *                  str,
  54         char *                  ws,
  55         char *                  hardsep
  56 )
  57 #else
  58 getlist (str, ws, hardsep)
  59         register char           *str,
  60                                 *ws;
  61         char                    *hardsep;
  62 #endif
  63 {
  64         register char           **list,
  65                                 *p,
  66                                 *sep,
  67                                 c;
  68 
  69         int                     n,
  70                                 len;
  71 
  72         char                    buf[10];
  73 
  74 
  75         if (!str || !*str)
  76                 return (0);
  77 
  78         /*
  79          * Construct in "sep" the full list of characters that
  80          * can separate items in the list. Avoid a "malloc()"
  81          * if possible.
  82          */
  83         len = strlen(ws) + strlen(hardsep) + 1;
  84         if (len > sizeof(buf)) {
  85                 if (!(sep = Malloc(len))) {
  86                         errno = ENOMEM;
  87                         return (0);
  88                 }
  89         } else
  90                 sep = buf;
  91         strcpy (sep, hardsep);
  92         strcat (sep, ws);
  93 
  94         /*
  95          * Skip leading white-space.
  96          */
  97         str += strspn(str, ws);
  98         if (!*str)
  99                 return (0);
 100 
 101         /*
 102          * Strip trailing white-space.
 103          */
 104         p = strchr(str, '\0');
 105         while (--p != str && strchr(ws, *p))
 106                 ;
 107         *++p = 0;
 108 
 109         /*
 110          * Pass 1: Count the number of items in the list.
 111          */
 112         for (n = 0, p = str; *p; ) {
 113                 if ((c = *p++) == '\\')
 114                         p++;
 115                 else
 116                         if (strchr(sep, c)) {
 117                                 n++;
 118                                 p += strspn(p, ws);
 119                                 if (
 120                                         !strchr(hardsep, c)
 121                                      && strchr(hardsep, *p)
 122                                 ) {
 123                                         p++;
 124                                         p += strspn(p, ws);
 125                                 }
 126                         }
 127         }
 128 
 129         /*
 130          * Pass 2: Create the list.
 131          */
 132 
 133         /*
 134          * Pass 1 counted the number of list separaters, so
 135          * add 2 to the count (includes 1 for terminating null).
 136          */
 137         if (!(list = (char **)Malloc((n+2) * sizeof(char *)))) {
 138                 errno = ENOMEM;
 139                 goto Done;
 140         }
 141 
 142         /*
 143          * This loop will copy all but the last item.
 144          */
 145         for (n = 0, p = str; *p; )
 146                 if ((c = *p++) == '\\')
 147                         p++;
 148                 else
 149                         if (strchr(sep, c)) {
 150 
 151                                 p[-1] = 0;
 152                                 list[n++] = unq_strdup(str, sep);
 153                                 p[-1] = c;
 154 
 155                                 p += strspn(p, ws);
 156                                 if (
 157                                         !strchr(hardsep, c)
 158                                      && strchr(hardsep, *p)
 159                                 ) {
 160                                         p++;
 161                                         p += strspn(p, ws);
 162                                 }
 163                                 str = p;
 164 
 165                         }
 166 
 167         list[n++] = unq_strdup(str, sep);
 168 
 169         list[n] = 0;
 170 
 171 Done:   if (sep != buf)
 172                 Free (sep);
 173         return (list);
 174 }
 175 
 176 /**
 177  ** unq_strdup()
 178  **/
 179 
 180 static char *
 181 #if     defined(__STDC__)
 182 unq_strdup (
 183         char *                  str,
 184         char *                  sep
 185 )
 186 #else
 187 unq_strdup (str, sep)
 188         char                    *str,
 189                                 *sep;
 190 #endif
 191 {
 192         register int            len     = 0;
 193 
 194         register char           *p,
 195                                 *q,
 196                                 *ret;
 197 
 198 
 199         for (p = str; *p; p++)
 200                 if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
 201                         len++;
 202         if (!(q = ret = Malloc(len + 1)))
 203                 return (0);
 204         for (p = str; *p; p++)
 205                 if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
 206                         *q++ = *p;
 207         *q = 0;
 208         return (ret);
 209 }