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