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 
  23 /*
  24  *      Copyright 2015 Gary Mills
  25  */
  26 
  27 /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T     */
  28 /*        All Rights Reserved   */
  29 
  30 
  31 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
  32 
  33 #include "string.h"
  34 #include "errno.h"
  35 #include "stdlib.h"
  36 
  37 #include "lp.h"
  38 
  39 #if     defined(__STDC__)
  40 static char             *unq_strdup ( char * , char * );
  41 #else
  42 static char             *unq_strdup();
  43 #endif
  44 
  45 /**
  46  ** getlist() - CONSTRUCT LIST FROM STRING
  47  **/
  48 
  49 /*
  50  * Any number of characters from "ws", or a single
  51  * character from "hardsep", can separate items in the list.
  52  */
  53 
  54 char **
  55 #if     defined(__STDC__)
  56 getlist (
  57         char *                  str,
  58         char *                  ws,
  59         char *                  hardsep
  60 )
  61 #else
  62 getlist (str, ws, hardsep)
  63         register char           *str,
  64                                 *ws;
  65         char                    *hardsep;
  66 #endif
  67 {
  68         register char           **list,
  69                                 *p,
  70                                 *sep,
  71                                 c;
  72 
  73         int                     n,
  74                                 len;
  75 
  76         char                    buf[10];
  77 
  78 
  79         char                    *copy,
  80                                 *begin;
  81 
  82         if (!str || !*str)
  83                 return (0);
  84 
  85         /*
  86          * Construct in "sep" the full list of characters that
  87          * can separate items in the list. Avoid a "malloc()"
  88          * if possible.
  89          */
  90         len = strlen(ws) + strlen(hardsep) + 1;
  91         if (len > sizeof(buf)) {
  92                 if (!(sep = Malloc(len))) {
  93                         errno = ENOMEM;
  94                         return (0);
  95                 }
  96         } else
  97                 sep = buf;
  98         strcpy (sep, hardsep);
  99         strcat (sep, ws);
 100 
 101         /*
 102          * Copy the input string because getlist() sometimes writes to it.
 103          */
 104         if (!(begin = Strdup(str))) {
 105                 errno = ENOMEM;
 106                 return (0);
 107         }
 108         copy = begin;
 109 
 110         /*
 111          * Skip leading white-space.
 112          */
 113         copy += strspn(copy, ws);
 114         if (!*copy) {
 115                 Free (begin);
 116                 return (0);
 117         }
 118 
 119         /*
 120          * Strip trailing white-space.
 121          */
 122         p = strchr(copy, '\0');
 123         while (--p != copy && strchr(ws, *p))
 124                 ;
 125         *++p = 0;
 126 
 127         /*
 128          * Pass 1: Count the number of items in the list.
 129          */
 130         for (n = 0, p = copy; *p; ) {
 131                 if ((c = *p++) == '\\')
 132                         p++;
 133                 else
 134                         if (strchr(sep, c)) {
 135                                 n++;
 136                                 p += strspn(p, ws);
 137                                 if (
 138                                         !strchr(hardsep, c)
 139                                      && strchr(hardsep, *p)
 140                                 ) {
 141                                         p++;
 142                                         p += strspn(p, ws);
 143                                 }
 144                         }
 145         }
 146 
 147         /*
 148          * Pass 2: Create the list.
 149          */
 150 
 151         /*
 152          * Pass 1 counted the number of list separaters, so
 153          * add 2 to the count (includes 1 for terminating null).
 154          */
 155         if (!(list = (char **)Malloc((n+2) * sizeof(char *)))) {
 156                 errno = ENOMEM;
 157                 goto Done;
 158         }
 159 
 160         /*
 161          * This loop will copy all but the last item.
 162          */
 163         for (n = 0, p = copy; *p; )
 164                 if ((c = *p++) == '\\')
 165                         p++;
 166                 else
 167                         if (strchr(sep, c)) {
 168 
 169                                 p[-1] = 0;
 170                                 list[n++] = unq_strdup(copy, sep);
 171                                 p[-1] = c;
 172 
 173                                 p += strspn(p, ws);
 174                                 if (
 175                                         !strchr(hardsep, c)
 176                                      && strchr(hardsep, *p)
 177                                 ) {
 178                                         p++;
 179                                         p += strspn(p, ws);
 180                                 }
 181                                 copy = p;
 182 
 183                         }
 184 
 185         list[n++] = unq_strdup(copy, sep);
 186 
 187         list[n] = 0;
 188 
 189 Done:   if (sep != buf)
 190                 Free (sep);
 191         Free (begin);
 192         return (list);
 193 }
 194 
 195 /**
 196  ** unq_strdup()
 197  **/
 198 
 199 static char *
 200 #if     defined(__STDC__)
 201 unq_strdup (
 202         char *                  str,
 203         char *                  sep
 204 )
 205 #else
 206 unq_strdup (str, sep)
 207         char                    *str,
 208                                 *sep;
 209 #endif
 210 {
 211         register int            len     = 0;
 212 
 213         register char           *p,
 214                                 *q,
 215                                 *ret;
 216 
 217 
 218         for (p = str; *p; p++)
 219                 if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
 220                         len++;
 221         if (!(q = ret = Malloc(len + 1)))
 222                 return (0);
 223         for (p = str; *p; p++)
 224                 if (*p != '\\' || !p[1] || !strchr(sep, p[1]))
 225                         *q++ = *p;
 226         *q = 0;
 227         return (ret);
 228 }