Home | History | Annotate | Line # | Download | only in ure
ure.c revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  yamt /* $OpenLDAP: pkg/ldap/libraries/liblunicode/ure/ure.c,v 1.17.2.3 2008/02/11 23:26:42 kurt Exp $ */
      2  1.1.1.1.2.2  yamt /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      3  1.1.1.1.2.2  yamt  *
      4  1.1.1.1.2.2  yamt  * Copyright 1998-2008 The OpenLDAP Foundation.
      5  1.1.1.1.2.2  yamt  * All rights reserved.
      6  1.1.1.1.2.2  yamt  *
      7  1.1.1.1.2.2  yamt  * Redistribution and use in source and binary forms, with or without
      8  1.1.1.1.2.2  yamt  * modification, are permitted only as authorized by the OpenLDAP
      9  1.1.1.1.2.2  yamt  * Public License.
     10  1.1.1.1.2.2  yamt  *
     11  1.1.1.1.2.2  yamt  * A copy of this license is available in file LICENSE in the
     12  1.1.1.1.2.2  yamt  * top-level directory of the distribution or, alternatively, at
     13  1.1.1.1.2.2  yamt  * <http://www.OpenLDAP.org/license.html>.
     14  1.1.1.1.2.2  yamt  */
     15  1.1.1.1.2.2  yamt /* Copyright 1997, 1998, 1999 Computing Research Labs,
     16  1.1.1.1.2.2  yamt  * New Mexico State University
     17  1.1.1.1.2.2  yamt  *
     18  1.1.1.1.2.2  yamt  * Permission is hereby granted, free of charge, to any person obtaining a
     19  1.1.1.1.2.2  yamt  * copy of this software and associated documentation files (the "Software"),
     20  1.1.1.1.2.2  yamt  * to deal in the Software without restriction, including without limitation
     21  1.1.1.1.2.2  yamt  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     22  1.1.1.1.2.2  yamt  * and/or sell copies of the Software, and to permit persons to whom the
     23  1.1.1.1.2.2  yamt  * Software is furnished to do so, subject to the following conditions:
     24  1.1.1.1.2.2  yamt  *
     25  1.1.1.1.2.2  yamt  * The above copyright notice and this permission notice shall be included in
     26  1.1.1.1.2.2  yamt  * all copies or substantial portions of the Software.
     27  1.1.1.1.2.2  yamt  *
     28  1.1.1.1.2.2  yamt  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     29  1.1.1.1.2.2  yamt  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     30  1.1.1.1.2.2  yamt  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     31  1.1.1.1.2.2  yamt  * THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
     32  1.1.1.1.2.2  yamt  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
     33  1.1.1.1.2.2  yamt  * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
     34  1.1.1.1.2.2  yamt  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     35  1.1.1.1.2.2  yamt  */
     36  1.1.1.1.2.2  yamt /* $Id: ure.c,v 1.1.1.1.2.2 2008/06/04 02:04:02 yamt Exp $" */
     37  1.1.1.1.2.2  yamt 
     38  1.1.1.1.2.2  yamt #include "portable.h"
     39  1.1.1.1.2.2  yamt 
     40  1.1.1.1.2.2  yamt #include <ac/stdlib.h>
     41  1.1.1.1.2.2  yamt #include <ac/string.h>
     42  1.1.1.1.2.2  yamt #include <ac/unistd.h>
     43  1.1.1.1.2.2  yamt 
     44  1.1.1.1.2.2  yamt #include "ure.h"
     45  1.1.1.1.2.2  yamt 
     46  1.1.1.1.2.2  yamt /*
     47  1.1.1.1.2.2  yamt  * Flags used internally in the DFA.
     48  1.1.1.1.2.2  yamt  */
     49  1.1.1.1.2.2  yamt #define _URE_DFA_CASEFOLD  0x01
     50  1.1.1.1.2.2  yamt #define _URE_DFA_BLANKLINE 0x02
     51  1.1.1.1.2.2  yamt 
     52  1.1.1.1.2.2  yamt static unsigned long cclass_flags[] = {
     53  1.1.1.1.2.2  yamt     0,
     54  1.1.1.1.2.2  yamt     _URE_NONSPACING,
     55  1.1.1.1.2.2  yamt     _URE_COMBINING,
     56  1.1.1.1.2.2  yamt     _URE_NUMDIGIT,
     57  1.1.1.1.2.2  yamt     _URE_NUMOTHER,
     58  1.1.1.1.2.2  yamt     _URE_SPACESEP,
     59  1.1.1.1.2.2  yamt     _URE_LINESEP,
     60  1.1.1.1.2.2  yamt     _URE_PARASEP,
     61  1.1.1.1.2.2  yamt     _URE_CNTRL,
     62  1.1.1.1.2.2  yamt     _URE_PUA,
     63  1.1.1.1.2.2  yamt     _URE_UPPER,
     64  1.1.1.1.2.2  yamt     _URE_LOWER,
     65  1.1.1.1.2.2  yamt     _URE_TITLE,
     66  1.1.1.1.2.2  yamt     _URE_MODIFIER,
     67  1.1.1.1.2.2  yamt     _URE_OTHERLETTER,
     68  1.1.1.1.2.2  yamt     _URE_DASHPUNCT,
     69  1.1.1.1.2.2  yamt     _URE_OPENPUNCT,
     70  1.1.1.1.2.2  yamt     _URE_CLOSEPUNCT,
     71  1.1.1.1.2.2  yamt     _URE_OTHERPUNCT,
     72  1.1.1.1.2.2  yamt     _URE_MATHSYM,
     73  1.1.1.1.2.2  yamt     _URE_CURRENCYSYM,
     74  1.1.1.1.2.2  yamt     _URE_OTHERSYM,
     75  1.1.1.1.2.2  yamt     _URE_LTR,
     76  1.1.1.1.2.2  yamt     _URE_RTL,
     77  1.1.1.1.2.2  yamt     _URE_EURONUM,
     78  1.1.1.1.2.2  yamt     _URE_EURONUMSEP,
     79  1.1.1.1.2.2  yamt     _URE_EURONUMTERM,
     80  1.1.1.1.2.2  yamt     _URE_ARABNUM,
     81  1.1.1.1.2.2  yamt     _URE_COMMONSEP,
     82  1.1.1.1.2.2  yamt     _URE_BLOCKSEP,
     83  1.1.1.1.2.2  yamt     _URE_SEGMENTSEP,
     84  1.1.1.1.2.2  yamt     _URE_WHITESPACE,
     85  1.1.1.1.2.2  yamt     _URE_OTHERNEUT,
     86  1.1.1.1.2.2  yamt };
     87  1.1.1.1.2.2  yamt 
     88  1.1.1.1.2.2  yamt /*
     89  1.1.1.1.2.2  yamt  * Symbol types for the DFA.
     90  1.1.1.1.2.2  yamt  */
     91  1.1.1.1.2.2  yamt #define _URE_ANY_CHAR   1
     92  1.1.1.1.2.2  yamt #define _URE_CHAR       2
     93  1.1.1.1.2.2  yamt #define _URE_CCLASS     3
     94  1.1.1.1.2.2  yamt #define _URE_NCCLASS    4
     95  1.1.1.1.2.2  yamt #define _URE_BOL_ANCHOR 5
     96  1.1.1.1.2.2  yamt #define _URE_EOL_ANCHOR 6
     97  1.1.1.1.2.2  yamt 
     98  1.1.1.1.2.2  yamt /*
     99  1.1.1.1.2.2  yamt  * Op codes for converting the NFA to a DFA.
    100  1.1.1.1.2.2  yamt  */
    101  1.1.1.1.2.2  yamt #define _URE_SYMBOL     10
    102  1.1.1.1.2.2  yamt #define _URE_PAREN      11
    103  1.1.1.1.2.2  yamt #define _URE_QUEST      12
    104  1.1.1.1.2.2  yamt #define _URE_STAR       13
    105  1.1.1.1.2.2  yamt #define _URE_PLUS       14
    106  1.1.1.1.2.2  yamt #define _URE_ONE        15
    107  1.1.1.1.2.2  yamt #define _URE_AND        16
    108  1.1.1.1.2.2  yamt #define _URE_OR         17
    109  1.1.1.1.2.2  yamt 
    110  1.1.1.1.2.2  yamt #define _URE_NOOP       0xffff
    111  1.1.1.1.2.2  yamt 
    112  1.1.1.1.2.2  yamt #define _URE_REGSTART 0x8000
    113  1.1.1.1.2.2  yamt #define _URE_REGEND   0x4000
    114  1.1.1.1.2.2  yamt 
    115  1.1.1.1.2.2  yamt /*
    116  1.1.1.1.2.2  yamt  * Structure used to handle a compacted range of characters.
    117  1.1.1.1.2.2  yamt  */
    118  1.1.1.1.2.2  yamt typedef struct {
    119  1.1.1.1.2.2  yamt     ucs4_t min_code;
    120  1.1.1.1.2.2  yamt     ucs4_t max_code;
    121  1.1.1.1.2.2  yamt } _ure_range_t;
    122  1.1.1.1.2.2  yamt 
    123  1.1.1.1.2.2  yamt typedef struct {
    124  1.1.1.1.2.2  yamt     _ure_range_t *ranges;
    125  1.1.1.1.2.2  yamt     ucs2_t ranges_used;
    126  1.1.1.1.2.2  yamt     ucs2_t ranges_size;
    127  1.1.1.1.2.2  yamt } _ure_ccl_t;
    128  1.1.1.1.2.2  yamt 
    129  1.1.1.1.2.2  yamt typedef union {
    130  1.1.1.1.2.2  yamt     ucs4_t chr;
    131  1.1.1.1.2.2  yamt     _ure_ccl_t ccl;
    132  1.1.1.1.2.2  yamt } _ure_sym_t;
    133  1.1.1.1.2.2  yamt 
    134  1.1.1.1.2.2  yamt /*
    135  1.1.1.1.2.2  yamt  * This is a general element structure used for expressions and stack
    136  1.1.1.1.2.2  yamt  * elements.
    137  1.1.1.1.2.2  yamt  */
    138  1.1.1.1.2.2  yamt typedef struct {
    139  1.1.1.1.2.2  yamt     ucs2_t reg;
    140  1.1.1.1.2.2  yamt     ucs2_t onstack;
    141  1.1.1.1.2.2  yamt     ucs2_t type;
    142  1.1.1.1.2.2  yamt     ucs2_t lhs;
    143  1.1.1.1.2.2  yamt     ucs2_t rhs;
    144  1.1.1.1.2.2  yamt } _ure_elt_t;
    145  1.1.1.1.2.2  yamt 
    146  1.1.1.1.2.2  yamt /*
    147  1.1.1.1.2.2  yamt  * This is a structure used to track a list or a stack of states.
    148  1.1.1.1.2.2  yamt  */
    149  1.1.1.1.2.2  yamt typedef struct {
    150  1.1.1.1.2.2  yamt     ucs2_t *slist;
    151  1.1.1.1.2.2  yamt     ucs2_t slist_size;
    152  1.1.1.1.2.2  yamt     ucs2_t slist_used;
    153  1.1.1.1.2.2  yamt } _ure_stlist_t;
    154  1.1.1.1.2.2  yamt 
    155  1.1.1.1.2.2  yamt /*
    156  1.1.1.1.2.2  yamt  * Structure to track the list of unique states for a symbol
    157  1.1.1.1.2.2  yamt  * during reduction.
    158  1.1.1.1.2.2  yamt  */
    159  1.1.1.1.2.2  yamt typedef struct {
    160  1.1.1.1.2.2  yamt     ucs2_t id;
    161  1.1.1.1.2.2  yamt     ucs2_t type;
    162  1.1.1.1.2.2  yamt     unsigned long mods;
    163  1.1.1.1.2.2  yamt     unsigned long props;
    164  1.1.1.1.2.2  yamt     _ure_sym_t sym;
    165  1.1.1.1.2.2  yamt     _ure_stlist_t states;
    166  1.1.1.1.2.2  yamt } _ure_symtab_t;
    167  1.1.1.1.2.2  yamt 
    168  1.1.1.1.2.2  yamt /*
    169  1.1.1.1.2.2  yamt  * Structure to hold a single state.
    170  1.1.1.1.2.2  yamt  */
    171  1.1.1.1.2.2  yamt typedef struct {
    172  1.1.1.1.2.2  yamt     ucs2_t id;
    173  1.1.1.1.2.2  yamt     ucs2_t accepting;
    174  1.1.1.1.2.2  yamt     ucs2_t pad;
    175  1.1.1.1.2.2  yamt     _ure_stlist_t st;
    176  1.1.1.1.2.2  yamt     _ure_elt_t *trans;
    177  1.1.1.1.2.2  yamt     ucs2_t trans_size;
    178  1.1.1.1.2.2  yamt     ucs2_t trans_used;
    179  1.1.1.1.2.2  yamt } _ure_state_t;
    180  1.1.1.1.2.2  yamt 
    181  1.1.1.1.2.2  yamt /*
    182  1.1.1.1.2.2  yamt  * Structure used for keeping lists of states.
    183  1.1.1.1.2.2  yamt  */
    184  1.1.1.1.2.2  yamt typedef struct {
    185  1.1.1.1.2.2  yamt     _ure_state_t *states;
    186  1.1.1.1.2.2  yamt     ucs2_t states_size;
    187  1.1.1.1.2.2  yamt     ucs2_t states_used;
    188  1.1.1.1.2.2  yamt } _ure_statetable_t;
    189  1.1.1.1.2.2  yamt 
    190  1.1.1.1.2.2  yamt /*
    191  1.1.1.1.2.2  yamt  * Structure to track pairs of DFA states when equivalent states are
    192  1.1.1.1.2.2  yamt  * merged.
    193  1.1.1.1.2.2  yamt  */
    194  1.1.1.1.2.2  yamt typedef struct {
    195  1.1.1.1.2.2  yamt     ucs2_t l;
    196  1.1.1.1.2.2  yamt     ucs2_t r;
    197  1.1.1.1.2.2  yamt } _ure_equiv_t;
    198  1.1.1.1.2.2  yamt 
    199  1.1.1.1.2.2  yamt /*
    200  1.1.1.1.2.2  yamt  * Structure used for constructing the NFA and reducing to a minimal DFA.
    201  1.1.1.1.2.2  yamt  */
    202  1.1.1.1.2.2  yamt typedef struct _ure_buffer_t {
    203  1.1.1.1.2.2  yamt     int reducing;
    204  1.1.1.1.2.2  yamt     int error;
    205  1.1.1.1.2.2  yamt     unsigned long flags;
    206  1.1.1.1.2.2  yamt 
    207  1.1.1.1.2.2  yamt     _ure_stlist_t stack;
    208  1.1.1.1.2.2  yamt 
    209  1.1.1.1.2.2  yamt     /*
    210  1.1.1.1.2.2  yamt      * Table of unique symbols encountered.
    211  1.1.1.1.2.2  yamt      */
    212  1.1.1.1.2.2  yamt     _ure_symtab_t *symtab;
    213  1.1.1.1.2.2  yamt     ucs2_t symtab_size;
    214  1.1.1.1.2.2  yamt     ucs2_t symtab_used;
    215  1.1.1.1.2.2  yamt 
    216  1.1.1.1.2.2  yamt     /*
    217  1.1.1.1.2.2  yamt      * Tracks the unique expressions generated for the NFA and when the NFA is
    218  1.1.1.1.2.2  yamt      * reduced.
    219  1.1.1.1.2.2  yamt      */
    220  1.1.1.1.2.2  yamt     _ure_elt_t *expr;
    221  1.1.1.1.2.2  yamt     ucs2_t expr_used;
    222  1.1.1.1.2.2  yamt     ucs2_t expr_size;
    223  1.1.1.1.2.2  yamt 
    224  1.1.1.1.2.2  yamt     /*
    225  1.1.1.1.2.2  yamt      * The reduced table of unique groups of NFA states.
    226  1.1.1.1.2.2  yamt      */
    227  1.1.1.1.2.2  yamt     _ure_statetable_t states;
    228  1.1.1.1.2.2  yamt 
    229  1.1.1.1.2.2  yamt     /*
    230  1.1.1.1.2.2  yamt      * Tracks states when equivalent states are merged.
    231  1.1.1.1.2.2  yamt      */
    232  1.1.1.1.2.2  yamt     _ure_equiv_t *equiv;
    233  1.1.1.1.2.2  yamt     ucs2_t equiv_used;
    234  1.1.1.1.2.2  yamt     ucs2_t equiv_size;
    235  1.1.1.1.2.2  yamt } _ure_buffer_t;
    236  1.1.1.1.2.2  yamt 
    237  1.1.1.1.2.2  yamt typedef struct {
    238  1.1.1.1.2.2  yamt     ucs2_t symbol;
    239  1.1.1.1.2.2  yamt     ucs2_t next_state;
    240  1.1.1.1.2.2  yamt } _ure_trans_t;
    241  1.1.1.1.2.2  yamt 
    242  1.1.1.1.2.2  yamt typedef struct {
    243  1.1.1.1.2.2  yamt     ucs2_t accepting;
    244  1.1.1.1.2.2  yamt     ucs2_t ntrans;
    245  1.1.1.1.2.2  yamt     _ure_trans_t *trans;
    246  1.1.1.1.2.2  yamt } _ure_dstate_t;
    247  1.1.1.1.2.2  yamt 
    248  1.1.1.1.2.2  yamt typedef struct _ure_dfa_t {
    249  1.1.1.1.2.2  yamt     unsigned long flags;
    250  1.1.1.1.2.2  yamt 
    251  1.1.1.1.2.2  yamt     _ure_symtab_t *syms;
    252  1.1.1.1.2.2  yamt     ucs2_t nsyms;
    253  1.1.1.1.2.2  yamt 
    254  1.1.1.1.2.2  yamt     _ure_dstate_t *states;
    255  1.1.1.1.2.2  yamt     ucs2_t nstates;
    256  1.1.1.1.2.2  yamt 
    257  1.1.1.1.2.2  yamt     _ure_trans_t *trans;
    258  1.1.1.1.2.2  yamt     ucs2_t ntrans;
    259  1.1.1.1.2.2  yamt } _ure_dfa_t;
    260  1.1.1.1.2.2  yamt 
    261  1.1.1.1.2.2  yamt /*************************************************************************
    262  1.1.1.1.2.2  yamt  *
    263  1.1.1.1.2.2  yamt  * Functions.
    264  1.1.1.1.2.2  yamt  *
    265  1.1.1.1.2.2  yamt  *************************************************************************/
    266  1.1.1.1.2.2  yamt 
    267  1.1.1.1.2.2  yamt static void
    268  1.1.1.1.2.2  yamt _ure_memmove(char *dest, char *src, unsigned long bytes)
    269  1.1.1.1.2.2  yamt {
    270  1.1.1.1.2.2  yamt     long i, j;
    271  1.1.1.1.2.2  yamt 
    272  1.1.1.1.2.2  yamt     i = (long) bytes;
    273  1.1.1.1.2.2  yamt     j = i & 7;
    274  1.1.1.1.2.2  yamt     i = (i + 7) >> 3;
    275  1.1.1.1.2.2  yamt 
    276  1.1.1.1.2.2  yamt     /*
    277  1.1.1.1.2.2  yamt      * Do a memmove using Ye Olde Duff's Device for efficiency.
    278  1.1.1.1.2.2  yamt      */
    279  1.1.1.1.2.2  yamt     if (src < dest) {
    280  1.1.1.1.2.2  yamt         src += bytes;
    281  1.1.1.1.2.2  yamt         dest += bytes;
    282  1.1.1.1.2.2  yamt 
    283  1.1.1.1.2.2  yamt         switch (j) {
    284  1.1.1.1.2.2  yamt           case 0: do {
    285  1.1.1.1.2.2  yamt               *--dest = *--src;
    286  1.1.1.1.2.2  yamt             case 7: *--dest = *--src;
    287  1.1.1.1.2.2  yamt             case 6: *--dest = *--src;
    288  1.1.1.1.2.2  yamt             case 5: *--dest = *--src;
    289  1.1.1.1.2.2  yamt             case 4: *--dest = *--src;
    290  1.1.1.1.2.2  yamt             case 3: *--dest = *--src;
    291  1.1.1.1.2.2  yamt             case 2: *--dest = *--src;
    292  1.1.1.1.2.2  yamt             case 1: *--dest = *--src;
    293  1.1.1.1.2.2  yamt           } while (--i > 0);
    294  1.1.1.1.2.2  yamt         }
    295  1.1.1.1.2.2  yamt     } else if (src > dest) {
    296  1.1.1.1.2.2  yamt         switch (j) {
    297  1.1.1.1.2.2  yamt           case 0: do {
    298  1.1.1.1.2.2  yamt               *dest++ = *src++;
    299  1.1.1.1.2.2  yamt             case 7: *dest++ = *src++;
    300  1.1.1.1.2.2  yamt             case 6: *dest++ = *src++;
    301  1.1.1.1.2.2  yamt             case 5: *dest++ = *src++;
    302  1.1.1.1.2.2  yamt             case 4: *dest++ = *src++;
    303  1.1.1.1.2.2  yamt             case 3: *dest++ = *src++;
    304  1.1.1.1.2.2  yamt             case 2: *dest++ = *src++;
    305  1.1.1.1.2.2  yamt             case 1: *dest++ = *src++;
    306  1.1.1.1.2.2  yamt           } while (--i > 0);
    307  1.1.1.1.2.2  yamt         }
    308  1.1.1.1.2.2  yamt     }
    309  1.1.1.1.2.2  yamt }
    310  1.1.1.1.2.2  yamt 
    311  1.1.1.1.2.2  yamt static void
    312  1.1.1.1.2.2  yamt _ure_push(ucs2_t v, _ure_buffer_t *b)
    313  1.1.1.1.2.2  yamt {
    314  1.1.1.1.2.2  yamt     _ure_stlist_t *s;
    315  1.1.1.1.2.2  yamt 
    316  1.1.1.1.2.2  yamt     if (b == 0)
    317  1.1.1.1.2.2  yamt       return;
    318  1.1.1.1.2.2  yamt 
    319  1.1.1.1.2.2  yamt     /*
    320  1.1.1.1.2.2  yamt      * If the `reducing' parameter is non-zero, check to see if the value
    321  1.1.1.1.2.2  yamt      * passed is already on the stack.
    322  1.1.1.1.2.2  yamt      */
    323  1.1.1.1.2.2  yamt     if (b->reducing != 0 && b->expr[v].onstack != 0)
    324  1.1.1.1.2.2  yamt       return;
    325  1.1.1.1.2.2  yamt 
    326  1.1.1.1.2.2  yamt     s = &b->stack;
    327  1.1.1.1.2.2  yamt     if (s->slist_used == s->slist_size) {
    328  1.1.1.1.2.2  yamt         if (s->slist_size == 0)
    329  1.1.1.1.2.2  yamt           s->slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3);
    330  1.1.1.1.2.2  yamt         else
    331  1.1.1.1.2.2  yamt           s->slist = (ucs2_t *) realloc((char *) s->slist,
    332  1.1.1.1.2.2  yamt                                         sizeof(ucs2_t) * (s->slist_size + 8));
    333  1.1.1.1.2.2  yamt         s->slist_size += 8;
    334  1.1.1.1.2.2  yamt     }
    335  1.1.1.1.2.2  yamt     s->slist[s->slist_used++] = v;
    336  1.1.1.1.2.2  yamt 
    337  1.1.1.1.2.2  yamt     /*
    338  1.1.1.1.2.2  yamt      * If the `reducing' parameter is non-zero, flag the element as being on
    339  1.1.1.1.2.2  yamt      * the stack.
    340  1.1.1.1.2.2  yamt      */
    341  1.1.1.1.2.2  yamt     if (b->reducing != 0)
    342  1.1.1.1.2.2  yamt       b->expr[v].onstack = 1;
    343  1.1.1.1.2.2  yamt }
    344  1.1.1.1.2.2  yamt 
    345  1.1.1.1.2.2  yamt static ucs2_t
    346  1.1.1.1.2.2  yamt _ure_peek(_ure_buffer_t *b)
    347  1.1.1.1.2.2  yamt {
    348  1.1.1.1.2.2  yamt     if (b == 0 || b->stack.slist_used == 0)
    349  1.1.1.1.2.2  yamt       return _URE_NOOP;
    350  1.1.1.1.2.2  yamt 
    351  1.1.1.1.2.2  yamt     return b->stack.slist[b->stack.slist_used - 1];
    352  1.1.1.1.2.2  yamt }
    353  1.1.1.1.2.2  yamt 
    354  1.1.1.1.2.2  yamt static ucs2_t
    355  1.1.1.1.2.2  yamt _ure_pop(_ure_buffer_t *b)
    356  1.1.1.1.2.2  yamt {
    357  1.1.1.1.2.2  yamt     ucs2_t v;
    358  1.1.1.1.2.2  yamt 
    359  1.1.1.1.2.2  yamt     if (b == 0 || b->stack.slist_used == 0)
    360  1.1.1.1.2.2  yamt       return _URE_NOOP;
    361  1.1.1.1.2.2  yamt 
    362  1.1.1.1.2.2  yamt     v = b->stack.slist[--b->stack.slist_used];
    363  1.1.1.1.2.2  yamt     if (b->reducing)
    364  1.1.1.1.2.2  yamt       b->expr[v].onstack = 0;
    365  1.1.1.1.2.2  yamt 
    366  1.1.1.1.2.2  yamt     return v;
    367  1.1.1.1.2.2  yamt }
    368  1.1.1.1.2.2  yamt 
    369  1.1.1.1.2.2  yamt /*************************************************************************
    370  1.1.1.1.2.2  yamt  *
    371  1.1.1.1.2.2  yamt  * Start symbol parse functions.
    372  1.1.1.1.2.2  yamt  *
    373  1.1.1.1.2.2  yamt  *************************************************************************/
    374  1.1.1.1.2.2  yamt 
    375  1.1.1.1.2.2  yamt /*
    376  1.1.1.1.2.2  yamt  * Parse a comma-separated list of integers that represent character
    377  1.1.1.1.2.2  yamt  * properties.  Combine them into a mask that is returned in the `mask'
    378  1.1.1.1.2.2  yamt  * variable, and return the number of characters consumed.
    379  1.1.1.1.2.2  yamt  */
    380  1.1.1.1.2.2  yamt static unsigned long
    381  1.1.1.1.2.2  yamt _ure_prop_list(ucs2_t *pp, unsigned long limit, unsigned long *mask,
    382  1.1.1.1.2.2  yamt                _ure_buffer_t *b)
    383  1.1.1.1.2.2  yamt {
    384  1.1.1.1.2.2  yamt     unsigned long n, m;
    385  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    386  1.1.1.1.2.2  yamt 
    387  1.1.1.1.2.2  yamt     sp = pp;
    388  1.1.1.1.2.2  yamt     ep = sp + limit;
    389  1.1.1.1.2.2  yamt 
    390  1.1.1.1.2.2  yamt     for (m = n = 0; b->error == _URE_OK && sp < ep; sp++) {
    391  1.1.1.1.2.2  yamt         if (*sp == ',') {
    392  1.1.1.1.2.2  yamt             /*
    393  1.1.1.1.2.2  yamt              * Encountered a comma, so select the next character property flag
    394  1.1.1.1.2.2  yamt              * and reset the number.
    395  1.1.1.1.2.2  yamt              */
    396  1.1.1.1.2.2  yamt             m |= cclass_flags[n];
    397  1.1.1.1.2.2  yamt             n = 0;
    398  1.1.1.1.2.2  yamt         } else if (*sp >= '0' && *sp <= '9')
    399  1.1.1.1.2.2  yamt           /*
    400  1.1.1.1.2.2  yamt            * Encountered a digit, so start or continue building the cardinal
    401  1.1.1.1.2.2  yamt            * that represents the character property flag.
    402  1.1.1.1.2.2  yamt            */
    403  1.1.1.1.2.2  yamt           n = (n * 10) + (*sp - '0');
    404  1.1.1.1.2.2  yamt         else
    405  1.1.1.1.2.2  yamt           /*
    406  1.1.1.1.2.2  yamt            * Encountered something that is not part of the property list.
    407  1.1.1.1.2.2  yamt            * Indicate that we are done.
    408  1.1.1.1.2.2  yamt            */
    409  1.1.1.1.2.2  yamt           break;
    410  1.1.1.1.2.2  yamt 
    411  1.1.1.1.2.2  yamt         /*
    412  1.1.1.1.2.2  yamt          * If a property number greater than 32 occurs, then there is a
    413  1.1.1.1.2.2  yamt          * problem.  Most likely a missing comma separator.
    414  1.1.1.1.2.2  yamt          */
    415  1.1.1.1.2.2  yamt         if (n > 32)
    416  1.1.1.1.2.2  yamt           b->error = _URE_INVALID_PROPERTY;
    417  1.1.1.1.2.2  yamt     }
    418  1.1.1.1.2.2  yamt 
    419  1.1.1.1.2.2  yamt     if (n != 0)
    420  1.1.1.1.2.2  yamt       m |= cclass_flags[n];
    421  1.1.1.1.2.2  yamt 
    422  1.1.1.1.2.2  yamt     /*
    423  1.1.1.1.2.2  yamt      * Set the mask that represents the group of character properties.
    424  1.1.1.1.2.2  yamt      */
    425  1.1.1.1.2.2  yamt     *mask = m;
    426  1.1.1.1.2.2  yamt 
    427  1.1.1.1.2.2  yamt     /*
    428  1.1.1.1.2.2  yamt      * Return the number of characters consumed.
    429  1.1.1.1.2.2  yamt      */
    430  1.1.1.1.2.2  yamt     return sp - pp;
    431  1.1.1.1.2.2  yamt }
    432  1.1.1.1.2.2  yamt 
    433  1.1.1.1.2.2  yamt /*
    434  1.1.1.1.2.2  yamt  * Collect a hex number with 1 to 4 digits and return the number
    435  1.1.1.1.2.2  yamt  * of characters used.
    436  1.1.1.1.2.2  yamt  */
    437  1.1.1.1.2.2  yamt static unsigned long
    438  1.1.1.1.2.2  yamt _ure_hex(ucs2_t *np, unsigned long limit, ucs4_t *n)
    439  1.1.1.1.2.2  yamt {
    440  1.1.1.1.2.2  yamt     ucs2_t i;
    441  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    442  1.1.1.1.2.2  yamt     ucs4_t nn;
    443  1.1.1.1.2.2  yamt 
    444  1.1.1.1.2.2  yamt     sp = np;
    445  1.1.1.1.2.2  yamt     ep = sp + limit;
    446  1.1.1.1.2.2  yamt 
    447  1.1.1.1.2.2  yamt     for (nn = 0, i = 0; i < 4 && sp < ep; i++, sp++) {
    448  1.1.1.1.2.2  yamt         if (*sp >= '0' && *sp <= '9')
    449  1.1.1.1.2.2  yamt           nn = (nn << 4) + (*sp - '0');
    450  1.1.1.1.2.2  yamt         else if (*sp >= 'A' && *sp <= 'F')
    451  1.1.1.1.2.2  yamt           nn = (nn << 4) + ((*sp - 'A') + 10);
    452  1.1.1.1.2.2  yamt         else if (*sp >= 'a' && *sp <= 'f')
    453  1.1.1.1.2.2  yamt           nn = (nn << 4) + ((*sp - 'a') + 10);
    454  1.1.1.1.2.2  yamt         else
    455  1.1.1.1.2.2  yamt           /*
    456  1.1.1.1.2.2  yamt            * Encountered something that is not a hex digit.
    457  1.1.1.1.2.2  yamt            */
    458  1.1.1.1.2.2  yamt           break;
    459  1.1.1.1.2.2  yamt     }
    460  1.1.1.1.2.2  yamt 
    461  1.1.1.1.2.2  yamt     /*
    462  1.1.1.1.2.2  yamt      * Assign the character code collected and return the number of
    463  1.1.1.1.2.2  yamt      * characters used.
    464  1.1.1.1.2.2  yamt      */
    465  1.1.1.1.2.2  yamt     *n = nn;
    466  1.1.1.1.2.2  yamt 
    467  1.1.1.1.2.2  yamt     return sp - np;
    468  1.1.1.1.2.2  yamt }
    469  1.1.1.1.2.2  yamt 
    470  1.1.1.1.2.2  yamt /*
    471  1.1.1.1.2.2  yamt  * Insert a range into a character class, removing duplicates and ordering
    472  1.1.1.1.2.2  yamt  * them in increasing range-start order.
    473  1.1.1.1.2.2  yamt  */
    474  1.1.1.1.2.2  yamt static void
    475  1.1.1.1.2.2  yamt _ure_add_range(_ure_ccl_t *ccl, _ure_range_t *r, _ure_buffer_t *b)
    476  1.1.1.1.2.2  yamt {
    477  1.1.1.1.2.2  yamt     ucs2_t i;
    478  1.1.1.1.2.2  yamt     ucs4_t tmp;
    479  1.1.1.1.2.2  yamt     _ure_range_t *rp;
    480  1.1.1.1.2.2  yamt 
    481  1.1.1.1.2.2  yamt     /*
    482  1.1.1.1.2.2  yamt      * If the `casefold' flag is set, then make sure both endpoints of the
    483  1.1.1.1.2.2  yamt      * range are converted to lower case.
    484  1.1.1.1.2.2  yamt      */
    485  1.1.1.1.2.2  yamt     if (b->flags & _URE_DFA_CASEFOLD) {
    486  1.1.1.1.2.2  yamt         r->min_code = _ure_tolower(r->min_code);
    487  1.1.1.1.2.2  yamt         r->max_code = _ure_tolower(r->max_code);
    488  1.1.1.1.2.2  yamt     }
    489  1.1.1.1.2.2  yamt 
    490  1.1.1.1.2.2  yamt     /*
    491  1.1.1.1.2.2  yamt      * Swap the range endpoints if they are not in increasing order.
    492  1.1.1.1.2.2  yamt      */
    493  1.1.1.1.2.2  yamt     if (r->min_code > r->max_code) {
    494  1.1.1.1.2.2  yamt         tmp = r->min_code;
    495  1.1.1.1.2.2  yamt         r->min_code = r->max_code;
    496  1.1.1.1.2.2  yamt         r->max_code = tmp;
    497  1.1.1.1.2.2  yamt     }
    498  1.1.1.1.2.2  yamt 
    499  1.1.1.1.2.2  yamt     for (i = 0, rp = ccl->ranges;
    500  1.1.1.1.2.2  yamt          i < ccl->ranges_used && r->min_code < rp->min_code; i++, rp++) ;
    501  1.1.1.1.2.2  yamt 
    502  1.1.1.1.2.2  yamt     /*
    503  1.1.1.1.2.2  yamt      * Check for a duplicate.
    504  1.1.1.1.2.2  yamt      */
    505  1.1.1.1.2.2  yamt     if (i < ccl->ranges_used &&
    506  1.1.1.1.2.2  yamt         r->min_code == rp->min_code && r->max_code == rp->max_code)
    507  1.1.1.1.2.2  yamt       return;
    508  1.1.1.1.2.2  yamt 
    509  1.1.1.1.2.2  yamt     if (ccl->ranges_used == ccl->ranges_size) {
    510  1.1.1.1.2.2  yamt         if (ccl->ranges_size == 0)
    511  1.1.1.1.2.2  yamt           ccl->ranges = (_ure_range_t *) malloc(sizeof(_ure_range_t) << 3);
    512  1.1.1.1.2.2  yamt         else
    513  1.1.1.1.2.2  yamt           ccl->ranges = (_ure_range_t *)
    514  1.1.1.1.2.2  yamt               realloc((char *) ccl->ranges,
    515  1.1.1.1.2.2  yamt                       sizeof(_ure_range_t) * (ccl->ranges_size + 8));
    516  1.1.1.1.2.2  yamt         ccl->ranges_size += 8;
    517  1.1.1.1.2.2  yamt     }
    518  1.1.1.1.2.2  yamt 
    519  1.1.1.1.2.2  yamt     rp = ccl->ranges + ccl->ranges_used;
    520  1.1.1.1.2.2  yamt 
    521  1.1.1.1.2.2  yamt     if (i < ccl->ranges_used)
    522  1.1.1.1.2.2  yamt       _ure_memmove((char *) (rp + 1), (char *) rp,
    523  1.1.1.1.2.2  yamt                    sizeof(_ure_range_t) * (ccl->ranges_used - i));
    524  1.1.1.1.2.2  yamt 
    525  1.1.1.1.2.2  yamt     ccl->ranges_used++;
    526  1.1.1.1.2.2  yamt     rp->min_code = r->min_code;
    527  1.1.1.1.2.2  yamt     rp->max_code = r->max_code;
    528  1.1.1.1.2.2  yamt }
    529  1.1.1.1.2.2  yamt 
    530  1.1.1.1.2.2  yamt #define _URE_ALPHA_MASK  (_URE_UPPER|_URE_LOWER|_URE_OTHERLETTER|\
    531  1.1.1.1.2.2  yamt _URE_MODIFIER|_URE_TITLE|_URE_NONSPACING|_URE_COMBINING)
    532  1.1.1.1.2.2  yamt #define _URE_ALNUM_MASK  (_URE_ALPHA_MASK|_URE_NUMDIGIT)
    533  1.1.1.1.2.2  yamt #define _URE_PUNCT_MASK  (_URE_DASHPUNCT|_URE_OPENPUNCT|_URE_CLOSEPUNCT|\
    534  1.1.1.1.2.2  yamt _URE_OTHERPUNCT)
    535  1.1.1.1.2.2  yamt #define _URE_GRAPH_MASK (_URE_NUMDIGIT|_URE_NUMOTHER|_URE_ALPHA_MASK|\
    536  1.1.1.1.2.2  yamt _URE_MATHSYM|_URE_CURRENCYSYM|_URE_OTHERSYM)
    537  1.1.1.1.2.2  yamt #define _URE_PRINT_MASK (_URE_GRAPH_MASK|_URE_SPACESEP)
    538  1.1.1.1.2.2  yamt #define _URE_SPACE_MASK  (_URE_SPACESEP|_URE_LINESEP|_URE_PARASEP)
    539  1.1.1.1.2.2  yamt 
    540  1.1.1.1.2.2  yamt typedef void (*_ure_cclsetup_t)(
    541  1.1.1.1.2.2  yamt     _ure_symtab_t *sym,
    542  1.1.1.1.2.2  yamt     unsigned long mask,
    543  1.1.1.1.2.2  yamt     _ure_buffer_t *b
    544  1.1.1.1.2.2  yamt );
    545  1.1.1.1.2.2  yamt 
    546  1.1.1.1.2.2  yamt typedef struct {
    547  1.1.1.1.2.2  yamt     ucs2_t key;
    548  1.1.1.1.2.2  yamt     unsigned long len;
    549  1.1.1.1.2.2  yamt     unsigned long next;
    550  1.1.1.1.2.2  yamt     _ure_cclsetup_t func;
    551  1.1.1.1.2.2  yamt     unsigned long mask;
    552  1.1.1.1.2.2  yamt } _ure_trie_t;
    553  1.1.1.1.2.2  yamt 
    554  1.1.1.1.2.2  yamt static void
    555  1.1.1.1.2.2  yamt _ure_ccl_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
    556  1.1.1.1.2.2  yamt {
    557  1.1.1.1.2.2  yamt     sym->props |= mask;
    558  1.1.1.1.2.2  yamt }
    559  1.1.1.1.2.2  yamt 
    560  1.1.1.1.2.2  yamt static void
    561  1.1.1.1.2.2  yamt _ure_space_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
    562  1.1.1.1.2.2  yamt {
    563  1.1.1.1.2.2  yamt     _ure_range_t range;
    564  1.1.1.1.2.2  yamt 
    565  1.1.1.1.2.2  yamt     sym->props |= mask;
    566  1.1.1.1.2.2  yamt 
    567  1.1.1.1.2.2  yamt     /*
    568  1.1.1.1.2.2  yamt      * Add the additional characters needed for handling isspace().
    569  1.1.1.1.2.2  yamt      */
    570  1.1.1.1.2.2  yamt     range.min_code = range.max_code = '\t';
    571  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    572  1.1.1.1.2.2  yamt     range.min_code = range.max_code = '\r';
    573  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    574  1.1.1.1.2.2  yamt     range.min_code = range.max_code = '\n';
    575  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    576  1.1.1.1.2.2  yamt     range.min_code = range.max_code = '\f';
    577  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    578  1.1.1.1.2.2  yamt     range.min_code = range.max_code = 0xfeff;
    579  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    580  1.1.1.1.2.2  yamt }
    581  1.1.1.1.2.2  yamt 
    582  1.1.1.1.2.2  yamt static void
    583  1.1.1.1.2.2  yamt _ure_xdigit_setup(_ure_symtab_t *sym, unsigned long mask, _ure_buffer_t *b)
    584  1.1.1.1.2.2  yamt {
    585  1.1.1.1.2.2  yamt     _ure_range_t range;
    586  1.1.1.1.2.2  yamt 
    587  1.1.1.1.2.2  yamt     /*
    588  1.1.1.1.2.2  yamt      * Add the additional characters needed for handling isxdigit().
    589  1.1.1.1.2.2  yamt      */
    590  1.1.1.1.2.2  yamt     range.min_code = '0';
    591  1.1.1.1.2.2  yamt     range.max_code = '9';
    592  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    593  1.1.1.1.2.2  yamt     range.min_code = 'A';
    594  1.1.1.1.2.2  yamt     range.max_code = 'F';
    595  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    596  1.1.1.1.2.2  yamt     range.min_code = 'a';
    597  1.1.1.1.2.2  yamt     range.max_code = 'f';
    598  1.1.1.1.2.2  yamt     _ure_add_range(&sym->sym.ccl, &range, b);
    599  1.1.1.1.2.2  yamt }
    600  1.1.1.1.2.2  yamt 
    601  1.1.1.1.2.2  yamt static _ure_trie_t cclass_trie[] = {
    602  1.1.1.1.2.2  yamt     {0x003a, 1, 1, 0, 0},
    603  1.1.1.1.2.2  yamt     {0x0061, 9, 10, 0, 0},
    604  1.1.1.1.2.2  yamt     {0x0063, 8, 19, 0, 0},
    605  1.1.1.1.2.2  yamt     {0x0064, 7, 24, 0, 0},
    606  1.1.1.1.2.2  yamt     {0x0067, 6, 29, 0, 0},
    607  1.1.1.1.2.2  yamt     {0x006c, 5, 34, 0, 0},
    608  1.1.1.1.2.2  yamt     {0x0070, 4, 39, 0, 0},
    609  1.1.1.1.2.2  yamt     {0x0073, 3, 49, 0, 0},
    610  1.1.1.1.2.2  yamt     {0x0075, 2, 54, 0, 0},
    611  1.1.1.1.2.2  yamt     {0x0078, 1, 59, 0, 0},
    612  1.1.1.1.2.2  yamt     {0x006c, 1, 11, 0, 0},
    613  1.1.1.1.2.2  yamt     {0x006e, 2, 13, 0, 0},
    614  1.1.1.1.2.2  yamt     {0x0070, 1, 16, 0, 0},
    615  1.1.1.1.2.2  yamt     {0x0075, 1, 14, 0, 0},
    616  1.1.1.1.2.2  yamt     {0x006d, 1, 15, 0, 0},
    617  1.1.1.1.2.2  yamt     {0x003a, 1, 16, _ure_ccl_setup, _URE_ALNUM_MASK},
    618  1.1.1.1.2.2  yamt     {0x0068, 1, 17, 0, 0},
    619  1.1.1.1.2.2  yamt     {0x0061, 1, 18, 0, 0},
    620  1.1.1.1.2.2  yamt     {0x003a, 1, 19, _ure_ccl_setup, _URE_ALPHA_MASK},
    621  1.1.1.1.2.2  yamt     {0x006e, 1, 20, 0, 0},
    622  1.1.1.1.2.2  yamt     {0x0074, 1, 21, 0, 0},
    623  1.1.1.1.2.2  yamt     {0x0072, 1, 22, 0, 0},
    624  1.1.1.1.2.2  yamt     {0x006c, 1, 23, 0, 0},
    625  1.1.1.1.2.2  yamt     {0x003a, 1, 24, _ure_ccl_setup, _URE_CNTRL},
    626  1.1.1.1.2.2  yamt     {0x0069, 1, 25, 0, 0},
    627  1.1.1.1.2.2  yamt     {0x0067, 1, 26, 0, 0},
    628  1.1.1.1.2.2  yamt     {0x0069, 1, 27, 0, 0},
    629  1.1.1.1.2.2  yamt     {0x0074, 1, 28, 0, 0},
    630  1.1.1.1.2.2  yamt     {0x003a, 1, 29, _ure_ccl_setup, _URE_NUMDIGIT},
    631  1.1.1.1.2.2  yamt     {0x0072, 1, 30, 0, 0},
    632  1.1.1.1.2.2  yamt     {0x0061, 1, 31, 0, 0},
    633  1.1.1.1.2.2  yamt     {0x0070, 1, 32, 0, 0},
    634  1.1.1.1.2.2  yamt     {0x0068, 1, 33, 0, 0},
    635  1.1.1.1.2.2  yamt     {0x003a, 1, 34, _ure_ccl_setup, _URE_GRAPH_MASK},
    636  1.1.1.1.2.2  yamt     {0x006f, 1, 35, 0, 0},
    637  1.1.1.1.2.2  yamt     {0x0077, 1, 36, 0, 0},
    638  1.1.1.1.2.2  yamt     {0x0065, 1, 37, 0, 0},
    639  1.1.1.1.2.2  yamt     {0x0072, 1, 38, 0, 0},
    640  1.1.1.1.2.2  yamt     {0x003a, 1, 39, _ure_ccl_setup, _URE_LOWER},
    641  1.1.1.1.2.2  yamt     {0x0072, 2, 41, 0, 0},
    642  1.1.1.1.2.2  yamt     {0x0075, 1, 45, 0, 0},
    643  1.1.1.1.2.2  yamt     {0x0069, 1, 42, 0, 0},
    644  1.1.1.1.2.2  yamt     {0x006e, 1, 43, 0, 0},
    645  1.1.1.1.2.2  yamt     {0x0074, 1, 44, 0, 0},
    646  1.1.1.1.2.2  yamt     {0x003a, 1, 45, _ure_ccl_setup, _URE_PRINT_MASK},
    647  1.1.1.1.2.2  yamt     {0x006e, 1, 46, 0, 0},
    648  1.1.1.1.2.2  yamt     {0x0063, 1, 47, 0, 0},
    649  1.1.1.1.2.2  yamt     {0x0074, 1, 48, 0, 0},
    650  1.1.1.1.2.2  yamt     {0x003a, 1, 49, _ure_ccl_setup, _URE_PUNCT_MASK},
    651  1.1.1.1.2.2  yamt     {0x0070, 1, 50, 0, 0},
    652  1.1.1.1.2.2  yamt     {0x0061, 1, 51, 0, 0},
    653  1.1.1.1.2.2  yamt     {0x0063, 1, 52, 0, 0},
    654  1.1.1.1.2.2  yamt     {0x0065, 1, 53, 0, 0},
    655  1.1.1.1.2.2  yamt     {0x003a, 1, 54, _ure_space_setup, _URE_SPACE_MASK},
    656  1.1.1.1.2.2  yamt     {0x0070, 1, 55, 0, 0},
    657  1.1.1.1.2.2  yamt     {0x0070, 1, 56, 0, 0},
    658  1.1.1.1.2.2  yamt     {0x0065, 1, 57, 0, 0},
    659  1.1.1.1.2.2  yamt     {0x0072, 1, 58, 0, 0},
    660  1.1.1.1.2.2  yamt     {0x003a, 1, 59, _ure_ccl_setup, _URE_UPPER},
    661  1.1.1.1.2.2  yamt     {0x0064, 1, 60, 0, 0},
    662  1.1.1.1.2.2  yamt     {0x0069, 1, 61, 0, 0},
    663  1.1.1.1.2.2  yamt     {0x0067, 1, 62, 0, 0},
    664  1.1.1.1.2.2  yamt     {0x0069, 1, 63, 0, 0},
    665  1.1.1.1.2.2  yamt     {0x0074, 1, 64, 0, 0},
    666  1.1.1.1.2.2  yamt     {0x003a, 1, 65, _ure_xdigit_setup, 0},
    667  1.1.1.1.2.2  yamt };
    668  1.1.1.1.2.2  yamt 
    669  1.1.1.1.2.2  yamt /*
    670  1.1.1.1.2.2  yamt  * Probe for one of the POSIX colon delimited character classes in the static
    671  1.1.1.1.2.2  yamt  * trie.
    672  1.1.1.1.2.2  yamt  */
    673  1.1.1.1.2.2  yamt static unsigned long
    674  1.1.1.1.2.2  yamt _ure_posix_ccl(ucs2_t *cp, unsigned long limit, _ure_symtab_t *sym,
    675  1.1.1.1.2.2  yamt                _ure_buffer_t *b)
    676  1.1.1.1.2.2  yamt {
    677  1.1.1.1.2.2  yamt     int i;
    678  1.1.1.1.2.2  yamt     unsigned long n;
    679  1.1.1.1.2.2  yamt     _ure_trie_t *tp;
    680  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    681  1.1.1.1.2.2  yamt 
    682  1.1.1.1.2.2  yamt     /*
    683  1.1.1.1.2.2  yamt      * If the number of characters left is less than 7, then this cannot be
    684  1.1.1.1.2.2  yamt      * interpreted as one of the colon delimited classes.
    685  1.1.1.1.2.2  yamt      */
    686  1.1.1.1.2.2  yamt     if (limit < 7)
    687  1.1.1.1.2.2  yamt       return 0;
    688  1.1.1.1.2.2  yamt 
    689  1.1.1.1.2.2  yamt     sp = cp;
    690  1.1.1.1.2.2  yamt     ep = sp + limit;
    691  1.1.1.1.2.2  yamt     tp = cclass_trie;
    692  1.1.1.1.2.2  yamt     for (i = 0; sp < ep && i < 8; i++, sp++) {
    693  1.1.1.1.2.2  yamt         n = tp->len;
    694  1.1.1.1.2.2  yamt 
    695  1.1.1.1.2.2  yamt         for (; n > 0 && tp->key != *sp; tp++, n--) ;
    696  1.1.1.1.2.2  yamt 
    697  1.1.1.1.2.2  yamt         if (n == 0)
    698  1.1.1.1.2.2  yamt           return 0;
    699  1.1.1.1.2.2  yamt 
    700  1.1.1.1.2.2  yamt         if (*sp == ':' && (i == 6 || i == 7)) {
    701  1.1.1.1.2.2  yamt             sp++;
    702  1.1.1.1.2.2  yamt             break;
    703  1.1.1.1.2.2  yamt         }
    704  1.1.1.1.2.2  yamt         if (sp + 1 < ep)
    705  1.1.1.1.2.2  yamt           tp = cclass_trie + tp->next;
    706  1.1.1.1.2.2  yamt     }
    707  1.1.1.1.2.2  yamt     if (tp->func == 0)
    708  1.1.1.1.2.2  yamt       return 0;
    709  1.1.1.1.2.2  yamt 
    710  1.1.1.1.2.2  yamt     (*tp->func)(sym, tp->mask, b);
    711  1.1.1.1.2.2  yamt 
    712  1.1.1.1.2.2  yamt     return sp - cp;
    713  1.1.1.1.2.2  yamt }
    714  1.1.1.1.2.2  yamt 
    715  1.1.1.1.2.2  yamt /*
    716  1.1.1.1.2.2  yamt  * Construct a list of ranges and return the number of characters consumed.
    717  1.1.1.1.2.2  yamt  */
    718  1.1.1.1.2.2  yamt static unsigned long
    719  1.1.1.1.2.2  yamt _ure_cclass(ucs2_t *cp, unsigned long limit, _ure_symtab_t *symp,
    720  1.1.1.1.2.2  yamt             _ure_buffer_t *b)
    721  1.1.1.1.2.2  yamt {
    722  1.1.1.1.2.2  yamt     int range_end;
    723  1.1.1.1.2.2  yamt     unsigned long n;
    724  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    725  1.1.1.1.2.2  yamt     ucs4_t c, last;
    726  1.1.1.1.2.2  yamt     _ure_ccl_t *cclp;
    727  1.1.1.1.2.2  yamt     _ure_range_t range;
    728  1.1.1.1.2.2  yamt 
    729  1.1.1.1.2.2  yamt     sp = cp;
    730  1.1.1.1.2.2  yamt     ep = sp + limit;
    731  1.1.1.1.2.2  yamt 
    732  1.1.1.1.2.2  yamt     if (*sp == '^') {
    733  1.1.1.1.2.2  yamt       symp->type = _URE_NCCLASS;
    734  1.1.1.1.2.2  yamt       sp++;
    735  1.1.1.1.2.2  yamt     } else
    736  1.1.1.1.2.2  yamt       symp->type = _URE_CCLASS;
    737  1.1.1.1.2.2  yamt 
    738  1.1.1.1.2.2  yamt     for (last = 0, range_end = 0;
    739  1.1.1.1.2.2  yamt          b->error == _URE_OK && sp < ep && *sp != ']'; ) {
    740  1.1.1.1.2.2  yamt         c = *sp++;
    741  1.1.1.1.2.2  yamt         if (c == '\\') {
    742  1.1.1.1.2.2  yamt             if (sp == ep) {
    743  1.1.1.1.2.2  yamt                 /*
    744  1.1.1.1.2.2  yamt                  * The EOS was encountered when expecting the reverse solidus
    745  1.1.1.1.2.2  yamt                  * to be followed by the character it is escaping.  Set an
    746  1.1.1.1.2.2  yamt                  * error code and return the number of characters consumed up
    747  1.1.1.1.2.2  yamt                  * to this point.
    748  1.1.1.1.2.2  yamt                  */
    749  1.1.1.1.2.2  yamt                 b->error = _URE_UNEXPECTED_EOS;
    750  1.1.1.1.2.2  yamt                 return sp - cp;
    751  1.1.1.1.2.2  yamt             }
    752  1.1.1.1.2.2  yamt 
    753  1.1.1.1.2.2  yamt             c = *sp++;
    754  1.1.1.1.2.2  yamt             switch (c) {
    755  1.1.1.1.2.2  yamt               case 'a':
    756  1.1.1.1.2.2  yamt                 c = 0x07;
    757  1.1.1.1.2.2  yamt                 break;
    758  1.1.1.1.2.2  yamt               case 'b':
    759  1.1.1.1.2.2  yamt                 c = 0x08;
    760  1.1.1.1.2.2  yamt                 break;
    761  1.1.1.1.2.2  yamt               case 'f':
    762  1.1.1.1.2.2  yamt                 c = 0x0c;
    763  1.1.1.1.2.2  yamt                 break;
    764  1.1.1.1.2.2  yamt               case 'n':
    765  1.1.1.1.2.2  yamt                 c = 0x0a;
    766  1.1.1.1.2.2  yamt                 break;
    767  1.1.1.1.2.2  yamt               case 'r':
    768  1.1.1.1.2.2  yamt                 c = 0x0d;
    769  1.1.1.1.2.2  yamt                 break;
    770  1.1.1.1.2.2  yamt               case 't':
    771  1.1.1.1.2.2  yamt                 c = 0x09;
    772  1.1.1.1.2.2  yamt                 break;
    773  1.1.1.1.2.2  yamt               case 'v':
    774  1.1.1.1.2.2  yamt                 c = 0x0b;
    775  1.1.1.1.2.2  yamt                 break;
    776  1.1.1.1.2.2  yamt               case 'p':
    777  1.1.1.1.2.2  yamt               case 'P':
    778  1.1.1.1.2.2  yamt                 sp += _ure_prop_list(sp, ep - sp, &symp->props, b);
    779  1.1.1.1.2.2  yamt                 /*
    780  1.1.1.1.2.2  yamt                  * Invert the bit mask of the properties if this is a negated
    781  1.1.1.1.2.2  yamt                  * character class or if 'P' is used to specify a list of
    782  1.1.1.1.2.2  yamt                  * character properties that should *not* match in a
    783  1.1.1.1.2.2  yamt                  * character class.
    784  1.1.1.1.2.2  yamt                  */
    785  1.1.1.1.2.2  yamt                 if (c == 'P')
    786  1.1.1.1.2.2  yamt                   symp->props = ~symp->props;
    787  1.1.1.1.2.2  yamt                 continue;
    788  1.1.1.1.2.2  yamt                 break;
    789  1.1.1.1.2.2  yamt               case 'x':
    790  1.1.1.1.2.2  yamt               case 'X':
    791  1.1.1.1.2.2  yamt               case 'u':
    792  1.1.1.1.2.2  yamt               case 'U':
    793  1.1.1.1.2.2  yamt                 if (sp < ep &&
    794  1.1.1.1.2.2  yamt                     ((*sp >= '0' && *sp <= '9') ||
    795  1.1.1.1.2.2  yamt                      (*sp >= 'A' && *sp <= 'F') ||
    796  1.1.1.1.2.2  yamt                      (*sp >= 'a' && *sp <= 'f')))
    797  1.1.1.1.2.2  yamt                   sp += _ure_hex(sp, ep - sp, &c);
    798  1.1.1.1.2.2  yamt             }
    799  1.1.1.1.2.2  yamt         } else if (c == ':') {
    800  1.1.1.1.2.2  yamt             /*
    801  1.1.1.1.2.2  yamt              * Probe for a POSIX colon delimited character class.
    802  1.1.1.1.2.2  yamt              */
    803  1.1.1.1.2.2  yamt             sp--;
    804  1.1.1.1.2.2  yamt             if ((n = _ure_posix_ccl(sp, ep - sp, symp, b)) == 0)
    805  1.1.1.1.2.2  yamt               sp++;
    806  1.1.1.1.2.2  yamt             else {
    807  1.1.1.1.2.2  yamt                 sp += n;
    808  1.1.1.1.2.2  yamt                 continue;
    809  1.1.1.1.2.2  yamt             }
    810  1.1.1.1.2.2  yamt         }
    811  1.1.1.1.2.2  yamt 
    812  1.1.1.1.2.2  yamt         cclp = &symp->sym.ccl;
    813  1.1.1.1.2.2  yamt 
    814  1.1.1.1.2.2  yamt         /*
    815  1.1.1.1.2.2  yamt          * Check to see if the current character is a low surrogate that needs
    816  1.1.1.1.2.2  yamt          * to be combined with a preceding high surrogate.
    817  1.1.1.1.2.2  yamt          */
    818  1.1.1.1.2.2  yamt         if (last != 0) {
    819  1.1.1.1.2.2  yamt             if (c >= 0xdc00 && c <= 0xdfff)
    820  1.1.1.1.2.2  yamt               /*
    821  1.1.1.1.2.2  yamt                * Construct the UTF16 character code.
    822  1.1.1.1.2.2  yamt                */
    823  1.1.1.1.2.2  yamt               c = 0x10000 + (((last & 0x03ff) << 10) | (c & 0x03ff));
    824  1.1.1.1.2.2  yamt             else {
    825  1.1.1.1.2.2  yamt                 /*
    826  1.1.1.1.2.2  yamt                  * Add the isolated high surrogate to the range.
    827  1.1.1.1.2.2  yamt                  */
    828  1.1.1.1.2.2  yamt                 if (range_end == 1)
    829  1.1.1.1.2.2  yamt                   range.max_code = last & 0xffff;
    830  1.1.1.1.2.2  yamt                 else
    831  1.1.1.1.2.2  yamt                   range.min_code = range.max_code = last & 0xffff;
    832  1.1.1.1.2.2  yamt 
    833  1.1.1.1.2.2  yamt                 _ure_add_range(cclp, &range, b);
    834  1.1.1.1.2.2  yamt                 range_end = 0;
    835  1.1.1.1.2.2  yamt             }
    836  1.1.1.1.2.2  yamt         }
    837  1.1.1.1.2.2  yamt 
    838  1.1.1.1.2.2  yamt         /*
    839  1.1.1.1.2.2  yamt          * Clear the last character code.
    840  1.1.1.1.2.2  yamt          */
    841  1.1.1.1.2.2  yamt         last = 0;
    842  1.1.1.1.2.2  yamt 
    843  1.1.1.1.2.2  yamt         /*
    844  1.1.1.1.2.2  yamt          * This slightly awkward code handles the different cases needed to
    845  1.1.1.1.2.2  yamt          * construct a range.
    846  1.1.1.1.2.2  yamt          */
    847  1.1.1.1.2.2  yamt         if (c >= 0xd800 && c <= 0xdbff) {
    848  1.1.1.1.2.2  yamt             /*
    849  1.1.1.1.2.2  yamt              * If the high surrogate is followed by a range indicator, simply
    850  1.1.1.1.2.2  yamt              * add it as the range start.  Otherwise, save it in case the next
    851  1.1.1.1.2.2  yamt              * character is a low surrogate.
    852  1.1.1.1.2.2  yamt              */
    853  1.1.1.1.2.2  yamt             if (*sp == '-') {
    854  1.1.1.1.2.2  yamt                 sp++;
    855  1.1.1.1.2.2  yamt                 range.min_code = c;
    856  1.1.1.1.2.2  yamt                 range_end = 1;
    857  1.1.1.1.2.2  yamt             } else
    858  1.1.1.1.2.2  yamt               last = c;
    859  1.1.1.1.2.2  yamt         } else if (range_end == 1) {
    860  1.1.1.1.2.2  yamt             range.max_code = c;
    861  1.1.1.1.2.2  yamt             _ure_add_range(cclp, &range, b);
    862  1.1.1.1.2.2  yamt             range_end = 0;
    863  1.1.1.1.2.2  yamt         } else {
    864  1.1.1.1.2.2  yamt             range.min_code = range.max_code = c;
    865  1.1.1.1.2.2  yamt             if (*sp == '-') {
    866  1.1.1.1.2.2  yamt                 sp++;
    867  1.1.1.1.2.2  yamt                 range_end = 1;
    868  1.1.1.1.2.2  yamt             } else
    869  1.1.1.1.2.2  yamt               _ure_add_range(cclp, &range, b);
    870  1.1.1.1.2.2  yamt         }
    871  1.1.1.1.2.2  yamt     }
    872  1.1.1.1.2.2  yamt 
    873  1.1.1.1.2.2  yamt     if (sp < ep && *sp == ']')
    874  1.1.1.1.2.2  yamt       sp++;
    875  1.1.1.1.2.2  yamt     else
    876  1.1.1.1.2.2  yamt       /*
    877  1.1.1.1.2.2  yamt        * The parse was not terminated by the character class close symbol
    878  1.1.1.1.2.2  yamt        * (']'), so set an error code.
    879  1.1.1.1.2.2  yamt        */
    880  1.1.1.1.2.2  yamt       b->error = _URE_CCLASS_OPEN;
    881  1.1.1.1.2.2  yamt 
    882  1.1.1.1.2.2  yamt     return sp - cp;
    883  1.1.1.1.2.2  yamt }
    884  1.1.1.1.2.2  yamt 
    885  1.1.1.1.2.2  yamt /*
    886  1.1.1.1.2.2  yamt  * Probe for a low surrogate hex code.
    887  1.1.1.1.2.2  yamt  */
    888  1.1.1.1.2.2  yamt static unsigned long
    889  1.1.1.1.2.2  yamt _ure_probe_ls(ucs2_t *ls, unsigned long limit, ucs4_t *c)
    890  1.1.1.1.2.2  yamt {
    891  1.1.1.1.2.2  yamt     ucs4_t i, code;
    892  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    893  1.1.1.1.2.2  yamt 
    894  1.1.1.1.2.2  yamt     for (i = code = 0, sp = ls, ep = sp + limit; i < 4 && sp < ep; sp++) {
    895  1.1.1.1.2.2  yamt         if (*sp >= '0' && *sp <= '9')
    896  1.1.1.1.2.2  yamt           code = (code << 4) + (*sp - '0');
    897  1.1.1.1.2.2  yamt         else if (*sp >= 'A' && *sp <= 'F')
    898  1.1.1.1.2.2  yamt           code = (code << 4) + ((*sp - 'A') + 10);
    899  1.1.1.1.2.2  yamt         else if (*sp >= 'a' && *sp <= 'f')
    900  1.1.1.1.2.2  yamt           code = (code << 4) + ((*sp - 'a') + 10);
    901  1.1.1.1.2.2  yamt         else
    902  1.1.1.1.2.2  yamt           break;
    903  1.1.1.1.2.2  yamt     }
    904  1.1.1.1.2.2  yamt 
    905  1.1.1.1.2.2  yamt     *c = code;
    906  1.1.1.1.2.2  yamt     return (0xdc00 <= code && code <= 0xdfff) ? sp - ls : 0;
    907  1.1.1.1.2.2  yamt }
    908  1.1.1.1.2.2  yamt 
    909  1.1.1.1.2.2  yamt static unsigned long
    910  1.1.1.1.2.2  yamt _ure_compile_symbol(ucs2_t *sym, unsigned long limit, _ure_symtab_t *symp,
    911  1.1.1.1.2.2  yamt                     _ure_buffer_t *b)
    912  1.1.1.1.2.2  yamt {
    913  1.1.1.1.2.2  yamt     ucs4_t c;
    914  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep;
    915  1.1.1.1.2.2  yamt 
    916  1.1.1.1.2.2  yamt     sp = sym;
    917  1.1.1.1.2.2  yamt     ep = sym + limit;
    918  1.1.1.1.2.2  yamt 
    919  1.1.1.1.2.2  yamt     if ((c = *sp++) == '\\') {
    920  1.1.1.1.2.2  yamt 
    921  1.1.1.1.2.2  yamt         if (sp == ep) {
    922  1.1.1.1.2.2  yamt             /*
    923  1.1.1.1.2.2  yamt              * The EOS was encountered when expecting the reverse solidus to
    924  1.1.1.1.2.2  yamt              * be followed by the character it is escaping.  Set an error code
    925  1.1.1.1.2.2  yamt              * and return the number of characters consumed up to this point.
    926  1.1.1.1.2.2  yamt              */
    927  1.1.1.1.2.2  yamt             b->error = _URE_UNEXPECTED_EOS;
    928  1.1.1.1.2.2  yamt             return sp - sym;
    929  1.1.1.1.2.2  yamt         }
    930  1.1.1.1.2.2  yamt 
    931  1.1.1.1.2.2  yamt         c = *sp++;
    932  1.1.1.1.2.2  yamt         switch (c) {
    933  1.1.1.1.2.2  yamt           case 'p':
    934  1.1.1.1.2.2  yamt           case 'P':
    935  1.1.1.1.2.2  yamt             symp->type = (c == 'p') ? _URE_CCLASS : _URE_NCCLASS;
    936  1.1.1.1.2.2  yamt             sp += _ure_prop_list(sp, ep - sp, &symp->props, b);
    937  1.1.1.1.2.2  yamt             break;
    938  1.1.1.1.2.2  yamt           case 'a':
    939  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    940  1.1.1.1.2.2  yamt             symp->sym.chr = 0x07;
    941  1.1.1.1.2.2  yamt             break;
    942  1.1.1.1.2.2  yamt           case 'b':
    943  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    944  1.1.1.1.2.2  yamt             symp->sym.chr = 0x08;
    945  1.1.1.1.2.2  yamt             break;
    946  1.1.1.1.2.2  yamt           case 'f':
    947  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    948  1.1.1.1.2.2  yamt             symp->sym.chr = 0x0c;
    949  1.1.1.1.2.2  yamt             break;
    950  1.1.1.1.2.2  yamt           case 'n':
    951  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    952  1.1.1.1.2.2  yamt             symp->sym.chr = 0x0a;
    953  1.1.1.1.2.2  yamt             break;
    954  1.1.1.1.2.2  yamt           case 'r':
    955  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    956  1.1.1.1.2.2  yamt             symp->sym.chr = 0x0d;
    957  1.1.1.1.2.2  yamt             break;
    958  1.1.1.1.2.2  yamt           case 't':
    959  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    960  1.1.1.1.2.2  yamt             symp->sym.chr = 0x09;
    961  1.1.1.1.2.2  yamt             break;
    962  1.1.1.1.2.2  yamt           case 'v':
    963  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    964  1.1.1.1.2.2  yamt             symp->sym.chr = 0x0b;
    965  1.1.1.1.2.2  yamt             break;
    966  1.1.1.1.2.2  yamt           case 'x':
    967  1.1.1.1.2.2  yamt           case 'X':
    968  1.1.1.1.2.2  yamt           case 'u':
    969  1.1.1.1.2.2  yamt           case 'U':
    970  1.1.1.1.2.2  yamt             /*
    971  1.1.1.1.2.2  yamt              * Collect between 1 and 4 digits representing a UCS2 code.  Fall
    972  1.1.1.1.2.2  yamt              * through to the next case.
    973  1.1.1.1.2.2  yamt              */
    974  1.1.1.1.2.2  yamt             if (sp < ep &&
    975  1.1.1.1.2.2  yamt                 ((*sp >= '0' && *sp <= '9') ||
    976  1.1.1.1.2.2  yamt                  (*sp >= 'A' && *sp <= 'F') ||
    977  1.1.1.1.2.2  yamt                  (*sp >= 'a' && *sp <= 'f')))
    978  1.1.1.1.2.2  yamt               sp += _ure_hex(sp, ep - sp, &c);
    979  1.1.1.1.2.2  yamt             /* FALLTHROUGH */
    980  1.1.1.1.2.2  yamt           default:
    981  1.1.1.1.2.2  yamt             /*
    982  1.1.1.1.2.2  yamt              * Simply add an escaped character here.
    983  1.1.1.1.2.2  yamt              */
    984  1.1.1.1.2.2  yamt             symp->type = _URE_CHAR;
    985  1.1.1.1.2.2  yamt             symp->sym.chr = c;
    986  1.1.1.1.2.2  yamt         }
    987  1.1.1.1.2.2  yamt     } else if (c == '^' || c == '$')
    988  1.1.1.1.2.2  yamt       /*
    989  1.1.1.1.2.2  yamt        * Handle the BOL and EOL anchors.  This actually consists simply of
    990  1.1.1.1.2.2  yamt        * setting a flag that indicates that the user supplied anchor match
    991  1.1.1.1.2.2  yamt        * function should be called.  This needs to be done instead of simply
    992  1.1.1.1.2.2  yamt        * matching line/paragraph separators because beginning-of-text and
    993  1.1.1.1.2.2  yamt        * end-of-text tests are needed as well.
    994  1.1.1.1.2.2  yamt        */
    995  1.1.1.1.2.2  yamt       symp->type = (c == '^') ? _URE_BOL_ANCHOR : _URE_EOL_ANCHOR;
    996  1.1.1.1.2.2  yamt     else if (c == '[')
    997  1.1.1.1.2.2  yamt       /*
    998  1.1.1.1.2.2  yamt        * Construct a character class.
    999  1.1.1.1.2.2  yamt        */
   1000  1.1.1.1.2.2  yamt       sp += _ure_cclass(sp, ep - sp, symp, b);
   1001  1.1.1.1.2.2  yamt     else if (c == '.')
   1002  1.1.1.1.2.2  yamt       symp->type = _URE_ANY_CHAR;
   1003  1.1.1.1.2.2  yamt     else {
   1004  1.1.1.1.2.2  yamt         symp->type = _URE_CHAR;
   1005  1.1.1.1.2.2  yamt         symp->sym.chr = c;
   1006  1.1.1.1.2.2  yamt     }
   1007  1.1.1.1.2.2  yamt 
   1008  1.1.1.1.2.2  yamt     /*
   1009  1.1.1.1.2.2  yamt      * If the symbol type happens to be a character and is a high surrogate,
   1010  1.1.1.1.2.2  yamt      * then probe forward to see if it is followed by a low surrogate that
   1011  1.1.1.1.2.2  yamt      * needs to be added.
   1012  1.1.1.1.2.2  yamt      */
   1013  1.1.1.1.2.2  yamt     if (sp < ep && symp->type == _URE_CHAR &&
   1014  1.1.1.1.2.2  yamt         0xd800 <= symp->sym.chr && symp->sym.chr <= 0xdbff) {
   1015  1.1.1.1.2.2  yamt 
   1016  1.1.1.1.2.2  yamt         if (0xdc00 <= *sp && *sp <= 0xdfff) {
   1017  1.1.1.1.2.2  yamt             symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) |
   1018  1.1.1.1.2.2  yamt                                        (*sp & 0x03ff));
   1019  1.1.1.1.2.2  yamt             sp++;
   1020  1.1.1.1.2.2  yamt         } else if (*sp == '\\' && (*(sp + 1) == 'x' || *(sp + 1) == 'X' ||
   1021  1.1.1.1.2.2  yamt                                  *(sp + 1) == 'u' || *(sp + 1) == 'U')) {
   1022  1.1.1.1.2.2  yamt             sp += _ure_probe_ls(sp + 2, ep - (sp + 2), &c);
   1023  1.1.1.1.2.2  yamt             if (0xdc00 <= c && c <= 0xdfff) {
   1024  1.1.1.1.2.2  yamt                 /*
   1025  1.1.1.1.2.2  yamt                  * Take into account the \[xu] in front of the hex code.
   1026  1.1.1.1.2.2  yamt                  */
   1027  1.1.1.1.2.2  yamt                 sp += 2;
   1028  1.1.1.1.2.2  yamt                 symp->sym.chr = 0x10000 + (((symp->sym.chr & 0x03ff) << 10) |
   1029  1.1.1.1.2.2  yamt                                            (c & 0x03ff));
   1030  1.1.1.1.2.2  yamt             }
   1031  1.1.1.1.2.2  yamt         }
   1032  1.1.1.1.2.2  yamt     }
   1033  1.1.1.1.2.2  yamt 
   1034  1.1.1.1.2.2  yamt     /*
   1035  1.1.1.1.2.2  yamt      * Last, make sure any _URE_CHAR type symbols are changed to lower case if
   1036  1.1.1.1.2.2  yamt      * the `casefold' flag is set.
   1037  1.1.1.1.2.2  yamt      */
   1038  1.1.1.1.2.2  yamt     if ((b->flags & _URE_DFA_CASEFOLD) && symp->type == _URE_CHAR)
   1039  1.1.1.1.2.2  yamt       symp->sym.chr = _ure_tolower(symp->sym.chr);
   1040  1.1.1.1.2.2  yamt 
   1041  1.1.1.1.2.2  yamt     /*
   1042  1.1.1.1.2.2  yamt      * If the symbol constructed is anything other than one of the anchors,
   1043  1.1.1.1.2.2  yamt      * make sure the _URE_DFA_BLANKLINE flag is removed.
   1044  1.1.1.1.2.2  yamt      */
   1045  1.1.1.1.2.2  yamt     if (symp->type != _URE_BOL_ANCHOR && symp->type != _URE_EOL_ANCHOR)
   1046  1.1.1.1.2.2  yamt       b->flags &= ~_URE_DFA_BLANKLINE;
   1047  1.1.1.1.2.2  yamt 
   1048  1.1.1.1.2.2  yamt     /*
   1049  1.1.1.1.2.2  yamt      * Return the number of characters consumed.
   1050  1.1.1.1.2.2  yamt      */
   1051  1.1.1.1.2.2  yamt     return sp - sym;
   1052  1.1.1.1.2.2  yamt }
   1053  1.1.1.1.2.2  yamt 
   1054  1.1.1.1.2.2  yamt static int
   1055  1.1.1.1.2.2  yamt _ure_sym_neq(_ure_symtab_t *a, _ure_symtab_t *b)
   1056  1.1.1.1.2.2  yamt {
   1057  1.1.1.1.2.2  yamt     if (a->type != b->type || a->mods != b->mods || a->props != b->props)
   1058  1.1.1.1.2.2  yamt       return 1;
   1059  1.1.1.1.2.2  yamt 
   1060  1.1.1.1.2.2  yamt     if (a->type == _URE_CCLASS || a->type == _URE_NCCLASS) {
   1061  1.1.1.1.2.2  yamt         if (a->sym.ccl.ranges_used != b->sym.ccl.ranges_used)
   1062  1.1.1.1.2.2  yamt           return 1;
   1063  1.1.1.1.2.2  yamt         if (a->sym.ccl.ranges_used > 0 &&
   1064  1.1.1.1.2.2  yamt             memcmp((char *) a->sym.ccl.ranges, (char *) b->sym.ccl.ranges,
   1065  1.1.1.1.2.2  yamt                    sizeof(_ure_range_t) * a->sym.ccl.ranges_used) != 0)
   1066  1.1.1.1.2.2  yamt           return 1;
   1067  1.1.1.1.2.2  yamt     } else if (a->type == _URE_CHAR && a->sym.chr != b->sym.chr)
   1068  1.1.1.1.2.2  yamt       return 1;
   1069  1.1.1.1.2.2  yamt     return 0;
   1070  1.1.1.1.2.2  yamt }
   1071  1.1.1.1.2.2  yamt 
   1072  1.1.1.1.2.2  yamt /*
   1073  1.1.1.1.2.2  yamt  * Construct a symbol, but only keep unique symbols.
   1074  1.1.1.1.2.2  yamt  */
   1075  1.1.1.1.2.2  yamt static ucs2_t
   1076  1.1.1.1.2.2  yamt _ure_make_symbol(ucs2_t *sym, unsigned long limit, unsigned long *consumed,
   1077  1.1.1.1.2.2  yamt                  _ure_buffer_t *b)
   1078  1.1.1.1.2.2  yamt {
   1079  1.1.1.1.2.2  yamt     ucs2_t i;
   1080  1.1.1.1.2.2  yamt     _ure_symtab_t *sp, symbol;
   1081  1.1.1.1.2.2  yamt 
   1082  1.1.1.1.2.2  yamt     /*
   1083  1.1.1.1.2.2  yamt      * Build the next symbol so we can test to see if it is already in the
   1084  1.1.1.1.2.2  yamt      * symbol table.
   1085  1.1.1.1.2.2  yamt      */
   1086  1.1.1.1.2.2  yamt     (void) memset((char *) &symbol, '\0', sizeof(_ure_symtab_t));
   1087  1.1.1.1.2.2  yamt     *consumed = _ure_compile_symbol(sym, limit, &symbol, b);
   1088  1.1.1.1.2.2  yamt 
   1089  1.1.1.1.2.2  yamt     /*
   1090  1.1.1.1.2.2  yamt      * Check to see if the symbol exists.
   1091  1.1.1.1.2.2  yamt      */
   1092  1.1.1.1.2.2  yamt     for (i = 0, sp = b->symtab;
   1093  1.1.1.1.2.2  yamt          i < b->symtab_used && _ure_sym_neq(&symbol, sp); i++, sp++) ;
   1094  1.1.1.1.2.2  yamt 
   1095  1.1.1.1.2.2  yamt     if (i < b->symtab_used) {
   1096  1.1.1.1.2.2  yamt         /*
   1097  1.1.1.1.2.2  yamt          * Free up any ranges used for the symbol.
   1098  1.1.1.1.2.2  yamt          */
   1099  1.1.1.1.2.2  yamt         if ((symbol.type == _URE_CCLASS || symbol.type == _URE_NCCLASS) &&
   1100  1.1.1.1.2.2  yamt             symbol.sym.ccl.ranges_size > 0)
   1101  1.1.1.1.2.2  yamt           free((char *) symbol.sym.ccl.ranges);
   1102  1.1.1.1.2.2  yamt 
   1103  1.1.1.1.2.2  yamt         return b->symtab[i].id;
   1104  1.1.1.1.2.2  yamt     }
   1105  1.1.1.1.2.2  yamt 
   1106  1.1.1.1.2.2  yamt     /*
   1107  1.1.1.1.2.2  yamt      * Need to add the new symbol.
   1108  1.1.1.1.2.2  yamt      */
   1109  1.1.1.1.2.2  yamt     if (b->symtab_used == b->symtab_size) {
   1110  1.1.1.1.2.2  yamt         if (b->symtab_size == 0)
   1111  1.1.1.1.2.2  yamt           b->symtab = (_ure_symtab_t *) malloc(sizeof(_ure_symtab_t) << 3);
   1112  1.1.1.1.2.2  yamt         else
   1113  1.1.1.1.2.2  yamt           b->symtab = (_ure_symtab_t *)
   1114  1.1.1.1.2.2  yamt               realloc((char *) b->symtab,
   1115  1.1.1.1.2.2  yamt                       sizeof(_ure_symtab_t) * (b->symtab_size + 8));
   1116  1.1.1.1.2.2  yamt         sp = b->symtab + b->symtab_size;
   1117  1.1.1.1.2.2  yamt         (void) memset((char *) sp, '\0', sizeof(_ure_symtab_t) << 3);
   1118  1.1.1.1.2.2  yamt         b->symtab_size += 8;
   1119  1.1.1.1.2.2  yamt     }
   1120  1.1.1.1.2.2  yamt 
   1121  1.1.1.1.2.2  yamt     symbol.id = b->symtab_used++;
   1122  1.1.1.1.2.2  yamt     (void) AC_MEMCPY((char *) &b->symtab[symbol.id], (char *) &symbol,
   1123  1.1.1.1.2.2  yamt                   sizeof(_ure_symtab_t));
   1124  1.1.1.1.2.2  yamt 
   1125  1.1.1.1.2.2  yamt     return symbol.id;
   1126  1.1.1.1.2.2  yamt }
   1127  1.1.1.1.2.2  yamt 
   1128  1.1.1.1.2.2  yamt /*************************************************************************
   1129  1.1.1.1.2.2  yamt  *
   1130  1.1.1.1.2.2  yamt  * End symbol parse functions.
   1131  1.1.1.1.2.2  yamt  *
   1132  1.1.1.1.2.2  yamt  *************************************************************************/
   1133  1.1.1.1.2.2  yamt 
   1134  1.1.1.1.2.2  yamt static ucs2_t
   1135  1.1.1.1.2.2  yamt _ure_make_expr(ucs2_t type, ucs2_t lhs, ucs2_t rhs, _ure_buffer_t *b)
   1136  1.1.1.1.2.2  yamt {
   1137  1.1.1.1.2.2  yamt     ucs2_t i;
   1138  1.1.1.1.2.2  yamt 
   1139  1.1.1.1.2.2  yamt     if (b == 0)
   1140  1.1.1.1.2.2  yamt       return _URE_NOOP;
   1141  1.1.1.1.2.2  yamt 
   1142  1.1.1.1.2.2  yamt     /*
   1143  1.1.1.1.2.2  yamt      * Determine if the expression already exists or not.
   1144  1.1.1.1.2.2  yamt      */
   1145  1.1.1.1.2.2  yamt     for (i = 0; i < b->expr_used; i++) {
   1146  1.1.1.1.2.2  yamt         if (b->expr[i].type == type && b->expr[i].lhs == lhs &&
   1147  1.1.1.1.2.2  yamt             b->expr[i].rhs == rhs)
   1148  1.1.1.1.2.2  yamt           break;
   1149  1.1.1.1.2.2  yamt     }
   1150  1.1.1.1.2.2  yamt     if (i < b->expr_used)
   1151  1.1.1.1.2.2  yamt       return i;
   1152  1.1.1.1.2.2  yamt 
   1153  1.1.1.1.2.2  yamt     /*
   1154  1.1.1.1.2.2  yamt      * Need to add a new expression.
   1155  1.1.1.1.2.2  yamt      */
   1156  1.1.1.1.2.2  yamt     if (b->expr_used == b->expr_size) {
   1157  1.1.1.1.2.2  yamt         if (b->expr_size == 0)
   1158  1.1.1.1.2.2  yamt           b->expr = (_ure_elt_t *) malloc(sizeof(_ure_elt_t) << 3);
   1159  1.1.1.1.2.2  yamt         else
   1160  1.1.1.1.2.2  yamt           b->expr = (_ure_elt_t *)
   1161  1.1.1.1.2.2  yamt               realloc((char *) b->expr,
   1162  1.1.1.1.2.2  yamt                       sizeof(_ure_elt_t) * (b->expr_size + 8));
   1163  1.1.1.1.2.2  yamt         b->expr_size += 8;
   1164  1.1.1.1.2.2  yamt     }
   1165  1.1.1.1.2.2  yamt 
   1166  1.1.1.1.2.2  yamt     b->expr[b->expr_used].onstack = 0;
   1167  1.1.1.1.2.2  yamt     b->expr[b->expr_used].type = type;
   1168  1.1.1.1.2.2  yamt     b->expr[b->expr_used].lhs = lhs;
   1169  1.1.1.1.2.2  yamt     b->expr[b->expr_used].rhs = rhs;
   1170  1.1.1.1.2.2  yamt 
   1171  1.1.1.1.2.2  yamt     return b->expr_used++;
   1172  1.1.1.1.2.2  yamt }
   1173  1.1.1.1.2.2  yamt 
   1174  1.1.1.1.2.2  yamt static unsigned char spmap[] = {
   1175  1.1.1.1.2.2  yamt     0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00,
   1176  1.1.1.1.2.2  yamt     0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   1177  1.1.1.1.2.2  yamt     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   1178  1.1.1.1.2.2  yamt };
   1179  1.1.1.1.2.2  yamt 
   1180  1.1.1.1.2.2  yamt #define _ure_isspecial(cc) ((cc) > 0x20 && (cc) < 0x7f && \
   1181  1.1.1.1.2.2  yamt                             (spmap[(cc) >> 3] & (1 << ((cc) & 7))))
   1182  1.1.1.1.2.2  yamt 
   1183  1.1.1.1.2.2  yamt /*
   1184  1.1.1.1.2.2  yamt  * Convert the regular expression into an NFA in a form that will be easy to
   1185  1.1.1.1.2.2  yamt  * reduce to a DFA.  The starting state for the reduction will be returned.
   1186  1.1.1.1.2.2  yamt  */
   1187  1.1.1.1.2.2  yamt static ucs2_t
   1188  1.1.1.1.2.2  yamt _ure_re2nfa(ucs2_t *re, unsigned long relen, _ure_buffer_t *b)
   1189  1.1.1.1.2.2  yamt {
   1190  1.1.1.1.2.2  yamt     ucs2_t c, state, top, sym, *sp, *ep;
   1191  1.1.1.1.2.2  yamt     unsigned long used;
   1192  1.1.1.1.2.2  yamt 
   1193  1.1.1.1.2.2  yamt     state = _URE_NOOP;
   1194  1.1.1.1.2.2  yamt 
   1195  1.1.1.1.2.2  yamt     sp = re;
   1196  1.1.1.1.2.2  yamt     ep = sp + relen;
   1197  1.1.1.1.2.2  yamt     while (b->error == _URE_OK && sp < ep) {
   1198  1.1.1.1.2.2  yamt         c = *sp++;
   1199  1.1.1.1.2.2  yamt         switch (c) {
   1200  1.1.1.1.2.2  yamt           case '(':
   1201  1.1.1.1.2.2  yamt             _ure_push(_URE_PAREN, b);
   1202  1.1.1.1.2.2  yamt             break;
   1203  1.1.1.1.2.2  yamt           case ')':
   1204  1.1.1.1.2.2  yamt             /*
   1205  1.1.1.1.2.2  yamt              * Check for the case of too many close parentheses.
   1206  1.1.1.1.2.2  yamt              */
   1207  1.1.1.1.2.2  yamt             if (_ure_peek(b) == _URE_NOOP) {
   1208  1.1.1.1.2.2  yamt                 b->error = _URE_UNBALANCED_GROUP;
   1209  1.1.1.1.2.2  yamt                 break;
   1210  1.1.1.1.2.2  yamt             }
   1211  1.1.1.1.2.2  yamt 
   1212  1.1.1.1.2.2  yamt             while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
   1213  1.1.1.1.2.2  yamt               /*
   1214  1.1.1.1.2.2  yamt                * Make an expression with the AND or OR operator and its right
   1215  1.1.1.1.2.2  yamt                * hand side.
   1216  1.1.1.1.2.2  yamt                */
   1217  1.1.1.1.2.2  yamt               state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
   1218  1.1.1.1.2.2  yamt 
   1219  1.1.1.1.2.2  yamt             /*
   1220  1.1.1.1.2.2  yamt              * Remove the _URE_PAREN off the stack.
   1221  1.1.1.1.2.2  yamt              */
   1222  1.1.1.1.2.2  yamt             (void) _ure_pop(b);
   1223  1.1.1.1.2.2  yamt             break;
   1224  1.1.1.1.2.2  yamt           case '*':
   1225  1.1.1.1.2.2  yamt             state = _ure_make_expr(_URE_STAR, state, _URE_NOOP, b);
   1226  1.1.1.1.2.2  yamt             break;
   1227  1.1.1.1.2.2  yamt           case '+':
   1228  1.1.1.1.2.2  yamt             state = _ure_make_expr(_URE_PLUS, state, _URE_NOOP, b);
   1229  1.1.1.1.2.2  yamt             break;
   1230  1.1.1.1.2.2  yamt           case '?':
   1231  1.1.1.1.2.2  yamt             state = _ure_make_expr(_URE_QUEST, state, _URE_NOOP, b);
   1232  1.1.1.1.2.2  yamt             break;
   1233  1.1.1.1.2.2  yamt           case '|':
   1234  1.1.1.1.2.2  yamt             while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
   1235  1.1.1.1.2.2  yamt               /*
   1236  1.1.1.1.2.2  yamt                * Make an expression with the AND or OR operator and its right
   1237  1.1.1.1.2.2  yamt                * hand side.
   1238  1.1.1.1.2.2  yamt                */
   1239  1.1.1.1.2.2  yamt               state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
   1240  1.1.1.1.2.2  yamt 
   1241  1.1.1.1.2.2  yamt             _ure_push(state, b);
   1242  1.1.1.1.2.2  yamt             _ure_push(_URE_OR, b);
   1243  1.1.1.1.2.2  yamt             break;
   1244  1.1.1.1.2.2  yamt           default:
   1245  1.1.1.1.2.2  yamt             sp--;
   1246  1.1.1.1.2.2  yamt             sym = _ure_make_symbol(sp, ep - sp, &used, b);
   1247  1.1.1.1.2.2  yamt             sp += used;
   1248  1.1.1.1.2.2  yamt             state = _ure_make_expr(_URE_SYMBOL, sym, _URE_NOOP, b);
   1249  1.1.1.1.2.2  yamt             break;
   1250  1.1.1.1.2.2  yamt         }
   1251  1.1.1.1.2.2  yamt 
   1252  1.1.1.1.2.2  yamt         if (c != '(' && c != '|' && sp < ep &&
   1253  1.1.1.1.2.2  yamt             (!_ure_isspecial(*sp) || *sp == '(')) {
   1254  1.1.1.1.2.2  yamt             _ure_push(state, b);
   1255  1.1.1.1.2.2  yamt             _ure_push(_URE_AND, b);
   1256  1.1.1.1.2.2  yamt         }
   1257  1.1.1.1.2.2  yamt     }
   1258  1.1.1.1.2.2  yamt     while ((top = _ure_peek(b)) == _URE_AND || top == _URE_OR)
   1259  1.1.1.1.2.2  yamt       /*
   1260  1.1.1.1.2.2  yamt        * Make an expression with the AND or OR operator and its right
   1261  1.1.1.1.2.2  yamt        * hand side.
   1262  1.1.1.1.2.2  yamt        */
   1263  1.1.1.1.2.2  yamt       state = _ure_make_expr(_ure_pop(b), _ure_pop(b), state, b);
   1264  1.1.1.1.2.2  yamt 
   1265  1.1.1.1.2.2  yamt     if (b->stack.slist_used > 0)
   1266  1.1.1.1.2.2  yamt       b->error = _URE_UNBALANCED_GROUP;
   1267  1.1.1.1.2.2  yamt 
   1268  1.1.1.1.2.2  yamt     return (b->error == _URE_OK) ? state : _URE_NOOP;
   1269  1.1.1.1.2.2  yamt }
   1270  1.1.1.1.2.2  yamt 
   1271  1.1.1.1.2.2  yamt static void
   1272  1.1.1.1.2.2  yamt _ure_add_symstate(ucs2_t sym, ucs2_t state, _ure_buffer_t *b)
   1273  1.1.1.1.2.2  yamt {
   1274  1.1.1.1.2.2  yamt     ucs2_t i, *stp;
   1275  1.1.1.1.2.2  yamt     _ure_symtab_t *sp;
   1276  1.1.1.1.2.2  yamt 
   1277  1.1.1.1.2.2  yamt     /*
   1278  1.1.1.1.2.2  yamt      * Locate the symbol in the symbol table so the state can be added.
   1279  1.1.1.1.2.2  yamt      * If the symbol doesn't exist, then a real problem exists.
   1280  1.1.1.1.2.2  yamt      */
   1281  1.1.1.1.2.2  yamt     for (i = 0, sp = b->symtab; i < b->symtab_used && sym != sp->id;
   1282  1.1.1.1.2.2  yamt          i++, sp++) ;
   1283  1.1.1.1.2.2  yamt 
   1284  1.1.1.1.2.2  yamt     /*
   1285  1.1.1.1.2.2  yamt      * Now find out if the state exists in the symbol's state list.
   1286  1.1.1.1.2.2  yamt      */
   1287  1.1.1.1.2.2  yamt     for (i = 0, stp = sp->states.slist;
   1288  1.1.1.1.2.2  yamt          i < sp->states.slist_used && state > *stp; i++, stp++) ;
   1289  1.1.1.1.2.2  yamt 
   1290  1.1.1.1.2.2  yamt     if (i == sp->states.slist_used || state < *stp) {
   1291  1.1.1.1.2.2  yamt         /*
   1292  1.1.1.1.2.2  yamt          * Need to add the state in order.
   1293  1.1.1.1.2.2  yamt          */
   1294  1.1.1.1.2.2  yamt         if (sp->states.slist_used == sp->states.slist_size) {
   1295  1.1.1.1.2.2  yamt             if (sp->states.slist_size == 0)
   1296  1.1.1.1.2.2  yamt               sp->states.slist = (ucs2_t *) malloc(sizeof(ucs2_t) << 3);
   1297  1.1.1.1.2.2  yamt             else
   1298  1.1.1.1.2.2  yamt               sp->states.slist = (ucs2_t *)
   1299  1.1.1.1.2.2  yamt                   realloc((char *) sp->states.slist,
   1300  1.1.1.1.2.2  yamt                           sizeof(ucs2_t) * (sp->states.slist_size + 8));
   1301  1.1.1.1.2.2  yamt             sp->states.slist_size += 8;
   1302  1.1.1.1.2.2  yamt         }
   1303  1.1.1.1.2.2  yamt         if (i < sp->states.slist_used)
   1304  1.1.1.1.2.2  yamt           (void) _ure_memmove((char *) (sp->states.slist + i + 1),
   1305  1.1.1.1.2.2  yamt                               (char *) (sp->states.slist + i),
   1306  1.1.1.1.2.2  yamt                               sizeof(ucs2_t) * (sp->states.slist_used - i));
   1307  1.1.1.1.2.2  yamt         sp->states.slist[i] = state;
   1308  1.1.1.1.2.2  yamt         sp->states.slist_used++;
   1309  1.1.1.1.2.2  yamt     }
   1310  1.1.1.1.2.2  yamt }
   1311  1.1.1.1.2.2  yamt 
   1312  1.1.1.1.2.2  yamt static ucs2_t
   1313  1.1.1.1.2.2  yamt _ure_add_state(ucs2_t nstates, ucs2_t *states, _ure_buffer_t *b)
   1314  1.1.1.1.2.2  yamt {
   1315  1.1.1.1.2.2  yamt     ucs2_t i;
   1316  1.1.1.1.2.2  yamt     _ure_state_t *sp;
   1317  1.1.1.1.2.2  yamt 
   1318  1.1.1.1.2.2  yamt     for (i = 0, sp = b->states.states; i < b->states.states_used; i++, sp++) {
   1319  1.1.1.1.2.2  yamt         if (sp->st.slist_used == nstates &&
   1320  1.1.1.1.2.2  yamt             memcmp((char *) states, (char *) sp->st.slist,
   1321  1.1.1.1.2.2  yamt                    sizeof(ucs2_t) * nstates) == 0)
   1322  1.1.1.1.2.2  yamt           break;
   1323  1.1.1.1.2.2  yamt     }
   1324  1.1.1.1.2.2  yamt 
   1325  1.1.1.1.2.2  yamt     if (i == b->states.states_used) {
   1326  1.1.1.1.2.2  yamt         /*
   1327  1.1.1.1.2.2  yamt          * Need to add a new DFA state (set of NFA states).
   1328  1.1.1.1.2.2  yamt          */
   1329  1.1.1.1.2.2  yamt         if (b->states.states_used == b->states.states_size) {
   1330  1.1.1.1.2.2  yamt             if (b->states.states_size == 0)
   1331  1.1.1.1.2.2  yamt               b->states.states = (_ure_state_t *)
   1332  1.1.1.1.2.2  yamt                   malloc(sizeof(_ure_state_t) << 3);
   1333  1.1.1.1.2.2  yamt             else
   1334  1.1.1.1.2.2  yamt               b->states.states = (_ure_state_t *)
   1335  1.1.1.1.2.2  yamt                   realloc((char *) b->states.states,
   1336  1.1.1.1.2.2  yamt                           sizeof(_ure_state_t) * (b->states.states_size + 8));
   1337  1.1.1.1.2.2  yamt             sp = b->states.states + b->states.states_size;
   1338  1.1.1.1.2.2  yamt             (void) memset((char *) sp, '\0', sizeof(_ure_state_t) << 3);
   1339  1.1.1.1.2.2  yamt             b->states.states_size += 8;
   1340  1.1.1.1.2.2  yamt         }
   1341  1.1.1.1.2.2  yamt 
   1342  1.1.1.1.2.2  yamt         sp = b->states.states + b->states.states_used++;
   1343  1.1.1.1.2.2  yamt         sp->id = i;
   1344  1.1.1.1.2.2  yamt 
   1345  1.1.1.1.2.2  yamt         if (sp->st.slist_used + nstates > sp->st.slist_size) {
   1346  1.1.1.1.2.2  yamt             if (sp->st.slist_size == 0)
   1347  1.1.1.1.2.2  yamt               sp->st.slist = (ucs2_t *)
   1348  1.1.1.1.2.2  yamt                   malloc(sizeof(ucs2_t) * (sp->st.slist_used + nstates));
   1349  1.1.1.1.2.2  yamt             else
   1350  1.1.1.1.2.2  yamt               sp->st.slist = (ucs2_t *)
   1351  1.1.1.1.2.2  yamt                   realloc((char *) sp->st.slist,
   1352  1.1.1.1.2.2  yamt                           sizeof(ucs2_t) * (sp->st.slist_used + nstates));
   1353  1.1.1.1.2.2  yamt             sp->st.slist_size = sp->st.slist_used + nstates;
   1354  1.1.1.1.2.2  yamt         }
   1355  1.1.1.1.2.2  yamt         sp->st.slist_used = nstates;
   1356  1.1.1.1.2.2  yamt         (void) AC_MEMCPY((char *) sp->st.slist, (char *) states,
   1357  1.1.1.1.2.2  yamt                       sizeof(ucs2_t) * nstates);
   1358  1.1.1.1.2.2  yamt     }
   1359  1.1.1.1.2.2  yamt 
   1360  1.1.1.1.2.2  yamt     /*
   1361  1.1.1.1.2.2  yamt      * Return the ID of the DFA state representing a group of NFA states.
   1362  1.1.1.1.2.2  yamt      */
   1363  1.1.1.1.2.2  yamt     return i;
   1364  1.1.1.1.2.2  yamt }
   1365  1.1.1.1.2.2  yamt 
   1366  1.1.1.1.2.2  yamt static void
   1367  1.1.1.1.2.2  yamt _ure_reduce(ucs2_t start, _ure_buffer_t *b)
   1368  1.1.1.1.2.2  yamt {
   1369  1.1.1.1.2.2  yamt     ucs2_t i, j, state, eval, syms, rhs;
   1370  1.1.1.1.2.2  yamt     ucs2_t s1, s2, ns1, ns2;
   1371  1.1.1.1.2.2  yamt     _ure_state_t *sp;
   1372  1.1.1.1.2.2  yamt     _ure_symtab_t *smp;
   1373  1.1.1.1.2.2  yamt 
   1374  1.1.1.1.2.2  yamt     b->reducing = 1;
   1375  1.1.1.1.2.2  yamt 
   1376  1.1.1.1.2.2  yamt     /*
   1377  1.1.1.1.2.2  yamt      * Add the starting state for the reduction.
   1378  1.1.1.1.2.2  yamt      */
   1379  1.1.1.1.2.2  yamt     _ure_add_state(1, &start, b);
   1380  1.1.1.1.2.2  yamt 
   1381  1.1.1.1.2.2  yamt     /*
   1382  1.1.1.1.2.2  yamt      * Process each set of NFA states that get created.
   1383  1.1.1.1.2.2  yamt      */
   1384  1.1.1.1.2.2  yamt     for (i = 0; i < b->states.states_used; i++) {
   1385  1.1.1.1.2.2  yamt         sp = b->states.states + i;
   1386  1.1.1.1.2.2  yamt 
   1387  1.1.1.1.2.2  yamt         /*
   1388  1.1.1.1.2.2  yamt          * Push the current states on the stack.
   1389  1.1.1.1.2.2  yamt          */
   1390  1.1.1.1.2.2  yamt         for (j = 0; j < sp->st.slist_used; j++)
   1391  1.1.1.1.2.2  yamt           _ure_push(sp->st.slist[j], b);
   1392  1.1.1.1.2.2  yamt 
   1393  1.1.1.1.2.2  yamt         /*
   1394  1.1.1.1.2.2  yamt          * Reduce the NFA states.
   1395  1.1.1.1.2.2  yamt          */
   1396  1.1.1.1.2.2  yamt         for (j = sp->accepting = syms = 0; j < b->stack.slist_used; j++) {
   1397  1.1.1.1.2.2  yamt             state = b->stack.slist[j];
   1398  1.1.1.1.2.2  yamt             eval = 1;
   1399  1.1.1.1.2.2  yamt 
   1400  1.1.1.1.2.2  yamt             /*
   1401  1.1.1.1.2.2  yamt              * This inner loop is the iterative equivalent of recursively
   1402  1.1.1.1.2.2  yamt              * reducing subexpressions generated as a result of a reduction.
   1403  1.1.1.1.2.2  yamt              */
   1404  1.1.1.1.2.2  yamt             while (eval) {
   1405  1.1.1.1.2.2  yamt                 switch (b->expr[state].type) {
   1406  1.1.1.1.2.2  yamt                   case _URE_SYMBOL:
   1407  1.1.1.1.2.2  yamt                     ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
   1408  1.1.1.1.2.2  yamt                     _ure_add_symstate(b->expr[state].lhs, ns1, b);
   1409  1.1.1.1.2.2  yamt                     syms++;
   1410  1.1.1.1.2.2  yamt                     eval = 0;
   1411  1.1.1.1.2.2  yamt                     break;
   1412  1.1.1.1.2.2  yamt                   case _URE_ONE:
   1413  1.1.1.1.2.2  yamt                     sp->accepting = 1;
   1414  1.1.1.1.2.2  yamt                     eval = 0;
   1415  1.1.1.1.2.2  yamt                     break;
   1416  1.1.1.1.2.2  yamt                   case _URE_QUEST:
   1417  1.1.1.1.2.2  yamt                     s1 = b->expr[state].lhs;
   1418  1.1.1.1.2.2  yamt                     ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
   1419  1.1.1.1.2.2  yamt                     state = _ure_make_expr(_URE_OR, ns1, s1, b);
   1420  1.1.1.1.2.2  yamt                     break;
   1421  1.1.1.1.2.2  yamt                   case _URE_PLUS:
   1422  1.1.1.1.2.2  yamt                     s1 = b->expr[state].lhs;
   1423  1.1.1.1.2.2  yamt                     ns1 = _ure_make_expr(_URE_STAR, s1, _URE_NOOP, b);
   1424  1.1.1.1.2.2  yamt                     state = _ure_make_expr(_URE_AND, s1, ns1, b);
   1425  1.1.1.1.2.2  yamt                     break;
   1426  1.1.1.1.2.2  yamt                   case _URE_STAR:
   1427  1.1.1.1.2.2  yamt                     s1 = b->expr[state].lhs;
   1428  1.1.1.1.2.2  yamt                     ns1 = _ure_make_expr(_URE_ONE, _URE_NOOP, _URE_NOOP, b);
   1429  1.1.1.1.2.2  yamt                     ns2 = _ure_make_expr(_URE_PLUS, s1, _URE_NOOP, b);
   1430  1.1.1.1.2.2  yamt                     state = _ure_make_expr(_URE_OR, ns1, ns2, b);
   1431  1.1.1.1.2.2  yamt                     break;
   1432  1.1.1.1.2.2  yamt                   case _URE_OR:
   1433  1.1.1.1.2.2  yamt                     s1 = b->expr[state].lhs;
   1434  1.1.1.1.2.2  yamt                     s2 = b->expr[state].rhs;
   1435  1.1.1.1.2.2  yamt                     _ure_push(s1, b);
   1436  1.1.1.1.2.2  yamt                     _ure_push(s2, b);
   1437  1.1.1.1.2.2  yamt                     eval = 0;
   1438  1.1.1.1.2.2  yamt                     break;
   1439  1.1.1.1.2.2  yamt                   case _URE_AND:
   1440  1.1.1.1.2.2  yamt                     s1 = b->expr[state].lhs;
   1441  1.1.1.1.2.2  yamt                     s2 = b->expr[state].rhs;
   1442  1.1.1.1.2.2  yamt                     switch (b->expr[s1].type) {
   1443  1.1.1.1.2.2  yamt                       case _URE_SYMBOL:
   1444  1.1.1.1.2.2  yamt                         _ure_add_symstate(b->expr[s1].lhs, s2, b);
   1445  1.1.1.1.2.2  yamt                         syms++;
   1446  1.1.1.1.2.2  yamt                         eval = 0;
   1447  1.1.1.1.2.2  yamt                         break;
   1448  1.1.1.1.2.2  yamt                       case _URE_ONE:
   1449  1.1.1.1.2.2  yamt                         state = s2;
   1450  1.1.1.1.2.2  yamt                         break;
   1451  1.1.1.1.2.2  yamt                       case _URE_QUEST:
   1452  1.1.1.1.2.2  yamt                         ns1 = b->expr[s1].lhs;
   1453  1.1.1.1.2.2  yamt                         ns2 = _ure_make_expr(_URE_AND, ns1, s2, b);
   1454  1.1.1.1.2.2  yamt                         state = _ure_make_expr(_URE_OR, s2, ns2, b);
   1455  1.1.1.1.2.2  yamt                         break;
   1456  1.1.1.1.2.2  yamt                       case _URE_PLUS:
   1457  1.1.1.1.2.2  yamt                         ns1 = b->expr[s1].lhs;
   1458  1.1.1.1.2.2  yamt                         ns2 = _ure_make_expr(_URE_OR, s2, state, b);
   1459  1.1.1.1.2.2  yamt                         state = _ure_make_expr(_URE_AND, ns1, ns2, b);
   1460  1.1.1.1.2.2  yamt                         break;
   1461  1.1.1.1.2.2  yamt                       case _URE_STAR:
   1462  1.1.1.1.2.2  yamt                         ns1 = b->expr[s1].lhs;
   1463  1.1.1.1.2.2  yamt                         ns2 = _ure_make_expr(_URE_AND, ns1, state, b);
   1464  1.1.1.1.2.2  yamt                         state = _ure_make_expr(_URE_OR, s2, ns2, b);
   1465  1.1.1.1.2.2  yamt                         break;
   1466  1.1.1.1.2.2  yamt                       case _URE_OR:
   1467  1.1.1.1.2.2  yamt                         ns1 = b->expr[s1].lhs;
   1468  1.1.1.1.2.2  yamt                         ns2 = b->expr[s1].rhs;
   1469  1.1.1.1.2.2  yamt                         ns1 = _ure_make_expr(_URE_AND, ns1, s2, b);
   1470  1.1.1.1.2.2  yamt                         ns2 = _ure_make_expr(_URE_AND, ns2, s2, b);
   1471  1.1.1.1.2.2  yamt                         state = _ure_make_expr(_URE_OR, ns1, ns2, b);
   1472  1.1.1.1.2.2  yamt                         break;
   1473  1.1.1.1.2.2  yamt                       case _URE_AND:
   1474  1.1.1.1.2.2  yamt                         ns1 = b->expr[s1].lhs;
   1475  1.1.1.1.2.2  yamt                         ns2 = b->expr[s1].rhs;
   1476  1.1.1.1.2.2  yamt                         ns2 = _ure_make_expr(_URE_AND, ns2, s2, b);
   1477  1.1.1.1.2.2  yamt                         state = _ure_make_expr(_URE_AND, ns1, ns2, b);
   1478  1.1.1.1.2.2  yamt                         break;
   1479  1.1.1.1.2.2  yamt                     }
   1480  1.1.1.1.2.2  yamt                 }
   1481  1.1.1.1.2.2  yamt             }
   1482  1.1.1.1.2.2  yamt         }
   1483  1.1.1.1.2.2  yamt 
   1484  1.1.1.1.2.2  yamt         /*
   1485  1.1.1.1.2.2  yamt          * Clear the state stack.
   1486  1.1.1.1.2.2  yamt          */
   1487  1.1.1.1.2.2  yamt         while (_ure_pop(b) != _URE_NOOP) ;
   1488  1.1.1.1.2.2  yamt 
   1489  1.1.1.1.2.2  yamt         /*
   1490  1.1.1.1.2.2  yamt          * Reset the state pointer because the reduction may have moved it
   1491  1.1.1.1.2.2  yamt          * during a reallocation.
   1492  1.1.1.1.2.2  yamt          */
   1493  1.1.1.1.2.2  yamt         sp = b->states.states + i;
   1494  1.1.1.1.2.2  yamt 
   1495  1.1.1.1.2.2  yamt         /*
   1496  1.1.1.1.2.2  yamt          * Generate the DFA states for the symbols collected during the
   1497  1.1.1.1.2.2  yamt          * current reduction.
   1498  1.1.1.1.2.2  yamt          */
   1499  1.1.1.1.2.2  yamt         if (sp->trans_used + syms > sp->trans_size) {
   1500  1.1.1.1.2.2  yamt             if (sp->trans_size == 0)
   1501  1.1.1.1.2.2  yamt               sp->trans = (_ure_elt_t *)
   1502  1.1.1.1.2.2  yamt                   malloc(sizeof(_ure_elt_t) * (sp->trans_used + syms));
   1503  1.1.1.1.2.2  yamt             else
   1504  1.1.1.1.2.2  yamt               sp->trans = (_ure_elt_t *)
   1505  1.1.1.1.2.2  yamt                   realloc((char *) sp->trans,
   1506  1.1.1.1.2.2  yamt                           sizeof(_ure_elt_t) * (sp->trans_used + syms));
   1507  1.1.1.1.2.2  yamt             sp->trans_size = sp->trans_used + syms;
   1508  1.1.1.1.2.2  yamt         }
   1509  1.1.1.1.2.2  yamt 
   1510  1.1.1.1.2.2  yamt         /*
   1511  1.1.1.1.2.2  yamt          * Go through the symbol table and generate the DFA state transitions
   1512  1.1.1.1.2.2  yamt          * for each symbol that has collected NFA states.
   1513  1.1.1.1.2.2  yamt          */
   1514  1.1.1.1.2.2  yamt         for (j = syms = 0, smp = b->symtab; j < b->symtab_used; j++, smp++) {
   1515  1.1.1.1.2.2  yamt             sp = b->states.states + i;
   1516  1.1.1.1.2.2  yamt 
   1517  1.1.1.1.2.2  yamt             if (smp->states.slist_used > 0) {
   1518  1.1.1.1.2.2  yamt                 sp->trans[syms].lhs = smp->id;
   1519  1.1.1.1.2.2  yamt                 rhs = _ure_add_state(smp->states.slist_used,
   1520  1.1.1.1.2.2  yamt                                      smp->states.slist, b);
   1521  1.1.1.1.2.2  yamt                 /*
   1522  1.1.1.1.2.2  yamt                  * Reset the state pointer in case the reallocation moves it
   1523  1.1.1.1.2.2  yamt                  * in memory.
   1524  1.1.1.1.2.2  yamt                  */
   1525  1.1.1.1.2.2  yamt                 sp = b->states.states + i;
   1526  1.1.1.1.2.2  yamt                 sp->trans[syms].rhs = rhs;
   1527  1.1.1.1.2.2  yamt 
   1528  1.1.1.1.2.2  yamt                 smp->states.slist_used = 0;
   1529  1.1.1.1.2.2  yamt                 syms++;
   1530  1.1.1.1.2.2  yamt             }
   1531  1.1.1.1.2.2  yamt         }
   1532  1.1.1.1.2.2  yamt 
   1533  1.1.1.1.2.2  yamt         /*
   1534  1.1.1.1.2.2  yamt          * Set the number of transitions actually used.
   1535  1.1.1.1.2.2  yamt          */
   1536  1.1.1.1.2.2  yamt         sp->trans_used = syms;
   1537  1.1.1.1.2.2  yamt     }
   1538  1.1.1.1.2.2  yamt     b->reducing = 0;
   1539  1.1.1.1.2.2  yamt }
   1540  1.1.1.1.2.2  yamt 
   1541  1.1.1.1.2.2  yamt static void
   1542  1.1.1.1.2.2  yamt _ure_add_equiv(ucs2_t l, ucs2_t r, _ure_buffer_t *b)
   1543  1.1.1.1.2.2  yamt {
   1544  1.1.1.1.2.2  yamt     ucs2_t tmp;
   1545  1.1.1.1.2.2  yamt 
   1546  1.1.1.1.2.2  yamt     l = b->states.states[l].id;
   1547  1.1.1.1.2.2  yamt     r = b->states.states[r].id;
   1548  1.1.1.1.2.2  yamt 
   1549  1.1.1.1.2.2  yamt     if (l == r)
   1550  1.1.1.1.2.2  yamt       return;
   1551  1.1.1.1.2.2  yamt 
   1552  1.1.1.1.2.2  yamt     if (l > r) {
   1553  1.1.1.1.2.2  yamt         tmp = l;
   1554  1.1.1.1.2.2  yamt         l = r;
   1555  1.1.1.1.2.2  yamt         r = tmp;
   1556  1.1.1.1.2.2  yamt     }
   1557  1.1.1.1.2.2  yamt 
   1558  1.1.1.1.2.2  yamt     /*
   1559  1.1.1.1.2.2  yamt      * Check to see if the equivalence pair already exists.
   1560  1.1.1.1.2.2  yamt      */
   1561  1.1.1.1.2.2  yamt     for (tmp = 0; tmp < b->equiv_used &&
   1562  1.1.1.1.2.2  yamt              (b->equiv[tmp].l != l || b->equiv[tmp].r != r);
   1563  1.1.1.1.2.2  yamt          tmp++) ;
   1564  1.1.1.1.2.2  yamt 
   1565  1.1.1.1.2.2  yamt     if (tmp < b->equiv_used)
   1566  1.1.1.1.2.2  yamt       return;
   1567  1.1.1.1.2.2  yamt 
   1568  1.1.1.1.2.2  yamt     if (b->equiv_used == b->equiv_size) {
   1569  1.1.1.1.2.2  yamt         if (b->equiv_size == 0)
   1570  1.1.1.1.2.2  yamt           b->equiv = (_ure_equiv_t *) malloc(sizeof(_ure_equiv_t) << 3);
   1571  1.1.1.1.2.2  yamt         else
   1572  1.1.1.1.2.2  yamt           b->equiv = (_ure_equiv_t *) realloc((char *) b->equiv,
   1573  1.1.1.1.2.2  yamt                                               sizeof(_ure_equiv_t) *
   1574  1.1.1.1.2.2  yamt                                               (b->equiv_size + 8));
   1575  1.1.1.1.2.2  yamt         b->equiv_size += 8;
   1576  1.1.1.1.2.2  yamt     }
   1577  1.1.1.1.2.2  yamt     b->equiv[b->equiv_used].l = l;
   1578  1.1.1.1.2.2  yamt     b->equiv[b->equiv_used].r = r;
   1579  1.1.1.1.2.2  yamt     b->equiv_used++;
   1580  1.1.1.1.2.2  yamt }
   1581  1.1.1.1.2.2  yamt 
   1582  1.1.1.1.2.2  yamt /*
   1583  1.1.1.1.2.2  yamt  * Merge the DFA states that are equivalent.
   1584  1.1.1.1.2.2  yamt  */
   1585  1.1.1.1.2.2  yamt static void
   1586  1.1.1.1.2.2  yamt _ure_merge_equiv(_ure_buffer_t *b)
   1587  1.1.1.1.2.2  yamt {
   1588  1.1.1.1.2.2  yamt     ucs2_t i, j, k, eq, done;
   1589  1.1.1.1.2.2  yamt     _ure_state_t *sp1, *sp2, *ls, *rs;
   1590  1.1.1.1.2.2  yamt 
   1591  1.1.1.1.2.2  yamt     for (i = 0; i < b->states.states_used; i++) {
   1592  1.1.1.1.2.2  yamt         sp1 = b->states.states + i;
   1593  1.1.1.1.2.2  yamt         if (sp1->id != i)
   1594  1.1.1.1.2.2  yamt           continue;
   1595  1.1.1.1.2.2  yamt         for (j = 0; j < i; j++) {
   1596  1.1.1.1.2.2  yamt             sp2 = b->states.states + j;
   1597  1.1.1.1.2.2  yamt             if (sp2->id != j)
   1598  1.1.1.1.2.2  yamt               continue;
   1599  1.1.1.1.2.2  yamt             b->equiv_used = 0;
   1600  1.1.1.1.2.2  yamt             _ure_add_equiv(i, j, b);
   1601  1.1.1.1.2.2  yamt             for (eq = 0, done = 0; eq < b->equiv_used; eq++) {
   1602  1.1.1.1.2.2  yamt                 ls = b->states.states + b->equiv[eq].l;
   1603  1.1.1.1.2.2  yamt                 rs = b->states.states + b->equiv[eq].r;
   1604  1.1.1.1.2.2  yamt                 if (ls->accepting != rs->accepting ||
   1605  1.1.1.1.2.2  yamt                     ls->trans_used != rs->trans_used) {
   1606  1.1.1.1.2.2  yamt                     done = 1;
   1607  1.1.1.1.2.2  yamt                     break;
   1608  1.1.1.1.2.2  yamt                 }
   1609  1.1.1.1.2.2  yamt                 for (k = 0; k < ls->trans_used &&
   1610  1.1.1.1.2.2  yamt                          ls->trans[k].lhs == rs->trans[k].lhs; k++) ;
   1611  1.1.1.1.2.2  yamt                 if (k < ls->trans_used) {
   1612  1.1.1.1.2.2  yamt                     done = 1;
   1613  1.1.1.1.2.2  yamt                     break;
   1614  1.1.1.1.2.2  yamt                 }
   1615  1.1.1.1.2.2  yamt 
   1616  1.1.1.1.2.2  yamt                 for (k = 0; k < ls->trans_used; k++)
   1617  1.1.1.1.2.2  yamt                   _ure_add_equiv(ls->trans[k].rhs, rs->trans[k].rhs, b);
   1618  1.1.1.1.2.2  yamt             }
   1619  1.1.1.1.2.2  yamt             if (done == 0)
   1620  1.1.1.1.2.2  yamt               break;
   1621  1.1.1.1.2.2  yamt         }
   1622  1.1.1.1.2.2  yamt         for (eq = 0; j < i && eq < b->equiv_used; eq++)
   1623  1.1.1.1.2.2  yamt           b->states.states[b->equiv[eq].r].id =
   1624  1.1.1.1.2.2  yamt               b->states.states[b->equiv[eq].l].id;
   1625  1.1.1.1.2.2  yamt     }
   1626  1.1.1.1.2.2  yamt 
   1627  1.1.1.1.2.2  yamt     /*
   1628  1.1.1.1.2.2  yamt      * Renumber the states appropriately.
   1629  1.1.1.1.2.2  yamt      */
   1630  1.1.1.1.2.2  yamt     for (i = eq = 0, sp1 = b->states.states; i < b->states.states_used;
   1631  1.1.1.1.2.2  yamt          sp1++, i++)
   1632  1.1.1.1.2.2  yamt       sp1->id = (sp1->id == i) ? eq++ : b->states.states[sp1->id].id;
   1633  1.1.1.1.2.2  yamt }
   1634  1.1.1.1.2.2  yamt 
   1635  1.1.1.1.2.2  yamt /*************************************************************************
   1636  1.1.1.1.2.2  yamt  *
   1637  1.1.1.1.2.2  yamt  * API.
   1638  1.1.1.1.2.2  yamt  *
   1639  1.1.1.1.2.2  yamt  *************************************************************************/
   1640  1.1.1.1.2.2  yamt 
   1641  1.1.1.1.2.2  yamt ure_buffer_t
   1642  1.1.1.1.2.2  yamt ure_buffer_create(void)
   1643  1.1.1.1.2.2  yamt {
   1644  1.1.1.1.2.2  yamt     ure_buffer_t b;
   1645  1.1.1.1.2.2  yamt 
   1646  1.1.1.1.2.2  yamt     b = (ure_buffer_t) calloc(1, sizeof(_ure_buffer_t));
   1647  1.1.1.1.2.2  yamt 
   1648  1.1.1.1.2.2  yamt     return b;
   1649  1.1.1.1.2.2  yamt }
   1650  1.1.1.1.2.2  yamt 
   1651  1.1.1.1.2.2  yamt void
   1652  1.1.1.1.2.2  yamt ure_buffer_free(ure_buffer_t buf)
   1653  1.1.1.1.2.2  yamt {
   1654  1.1.1.1.2.2  yamt     unsigned long i;
   1655  1.1.1.1.2.2  yamt 
   1656  1.1.1.1.2.2  yamt     if (buf == 0)
   1657  1.1.1.1.2.2  yamt       return;
   1658  1.1.1.1.2.2  yamt 
   1659  1.1.1.1.2.2  yamt     if (buf->stack.slist_size > 0)
   1660  1.1.1.1.2.2  yamt       free((char *) buf->stack.slist);
   1661  1.1.1.1.2.2  yamt 
   1662  1.1.1.1.2.2  yamt     if (buf->expr_size > 0)
   1663  1.1.1.1.2.2  yamt       free((char *) buf->expr);
   1664  1.1.1.1.2.2  yamt 
   1665  1.1.1.1.2.2  yamt     for (i = 0; i < buf->symtab_size; i++) {
   1666  1.1.1.1.2.2  yamt         if (buf->symtab[i].states.slist_size > 0)
   1667  1.1.1.1.2.2  yamt           free((char *) buf->symtab[i].states.slist);
   1668  1.1.1.1.2.2  yamt     }
   1669  1.1.1.1.2.2  yamt 
   1670  1.1.1.1.2.2  yamt     if (buf->symtab_size > 0)
   1671  1.1.1.1.2.2  yamt       free((char *) buf->symtab);
   1672  1.1.1.1.2.2  yamt 
   1673  1.1.1.1.2.2  yamt     for (i = 0; i < buf->states.states_size; i++) {
   1674  1.1.1.1.2.2  yamt         if (buf->states.states[i].trans_size > 0)
   1675  1.1.1.1.2.2  yamt           free((char *) buf->states.states[i].trans);
   1676  1.1.1.1.2.2  yamt         if (buf->states.states[i].st.slist_size > 0)
   1677  1.1.1.1.2.2  yamt           free((char *) buf->states.states[i].st.slist);
   1678  1.1.1.1.2.2  yamt     }
   1679  1.1.1.1.2.2  yamt 
   1680  1.1.1.1.2.2  yamt     if (buf->states.states_size > 0)
   1681  1.1.1.1.2.2  yamt       free((char *) buf->states.states);
   1682  1.1.1.1.2.2  yamt 
   1683  1.1.1.1.2.2  yamt     if (buf->equiv_size > 0)
   1684  1.1.1.1.2.2  yamt       free((char *) buf->equiv);
   1685  1.1.1.1.2.2  yamt 
   1686  1.1.1.1.2.2  yamt     free((char *) buf);
   1687  1.1.1.1.2.2  yamt }
   1688  1.1.1.1.2.2  yamt 
   1689  1.1.1.1.2.2  yamt ure_dfa_t
   1690  1.1.1.1.2.2  yamt ure_compile(ucs2_t *re, unsigned long relen, int casefold, ure_buffer_t buf)
   1691  1.1.1.1.2.2  yamt {
   1692  1.1.1.1.2.2  yamt     ucs2_t i, j, state;
   1693  1.1.1.1.2.2  yamt     _ure_state_t *sp;
   1694  1.1.1.1.2.2  yamt     _ure_dstate_t *dsp;
   1695  1.1.1.1.2.2  yamt     _ure_trans_t *tp;
   1696  1.1.1.1.2.2  yamt     ure_dfa_t dfa;
   1697  1.1.1.1.2.2  yamt 
   1698  1.1.1.1.2.2  yamt     if (re == 0 || *re == 0 || relen == 0 || buf == 0)
   1699  1.1.1.1.2.2  yamt       return 0;
   1700  1.1.1.1.2.2  yamt 
   1701  1.1.1.1.2.2  yamt     /*
   1702  1.1.1.1.2.2  yamt      * Reset the various fields of the compilation buffer.  Default the flags
   1703  1.1.1.1.2.2  yamt      * to indicate the presense of the "^$" pattern.  If any other pattern
   1704  1.1.1.1.2.2  yamt      * occurs, then this flag will be removed.  This is done to catch this
   1705  1.1.1.1.2.2  yamt      * special pattern and handle it specially when matching.
   1706  1.1.1.1.2.2  yamt      */
   1707  1.1.1.1.2.2  yamt     buf->flags = _URE_DFA_BLANKLINE | ((casefold) ? _URE_DFA_CASEFOLD : 0);
   1708  1.1.1.1.2.2  yamt     buf->reducing = 0;
   1709  1.1.1.1.2.2  yamt     buf->stack.slist_used = 0;
   1710  1.1.1.1.2.2  yamt     buf->expr_used = 0;
   1711  1.1.1.1.2.2  yamt 
   1712  1.1.1.1.2.2  yamt     for (i = 0; i < buf->symtab_used; i++)
   1713  1.1.1.1.2.2  yamt       buf->symtab[i].states.slist_used = 0;
   1714  1.1.1.1.2.2  yamt     buf->symtab_used = 0;
   1715  1.1.1.1.2.2  yamt 
   1716  1.1.1.1.2.2  yamt     for (i = 0; i < buf->states.states_used; i++) {
   1717  1.1.1.1.2.2  yamt         buf->states.states[i].st.slist_used = 0;
   1718  1.1.1.1.2.2  yamt         buf->states.states[i].trans_used = 0;
   1719  1.1.1.1.2.2  yamt     }
   1720  1.1.1.1.2.2  yamt     buf->states.states_used = 0;
   1721  1.1.1.1.2.2  yamt 
   1722  1.1.1.1.2.2  yamt     /*
   1723  1.1.1.1.2.2  yamt      * Construct the NFA.  If this stage returns a 0, then an error occured or
   1724  1.1.1.1.2.2  yamt      * an empty expression was passed.
   1725  1.1.1.1.2.2  yamt      */
   1726  1.1.1.1.2.2  yamt     if ((state = _ure_re2nfa(re, relen, buf)) == _URE_NOOP)
   1727  1.1.1.1.2.2  yamt       return 0;
   1728  1.1.1.1.2.2  yamt 
   1729  1.1.1.1.2.2  yamt     /*
   1730  1.1.1.1.2.2  yamt      * Do the expression reduction to get the initial DFA.
   1731  1.1.1.1.2.2  yamt      */
   1732  1.1.1.1.2.2  yamt     _ure_reduce(state, buf);
   1733  1.1.1.1.2.2  yamt 
   1734  1.1.1.1.2.2  yamt     /*
   1735  1.1.1.1.2.2  yamt      * Merge all the equivalent DFA states.
   1736  1.1.1.1.2.2  yamt      */
   1737  1.1.1.1.2.2  yamt     _ure_merge_equiv(buf);
   1738  1.1.1.1.2.2  yamt 
   1739  1.1.1.1.2.2  yamt     /*
   1740  1.1.1.1.2.2  yamt      * Construct the minimal DFA.
   1741  1.1.1.1.2.2  yamt      */
   1742  1.1.1.1.2.2  yamt     dfa = (ure_dfa_t) malloc(sizeof(_ure_dfa_t));
   1743  1.1.1.1.2.2  yamt     (void) memset((char *) dfa, '\0', sizeof(_ure_dfa_t));
   1744  1.1.1.1.2.2  yamt 
   1745  1.1.1.1.2.2  yamt     dfa->flags = buf->flags & (_URE_DFA_CASEFOLD|_URE_DFA_BLANKLINE);
   1746  1.1.1.1.2.2  yamt 
   1747  1.1.1.1.2.2  yamt     /*
   1748  1.1.1.1.2.2  yamt      * Free up the NFA state groups and transfer the symbols from the buffer
   1749  1.1.1.1.2.2  yamt      * to the DFA.
   1750  1.1.1.1.2.2  yamt      */
   1751  1.1.1.1.2.2  yamt     for (i = 0; i < buf->symtab_size; i++) {
   1752  1.1.1.1.2.2  yamt         if (buf->symtab[i].states.slist_size > 0)
   1753  1.1.1.1.2.2  yamt           free((char *) buf->symtab[i].states.slist);
   1754  1.1.1.1.2.2  yamt     }
   1755  1.1.1.1.2.2  yamt     dfa->syms = buf->symtab;
   1756  1.1.1.1.2.2  yamt     dfa->nsyms = buf->symtab_used;
   1757  1.1.1.1.2.2  yamt 
   1758  1.1.1.1.2.2  yamt     buf->symtab_used = buf->symtab_size = 0;
   1759  1.1.1.1.2.2  yamt 
   1760  1.1.1.1.2.2  yamt     /*
   1761  1.1.1.1.2.2  yamt      * Collect the total number of states and transitions needed for the DFA.
   1762  1.1.1.1.2.2  yamt      */
   1763  1.1.1.1.2.2  yamt     for (i = state = 0, sp = buf->states.states; i < buf->states.states_used;
   1764  1.1.1.1.2.2  yamt          i++, sp++) {
   1765  1.1.1.1.2.2  yamt         if (sp->id == state) {
   1766  1.1.1.1.2.2  yamt             dfa->nstates++;
   1767  1.1.1.1.2.2  yamt             dfa->ntrans += sp->trans_used;
   1768  1.1.1.1.2.2  yamt             state++;
   1769  1.1.1.1.2.2  yamt         }
   1770  1.1.1.1.2.2  yamt     }
   1771  1.1.1.1.2.2  yamt 
   1772  1.1.1.1.2.2  yamt     /*
   1773  1.1.1.1.2.2  yamt      * Allocate enough space for the states and transitions.
   1774  1.1.1.1.2.2  yamt      */
   1775  1.1.1.1.2.2  yamt     dfa->states = (_ure_dstate_t *) malloc(sizeof(_ure_dstate_t) *
   1776  1.1.1.1.2.2  yamt                                            dfa->nstates);
   1777  1.1.1.1.2.2  yamt     dfa->trans = (_ure_trans_t *) malloc(sizeof(_ure_trans_t) * dfa->ntrans);
   1778  1.1.1.1.2.2  yamt 
   1779  1.1.1.1.2.2  yamt     /*
   1780  1.1.1.1.2.2  yamt      * Actually transfer the DFA states from the buffer.
   1781  1.1.1.1.2.2  yamt      */
   1782  1.1.1.1.2.2  yamt     dsp = dfa->states;
   1783  1.1.1.1.2.2  yamt     tp = dfa->trans;
   1784  1.1.1.1.2.2  yamt     for (i = state = 0, sp = buf->states.states; i < buf->states.states_used;
   1785  1.1.1.1.2.2  yamt          i++, sp++) {
   1786  1.1.1.1.2.2  yamt         if (sp->id == state) {
   1787  1.1.1.1.2.2  yamt             dsp->trans = tp;
   1788  1.1.1.1.2.2  yamt             dsp->ntrans = sp->trans_used;
   1789  1.1.1.1.2.2  yamt             dsp->accepting = sp->accepting;
   1790  1.1.1.1.2.2  yamt 
   1791  1.1.1.1.2.2  yamt             /*
   1792  1.1.1.1.2.2  yamt              * Add the transitions for the state.
   1793  1.1.1.1.2.2  yamt              */
   1794  1.1.1.1.2.2  yamt             for (j = 0; j < dsp->ntrans; j++, tp++) {
   1795  1.1.1.1.2.2  yamt                 tp->symbol = sp->trans[j].lhs;
   1796  1.1.1.1.2.2  yamt                 tp->next_state = buf->states.states[sp->trans[j].rhs].id;
   1797  1.1.1.1.2.2  yamt             }
   1798  1.1.1.1.2.2  yamt 
   1799  1.1.1.1.2.2  yamt             dsp++;
   1800  1.1.1.1.2.2  yamt             state++;
   1801  1.1.1.1.2.2  yamt         }
   1802  1.1.1.1.2.2  yamt     }
   1803  1.1.1.1.2.2  yamt 
   1804  1.1.1.1.2.2  yamt     return dfa;
   1805  1.1.1.1.2.2  yamt }
   1806  1.1.1.1.2.2  yamt 
   1807  1.1.1.1.2.2  yamt void
   1808  1.1.1.1.2.2  yamt ure_dfa_free(ure_dfa_t dfa)
   1809  1.1.1.1.2.2  yamt {
   1810  1.1.1.1.2.2  yamt     ucs2_t i;
   1811  1.1.1.1.2.2  yamt 
   1812  1.1.1.1.2.2  yamt     if (dfa == 0)
   1813  1.1.1.1.2.2  yamt       return;
   1814  1.1.1.1.2.2  yamt 
   1815  1.1.1.1.2.2  yamt     for (i = 0; i < dfa->nsyms; i++) {
   1816  1.1.1.1.2.2  yamt         if ((dfa->syms[i].type == _URE_CCLASS ||
   1817  1.1.1.1.2.2  yamt              dfa->syms[i].type == _URE_NCCLASS) &&
   1818  1.1.1.1.2.2  yamt             dfa->syms[i].sym.ccl.ranges_size > 0)
   1819  1.1.1.1.2.2  yamt           free((char *) dfa->syms[i].sym.ccl.ranges);
   1820  1.1.1.1.2.2  yamt     }
   1821  1.1.1.1.2.2  yamt     if (dfa->nsyms > 0)
   1822  1.1.1.1.2.2  yamt       free((char *) dfa->syms);
   1823  1.1.1.1.2.2  yamt 
   1824  1.1.1.1.2.2  yamt     if (dfa->nstates > 0)
   1825  1.1.1.1.2.2  yamt       free((char *) dfa->states);
   1826  1.1.1.1.2.2  yamt     if (dfa->ntrans > 0)
   1827  1.1.1.1.2.2  yamt       free((char *) dfa->trans);
   1828  1.1.1.1.2.2  yamt     free((char *) dfa);
   1829  1.1.1.1.2.2  yamt }
   1830  1.1.1.1.2.2  yamt 
   1831  1.1.1.1.2.2  yamt void
   1832  1.1.1.1.2.2  yamt ure_write_dfa(ure_dfa_t dfa, FILE *out)
   1833  1.1.1.1.2.2  yamt {
   1834  1.1.1.1.2.2  yamt     ucs2_t i, j, k, h, l;
   1835  1.1.1.1.2.2  yamt     _ure_dstate_t *sp;
   1836  1.1.1.1.2.2  yamt     _ure_symtab_t *sym;
   1837  1.1.1.1.2.2  yamt     _ure_range_t *rp;
   1838  1.1.1.1.2.2  yamt 
   1839  1.1.1.1.2.2  yamt     if (dfa == 0 || out == 0)
   1840  1.1.1.1.2.2  yamt       return;
   1841  1.1.1.1.2.2  yamt 
   1842  1.1.1.1.2.2  yamt     /*
   1843  1.1.1.1.2.2  yamt      * Write all the different character classes.
   1844  1.1.1.1.2.2  yamt      */
   1845  1.1.1.1.2.2  yamt     for (i = 0, sym = dfa->syms; i < dfa->nsyms; i++, sym++) {
   1846  1.1.1.1.2.2  yamt         if (sym->type == _URE_CCLASS || sym->type == _URE_NCCLASS) {
   1847  1.1.1.1.2.2  yamt             fprintf(out, "C%hd = ", sym->id);
   1848  1.1.1.1.2.2  yamt             if (sym->sym.ccl.ranges_used > 0) {
   1849  1.1.1.1.2.2  yamt                 putc('[', out);
   1850  1.1.1.1.2.2  yamt                 if (sym->type == _URE_NCCLASS)
   1851  1.1.1.1.2.2  yamt                   putc('^', out);
   1852  1.1.1.1.2.2  yamt             }
   1853  1.1.1.1.2.2  yamt             if (sym->props != 0) {
   1854  1.1.1.1.2.2  yamt                 if (sym->type == _URE_NCCLASS)
   1855  1.1.1.1.2.2  yamt                   fprintf(out, "\\P");
   1856  1.1.1.1.2.2  yamt                 else
   1857  1.1.1.1.2.2  yamt                   fprintf(out, "\\p");
   1858  1.1.1.1.2.2  yamt                 for (k = h = 0; k < 32; k++) {
   1859  1.1.1.1.2.2  yamt                     if (sym->props & (1 << k)) {
   1860  1.1.1.1.2.2  yamt                         if (h != 0)
   1861  1.1.1.1.2.2  yamt                           putc(',', out);
   1862  1.1.1.1.2.2  yamt                         fprintf(out, "%hd", k + 1);
   1863  1.1.1.1.2.2  yamt                         h = 1;
   1864  1.1.1.1.2.2  yamt                     }
   1865  1.1.1.1.2.2  yamt                 }
   1866  1.1.1.1.2.2  yamt             }
   1867  1.1.1.1.2.2  yamt             /*
   1868  1.1.1.1.2.2  yamt              * Dump the ranges.
   1869  1.1.1.1.2.2  yamt              */
   1870  1.1.1.1.2.2  yamt             for (k = 0, rp = sym->sym.ccl.ranges;
   1871  1.1.1.1.2.2  yamt                  k < sym->sym.ccl.ranges_used; k++, rp++) {
   1872  1.1.1.1.2.2  yamt                 /*
   1873  1.1.1.1.2.2  yamt                  * Check for UTF16 characters.
   1874  1.1.1.1.2.2  yamt                  */
   1875  1.1.1.1.2.2  yamt                 if (0x10000 <= rp->min_code &&
   1876  1.1.1.1.2.2  yamt                     rp->min_code <= 0x10ffff) {
   1877  1.1.1.1.2.2  yamt                     h = (ucs2_t) (((rp->min_code - 0x10000) >> 10) + 0xd800);
   1878  1.1.1.1.2.2  yamt                     l = (ucs2_t) (((rp->min_code - 0x10000) & 1023) + 0xdc00);
   1879  1.1.1.1.2.2  yamt                     fprintf(out, "\\x%04hX\\x%04hX", h, l);
   1880  1.1.1.1.2.2  yamt                 } else
   1881  1.1.1.1.2.2  yamt                   fprintf(out, "\\x%04lX", rp->min_code & 0xffff);
   1882  1.1.1.1.2.2  yamt                 if (rp->max_code != rp->min_code) {
   1883  1.1.1.1.2.2  yamt                     putc('-', out);
   1884  1.1.1.1.2.2  yamt                     if (rp->max_code >= 0x10000 &&
   1885  1.1.1.1.2.2  yamt                         rp->max_code <= 0x10ffff) {
   1886  1.1.1.1.2.2  yamt                         h = (ucs2_t) (((rp->max_code - 0x10000) >> 10) + 0xd800);
   1887  1.1.1.1.2.2  yamt                         l = (ucs2_t) (((rp->max_code - 0x10000) & 1023) + 0xdc00);
   1888  1.1.1.1.2.2  yamt                         fprintf(out, "\\x%04hX\\x%04hX", h, l);
   1889  1.1.1.1.2.2  yamt                     } else
   1890  1.1.1.1.2.2  yamt                       fprintf(out, "\\x%04lX", rp->max_code & 0xffff);
   1891  1.1.1.1.2.2  yamt                 }
   1892  1.1.1.1.2.2  yamt             }
   1893  1.1.1.1.2.2  yamt             if (sym->sym.ccl.ranges_used > 0)
   1894  1.1.1.1.2.2  yamt               putc(']', out);
   1895  1.1.1.1.2.2  yamt             putc('\n', out);
   1896  1.1.1.1.2.2  yamt         }
   1897  1.1.1.1.2.2  yamt     }
   1898  1.1.1.1.2.2  yamt 
   1899  1.1.1.1.2.2  yamt     for (i = 0, sp = dfa->states; i < dfa->nstates; i++, sp++) {
   1900  1.1.1.1.2.2  yamt         fprintf(out, "S%hd = ", i);
   1901  1.1.1.1.2.2  yamt         if (sp->accepting) {
   1902  1.1.1.1.2.2  yamt             fprintf(out, "1 ");
   1903  1.1.1.1.2.2  yamt             if (sp->ntrans)
   1904  1.1.1.1.2.2  yamt               fprintf(out, "| ");
   1905  1.1.1.1.2.2  yamt         }
   1906  1.1.1.1.2.2  yamt         for (j = 0; j < sp->ntrans; j++) {
   1907  1.1.1.1.2.2  yamt             if (j > 0)
   1908  1.1.1.1.2.2  yamt               fprintf(out, "| ");
   1909  1.1.1.1.2.2  yamt 
   1910  1.1.1.1.2.2  yamt             sym = dfa->syms + sp->trans[j].symbol;
   1911  1.1.1.1.2.2  yamt             switch (sym->type) {
   1912  1.1.1.1.2.2  yamt               case _URE_CHAR:
   1913  1.1.1.1.2.2  yamt                 if (0x10000 <= sym->sym.chr && sym->sym.chr <= 0x10ffff) {
   1914  1.1.1.1.2.2  yamt                     /*
   1915  1.1.1.1.2.2  yamt                      * Take care of UTF16 characters.
   1916  1.1.1.1.2.2  yamt                      */
   1917  1.1.1.1.2.2  yamt                     h = (ucs2_t) (((sym->sym.chr - 0x10000) >> 10) + 0xd800);
   1918  1.1.1.1.2.2  yamt                     l = (ucs2_t) (((sym->sym.chr - 0x10000) & 1023) + 0xdc00);
   1919  1.1.1.1.2.2  yamt                     fprintf(out, "\\x%04hX\\x%04hX ", h, l);
   1920  1.1.1.1.2.2  yamt                 } else
   1921  1.1.1.1.2.2  yamt                   fprintf(out, "\\x%04lX ", sym->sym.chr & 0xffff);
   1922  1.1.1.1.2.2  yamt                 break;
   1923  1.1.1.1.2.2  yamt               case _URE_ANY_CHAR:
   1924  1.1.1.1.2.2  yamt                 fprintf(out, "<any> ");
   1925  1.1.1.1.2.2  yamt                 break;
   1926  1.1.1.1.2.2  yamt               case _URE_BOL_ANCHOR:
   1927  1.1.1.1.2.2  yamt                 fprintf(out, "<bol-anchor> ");
   1928  1.1.1.1.2.2  yamt                 break;
   1929  1.1.1.1.2.2  yamt               case _URE_EOL_ANCHOR:
   1930  1.1.1.1.2.2  yamt                 fprintf(out, "<eol-anchor> ");
   1931  1.1.1.1.2.2  yamt                 break;
   1932  1.1.1.1.2.2  yamt               case _URE_CCLASS:
   1933  1.1.1.1.2.2  yamt               case _URE_NCCLASS:
   1934  1.1.1.1.2.2  yamt                 fprintf(out, "[C%hd] ", sym->id);
   1935  1.1.1.1.2.2  yamt                 break;
   1936  1.1.1.1.2.2  yamt             }
   1937  1.1.1.1.2.2  yamt             fprintf(out, "S%hd", sp->trans[j].next_state);
   1938  1.1.1.1.2.2  yamt             if (j + 1 < sp->ntrans)
   1939  1.1.1.1.2.2  yamt               putc(' ', out);
   1940  1.1.1.1.2.2  yamt         }
   1941  1.1.1.1.2.2  yamt         putc('\n', out);
   1942  1.1.1.1.2.2  yamt     }
   1943  1.1.1.1.2.2  yamt }
   1944  1.1.1.1.2.2  yamt 
   1945  1.1.1.1.2.2  yamt #define _ure_issep(cc) ((cc) == '\n' || (cc) == '\r' || (cc) == 0x2028 ||\
   1946  1.1.1.1.2.2  yamt                         (cc) == 0x2029)
   1947  1.1.1.1.2.2  yamt 
   1948  1.1.1.1.2.2  yamt int
   1949  1.1.1.1.2.2  yamt ure_exec(ure_dfa_t dfa, int flags, ucs2_t *text, unsigned long textlen,
   1950  1.1.1.1.2.2  yamt          unsigned long *match_start, unsigned long *match_end)
   1951  1.1.1.1.2.2  yamt {
   1952  1.1.1.1.2.2  yamt     int i, j, matched, found, skip;
   1953  1.1.1.1.2.2  yamt     unsigned long ms, me;
   1954  1.1.1.1.2.2  yamt     ucs4_t c;
   1955  1.1.1.1.2.2  yamt     ucs2_t *sp, *ep, *lp;
   1956  1.1.1.1.2.2  yamt     _ure_dstate_t *stp;
   1957  1.1.1.1.2.2  yamt     _ure_symtab_t *sym;
   1958  1.1.1.1.2.2  yamt     _ure_range_t *rp;
   1959  1.1.1.1.2.2  yamt 
   1960  1.1.1.1.2.2  yamt     if (dfa == 0 || text == 0)
   1961  1.1.1.1.2.2  yamt       return 0;
   1962  1.1.1.1.2.2  yamt 
   1963  1.1.1.1.2.2  yamt     /*
   1964  1.1.1.1.2.2  yamt      * Handle the special case of an empty string matching the "^$" pattern.
   1965  1.1.1.1.2.2  yamt      */
   1966  1.1.1.1.2.2  yamt     if (textlen == 0 && (dfa->flags & _URE_DFA_BLANKLINE)) {
   1967  1.1.1.1.2.2  yamt         *match_start = *match_end = 0;
   1968  1.1.1.1.2.2  yamt         return 1;
   1969  1.1.1.1.2.2  yamt     }
   1970  1.1.1.1.2.2  yamt 
   1971  1.1.1.1.2.2  yamt     sp = text;
   1972  1.1.1.1.2.2  yamt     ep = sp + textlen;
   1973  1.1.1.1.2.2  yamt 
   1974  1.1.1.1.2.2  yamt     ms = me = ~0;
   1975  1.1.1.1.2.2  yamt 
   1976  1.1.1.1.2.2  yamt     stp = dfa->states;
   1977  1.1.1.1.2.2  yamt 
   1978  1.1.1.1.2.2  yamt     for (found = skip = 0; found == 0 && sp < ep; ) {
   1979  1.1.1.1.2.2  yamt         lp = sp;
   1980  1.1.1.1.2.2  yamt         c = *sp++;
   1981  1.1.1.1.2.2  yamt 
   1982  1.1.1.1.2.2  yamt         /*
   1983  1.1.1.1.2.2  yamt          * Check to see if this is a high surrogate that should be
   1984  1.1.1.1.2.2  yamt          * combined with a following low surrogate.
   1985  1.1.1.1.2.2  yamt          */
   1986  1.1.1.1.2.2  yamt         if (sp < ep && 0xd800 <= c && c <= 0xdbff &&
   1987  1.1.1.1.2.2  yamt             0xdc00 <= *sp && *sp <= 0xdfff)
   1988  1.1.1.1.2.2  yamt           c = 0x10000 + (((c & 0x03ff) << 10) | (*sp++ & 0x03ff));
   1989  1.1.1.1.2.2  yamt 
   1990  1.1.1.1.2.2  yamt         /*
   1991  1.1.1.1.2.2  yamt          * Determine if the character is non-spacing and should be skipped.
   1992  1.1.1.1.2.2  yamt          */
   1993  1.1.1.1.2.2  yamt         if (_ure_matches_properties(_URE_NONSPACING, c) &&
   1994  1.1.1.1.2.2  yamt             (flags & URE_IGNORE_NONSPACING)) {
   1995  1.1.1.1.2.2  yamt             sp++;
   1996  1.1.1.1.2.2  yamt             continue;
   1997  1.1.1.1.2.2  yamt         }
   1998  1.1.1.1.2.2  yamt 
   1999  1.1.1.1.2.2  yamt         if (dfa->flags & _URE_DFA_CASEFOLD)
   2000  1.1.1.1.2.2  yamt           c = _ure_tolower(c);
   2001  1.1.1.1.2.2  yamt 
   2002  1.1.1.1.2.2  yamt         /*
   2003  1.1.1.1.2.2  yamt          * See if one of the transitions matches.
   2004  1.1.1.1.2.2  yamt          */
   2005  1.1.1.1.2.2  yamt         for (i = 0, matched = 0; matched == 0 && i < stp->ntrans; i++) {
   2006  1.1.1.1.2.2  yamt             sym = dfa->syms + stp->trans[i].symbol;
   2007  1.1.1.1.2.2  yamt             switch (sym->type) {
   2008  1.1.1.1.2.2  yamt               case _URE_ANY_CHAR:
   2009  1.1.1.1.2.2  yamt                 if ((flags & URE_DOT_MATCHES_SEPARATORS) ||
   2010  1.1.1.1.2.2  yamt                     !_ure_issep(c))
   2011  1.1.1.1.2.2  yamt                   matched = 1;
   2012  1.1.1.1.2.2  yamt                 break;
   2013  1.1.1.1.2.2  yamt               case _URE_CHAR:
   2014  1.1.1.1.2.2  yamt                 if (c == sym->sym.chr)
   2015  1.1.1.1.2.2  yamt                   matched = 1;
   2016  1.1.1.1.2.2  yamt                 break;
   2017  1.1.1.1.2.2  yamt               case _URE_BOL_ANCHOR:
   2018  1.1.1.1.2.2  yamt                 if (lp == text) {
   2019  1.1.1.1.2.2  yamt                     sp = lp;
   2020  1.1.1.1.2.2  yamt                     matched = 1;
   2021  1.1.1.1.2.2  yamt                 } else if (_ure_issep(c)) {
   2022  1.1.1.1.2.2  yamt                     if (c == '\r' && sp < ep && *sp == '\n')
   2023  1.1.1.1.2.2  yamt                       sp++;
   2024  1.1.1.1.2.2  yamt                     lp = sp;
   2025  1.1.1.1.2.2  yamt                     matched = 1;
   2026  1.1.1.1.2.2  yamt                 }
   2027  1.1.1.1.2.2  yamt                 break;
   2028  1.1.1.1.2.2  yamt               case _URE_EOL_ANCHOR:
   2029  1.1.1.1.2.2  yamt                 if (_ure_issep(c)) {
   2030  1.1.1.1.2.2  yamt                     /*
   2031  1.1.1.1.2.2  yamt                      * Put the pointer back before the separator so the match
   2032  1.1.1.1.2.2  yamt                      * end position will be correct.  This case will also
   2033  1.1.1.1.2.2  yamt                      * cause the `sp' pointer to be advanced over the current
   2034  1.1.1.1.2.2  yamt                      * separator once the match end point has been recorded.
   2035  1.1.1.1.2.2  yamt                      */
   2036  1.1.1.1.2.2  yamt                     sp = lp;
   2037  1.1.1.1.2.2  yamt                     matched = 1;
   2038  1.1.1.1.2.2  yamt                 }
   2039  1.1.1.1.2.2  yamt                 break;
   2040  1.1.1.1.2.2  yamt               case _URE_CCLASS:
   2041  1.1.1.1.2.2  yamt               case _URE_NCCLASS:
   2042  1.1.1.1.2.2  yamt                 if (sym->props != 0)
   2043  1.1.1.1.2.2  yamt                   matched = _ure_matches_properties(sym->props, c);
   2044  1.1.1.1.2.2  yamt                 for (j = 0, rp = sym->sym.ccl.ranges;
   2045  1.1.1.1.2.2  yamt                      j < sym->sym.ccl.ranges_used; j++, rp++) {
   2046  1.1.1.1.2.2  yamt                     if (rp->min_code <= c && c <= rp->max_code)
   2047  1.1.1.1.2.2  yamt                       matched = 1;
   2048  1.1.1.1.2.2  yamt                 }
   2049  1.1.1.1.2.2  yamt                 if (sym->type == _URE_NCCLASS)
   2050  1.1.1.1.2.2  yamt                   matched = !matched;
   2051  1.1.1.1.2.2  yamt                 break;
   2052  1.1.1.1.2.2  yamt             }
   2053  1.1.1.1.2.2  yamt 
   2054  1.1.1.1.2.2  yamt             if (matched) {
   2055  1.1.1.1.2.2  yamt                 if (ms == ~0UL)
   2056  1.1.1.1.2.2  yamt                   ms = lp - text;
   2057  1.1.1.1.2.2  yamt                 else
   2058  1.1.1.1.2.2  yamt                   me = sp - text;
   2059  1.1.1.1.2.2  yamt                 stp = dfa->states + stp->trans[i].next_state;
   2060  1.1.1.1.2.2  yamt 
   2061  1.1.1.1.2.2  yamt                 /*
   2062  1.1.1.1.2.2  yamt                  * If the match was an EOL anchor, adjust the pointer past the
   2063  1.1.1.1.2.2  yamt                  * separator that caused the match.  The correct match
   2064  1.1.1.1.2.2  yamt                  * position has been recorded already.
   2065  1.1.1.1.2.2  yamt                  */
   2066  1.1.1.1.2.2  yamt                 if (sym->type == _URE_EOL_ANCHOR) {
   2067  1.1.1.1.2.2  yamt                     /*
   2068  1.1.1.1.2.2  yamt                      * Skip the character that caused the match.
   2069  1.1.1.1.2.2  yamt                      */
   2070  1.1.1.1.2.2  yamt                     sp++;
   2071  1.1.1.1.2.2  yamt 
   2072  1.1.1.1.2.2  yamt                     /*
   2073  1.1.1.1.2.2  yamt                      * Handle the infamous CRLF situation.
   2074  1.1.1.1.2.2  yamt                      */
   2075  1.1.1.1.2.2  yamt                     if (sp < ep && c == '\r' && *sp == '\n')
   2076  1.1.1.1.2.2  yamt                       sp++;
   2077  1.1.1.1.2.2  yamt                 }
   2078  1.1.1.1.2.2  yamt             }
   2079  1.1.1.1.2.2  yamt         }
   2080  1.1.1.1.2.2  yamt 
   2081  1.1.1.1.2.2  yamt         if (matched == 0) {
   2082  1.1.1.1.2.2  yamt             if (stp->accepting == 0) {
   2083  1.1.1.1.2.2  yamt                 /*
   2084  1.1.1.1.2.2  yamt                  * If the last state was not accepting, then reset
   2085  1.1.1.1.2.2  yamt                  * and start over.
   2086  1.1.1.1.2.2  yamt                  */
   2087  1.1.1.1.2.2  yamt                 stp = dfa->states;
   2088  1.1.1.1.2.2  yamt                 ms = me = ~0;
   2089  1.1.1.1.2.2  yamt             } else
   2090  1.1.1.1.2.2  yamt               /*
   2091  1.1.1.1.2.2  yamt                * The last state was accepting, so terminate the matching
   2092  1.1.1.1.2.2  yamt                * loop to avoid more work.
   2093  1.1.1.1.2.2  yamt                */
   2094  1.1.1.1.2.2  yamt               found = 1;
   2095  1.1.1.1.2.2  yamt         } else if (sp == ep) {
   2096  1.1.1.1.2.2  yamt             if (!stp->accepting) {
   2097  1.1.1.1.2.2  yamt                 /*
   2098  1.1.1.1.2.2  yamt                  * This ugly hack is to make sure the end-of-line anchors
   2099  1.1.1.1.2.2  yamt                  * match when the source text hits the end.  This is only done
   2100  1.1.1.1.2.2  yamt                  * if the last subexpression matches.
   2101  1.1.1.1.2.2  yamt                  */
   2102  1.1.1.1.2.2  yamt                 for (i = 0; found == 0 && i < stp->ntrans; i++) {
   2103  1.1.1.1.2.2  yamt                     sym = dfa->syms + stp->trans[i].symbol;
   2104  1.1.1.1.2.2  yamt                     if (sym->type ==_URE_EOL_ANCHOR) {
   2105  1.1.1.1.2.2  yamt                         stp = dfa->states + stp->trans[i].next_state;
   2106  1.1.1.1.2.2  yamt                         if (stp->accepting) {
   2107  1.1.1.1.2.2  yamt                             me = sp - text;
   2108  1.1.1.1.2.2  yamt                             found = 1;
   2109  1.1.1.1.2.2  yamt                         } else
   2110  1.1.1.1.2.2  yamt                           break;
   2111  1.1.1.1.2.2  yamt                     }
   2112  1.1.1.1.2.2  yamt                 }
   2113  1.1.1.1.2.2  yamt             } else {
   2114  1.1.1.1.2.2  yamt                 /*
   2115  1.1.1.1.2.2  yamt                  * Make sure any conditions that match all the way to the end
   2116  1.1.1.1.2.2  yamt                  * of the string match.
   2117  1.1.1.1.2.2  yamt                  */
   2118  1.1.1.1.2.2  yamt                 found = 1;
   2119  1.1.1.1.2.2  yamt                 me = sp - text;
   2120  1.1.1.1.2.2  yamt             }
   2121  1.1.1.1.2.2  yamt         }
   2122  1.1.1.1.2.2  yamt     }
   2123  1.1.1.1.2.2  yamt 
   2124  1.1.1.1.2.2  yamt     if (found == 0)
   2125  1.1.1.1.2.2  yamt       ms = me = ~0;
   2126  1.1.1.1.2.2  yamt 
   2127  1.1.1.1.2.2  yamt     *match_start = ms;
   2128  1.1.1.1.2.2  yamt     *match_end = me;
   2129  1.1.1.1.2.2  yamt 
   2130  1.1.1.1.2.2  yamt     return (ms != ~0UL) ? 1 : 0;
   2131  1.1.1.1.2.2  yamt }
   2132