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) 1988 AT&T     */
  23 /*        All Rights Reserved   */
  24 
  25 
  26 /*
  27  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  28  * Use is subject to license terms.
  29  */
  30 
  31 #pragma ident   "%Z%%M% %I%     %E% SMI"        /* SVr4.0 1.2   */
  32 
  33 /*LINTLIBRARY*/
  34 
  35 #include <sys/types.h>
  36 #include <stdlib.h>
  37 #include "utility.h"
  38 
  39 /* this code was taken from REGCMP(3X) */
  40 
  41 #define SSIZE   16
  42 #define TGRP    48
  43 #define A256    02
  44 #define ZERO    01
  45 #define NBRA    10
  46 #define CIRCFL  32;
  47 #define SLOP    5
  48 #define FEOF    0 /* This was originally EOF but it clashes with the header */
  49                         /* definition so it was changed to FEOF */
  50 
  51 #define CBRA    60
  52 #define GRP     40
  53 #define SGRP    56
  54 #define PGRP    68
  55 #define EGRP    44
  56 #define RNGE    03
  57 #define CCHR    20
  58 #define CDOT    64
  59 #define CCL     24
  60 #define NCCL    8
  61 #define CDOL    28
  62 #define FCEOF   52 /* This was originally CEOF but it clashes with the header */
  63                         /* definition so it was changed to FCEOF */
  64 #define CKET    12
  65 
  66 #define STAR    01
  67 #define PLUS    02
  68 #define MINUS   16
  69 
  70 intptr_t        *__sp_;
  71 intptr_t        *__stmax;
  72 int     __i_size;
  73 
  74 /*ARGSUSED2*/
  75 char *
  76 libform_regcmp(char *cs1, char *cs2)
  77 {
  78         char c;
  79         char *ep, *sp;
  80         int *adx;
  81         int i, cflg;
  82         char *lastep, *sep, *eptr;
  83         int nbra, ngrp;
  84         int cclcnt;
  85         intptr_t stack[SSIZE];
  86 
  87         __sp_ = stack;
  88         *__sp_ = -1;
  89         __stmax = &stack[SSIZE];
  90 
  91         adx = (int *)&cs1;
  92         i = nbra = ngrp = 0;
  93         while (*adx)
  94                 i += __size((char *)(intptr_t)*adx++);
  95         adx = (int *)&cs1;
  96         sp = (char *)(intptr_t)*adx++;
  97         if ((sep = ep = malloc((unsigned)(2 * i + SLOP))) == NULL)
  98                 return (NULL);
  99         if ((c = *sp++) == FEOF)
 100                 goto cerror;
 101         if (c == '^') {
 102                 c = *sp++;
 103                 *ep++ = CIRCFL;
 104         }
 105         if ((c == '*') || (c == '+') || (c == '{'))
 106                 goto cerror;
 107         sp--;
 108         for (;;) {
 109                 if ((c = *sp++) == FEOF) {
 110                         if (*adx) {
 111                                 sp = (char *)(intptr_t)*adx++;
 112                                 continue;
 113                         }
 114                         *ep++ = FCEOF;
 115                         if (--nbra > NBRA || *__sp_ != -1)
 116                                 goto cerror;
 117                         __i_size = (int) (ep - sep);
 118                         return (sep);
 119                 }
 120                 if ((c != '*') && (c != '{') && (c != '+'))
 121                         lastep = ep;
 122                 switch (c) {
 123 
 124                 case '(':
 125                         if (!__rpush(ep)) goto cerror;
 126                         *ep++ = CBRA;
 127                         *ep++ = -1;
 128                         continue;
 129                 case ')':
 130                         if (!(eptr = (char *)__rpop())) goto cerror;
 131                         if ((c = *sp++) == '$') {
 132                                 if ('0' > (c = *sp++) || c > '9')
 133                                         goto cerror;
 134                                 *ep++ = CKET;
 135                                 *ep++ = *++eptr = nbra++;
 136                                 *ep++ = (c-'0');
 137                                 continue;
 138                         }
 139                         *ep++ = EGRP;
 140                         *ep++ = ngrp++;
 141                         sp--;
 142                         switch (c) {
 143                         case '+':
 144                                 *eptr = PGRP;
 145                                 break;
 146                         case '*':
 147                                 *eptr = SGRP;
 148                                 break;
 149                         case '{':
 150                                 *eptr = TGRP;
 151                                 break;
 152                         default:
 153                                 *eptr = GRP;
 154                                 continue;
 155                         }
 156                         i = (int) (ep - eptr - 2);
 157                         for (cclcnt = 0; i >= 256; cclcnt++)
 158                                 i -= 256;
 159                         if (cclcnt > 3) goto cerror;
 160                         *eptr |= cclcnt;
 161                         *++eptr = (char) i;
 162                         continue;
 163 
 164                 case '\\':
 165                         *ep++ = CCHR;
 166                         if ((c = *sp++) == FEOF)
 167                                 goto cerror;
 168                         *ep++ = c;
 169                         continue;
 170 
 171                 case '{':
 172                         *lastep |= RNGE;
 173                         cflg = 0;
 174                 nlim:
 175                         if ((c = *sp++) == '}') goto cerror;
 176                         i = 0;
 177                         do {
 178                                 if ('0' <= c && c <= '9')
 179                                         i = (i*10+(c-'0'));
 180                                 else goto cerror;
 181                         } while (((c = *sp++) != '}') && (c != ','));
 182                         if (i > 255) goto cerror;
 183                         *ep++ = (char) i;
 184                         if (c == ',') {
 185                                 if (cflg++) goto cerror;
 186                                 if ((c = *sp++) == '}') {
 187                                         *ep++ = -1;
 188                                         continue;
 189                                 } else {
 190                                         sp--;
 191                                         goto nlim;
 192                                 }
 193                         }
 194                         if (!cflg)
 195                                 *ep++ = (char) i;
 196                         else if ((ep[-1]&0377) < (ep[-2]&0377))
 197                                 goto cerror;
 198                         continue;
 199 
 200                 case '.':
 201                         *ep++ = CDOT;
 202                         continue;
 203 
 204                 case '+':
 205                         if (*lastep == CBRA || *lastep == CKET)
 206                                 goto cerror;
 207                         *lastep |= PLUS;
 208                         continue;
 209 
 210                 case '*':
 211                         if (*lastep == CBRA || *lastep == CKET)
 212                         goto cerror;
 213                         *lastep |= STAR;
 214                         continue;
 215 
 216                 case '$':
 217                         if ((*sp != FEOF) || (*adx))
 218                                 goto defchar;
 219                         *ep++ = CDOL;
 220                         continue;
 221 
 222                 case '[':
 223                         *ep++ = CCL;
 224                         *ep++ = 0;
 225                         cclcnt = 1;
 226                         if ((c = *sp++) == '^') {
 227                                 c = *sp++;
 228                                 ep[-2] = NCCL;
 229                         }
 230                         do {
 231                                 if (c == FEOF)
 232                                         goto cerror;
 233                                 if ((c == '-') && (cclcnt > 1) &&
 234                                     (*sp != ']')) {
 235                                         *ep = ep[-1];
 236                                         ep++;
 237                                         ep[-2] = MINUS;
 238                                         cclcnt++;
 239                                         continue;
 240                                 }
 241                                 *ep++ = c;
 242                                 cclcnt++;
 243                         } while ((c = *sp++) != ']');
 244                         lastep[1] = (char) cclcnt;
 245                         continue;
 246 
 247                 defchar:
 248                 default:
 249                         *ep++ = CCHR;
 250                         *ep++ = c;
 251                 }
 252         }
 253 cerror:
 254         free(sep);
 255         return (0);
 256 }
 257 
 258 int
 259 __size(char *strg)
 260 {
 261         int     i;
 262 
 263         i = 1;
 264         while (*strg++)
 265                 i++;
 266         return (i);
 267 }
 268 
 269 intptr_t
 270 __rpop(void)
 271 {
 272         return ((*__sp_ == -1)?0:*__sp_--);
 273 }
 274 
 275 int
 276 __rpush(char *ptr)
 277 {
 278         if (__sp_ >= __stmax)
 279                 return (0);
 280         *++__sp_ = (intptr_t)ptr;
 281         return (1);
 282 }