Home | History | Annotate | Download | only in Oniguruma
      1 /**********************************************************************
      2   regerror.c -  Oniguruma (regular expression library)
      3 **********************************************************************/
      4 /*-
      5  * Copyright (c) 2002-2007  K.Kosako  <sndgk393 AT ybb DOT ne DOT jp>
      6  * All rights reserved.
      7  *
      8  * (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #define HAVE_STDARG_PROTOTYPES
     33 
     34 #include "regint.h"
     35 
     36 #if 0
     37 #include <stdio.h> /* for vsnprintf() */
     38 
     39 #ifdef HAVE_STDARG_PROTOTYPES
     40 #include <stdarg.h>
     41 #define va_init_list(a,b) va_start(a,b)
     42 #else
     43 #include <varargs.h>
     44 #define va_init_list(a,b) va_start(a)
     45 #endif
     46 #endif
     47 
     48 extern UChar*
     49 onig_error_code_to_format(int code)
     50 {
     51   char *p;
     52 
     53   if (code >= 0) return (UChar* )0;
     54 
     55   switch (code) {
     56   case ONIG_MISMATCH:
     57     p = "mismatch"; break;
     58   case ONIG_NO_SUPPORT_CONFIG:
     59     p = "no support in this configuration"; break;
     60   case ONIGERR_MEMORY:
     61     p = "fail to memory allocation"; break;
     62   case ONIGERR_MATCH_STACK_LIMIT_OVER:
     63     p = "match-stack limit over"; break;
     64   case ONIGERR_TYPE_BUG:
     65     p = "undefined type (bug)"; break;
     66   case ONIGERR_PARSER_BUG:
     67     p = "internal parser error (bug)"; break;
     68   case ONIGERR_STACK_BUG:
     69     p = "stack error (bug)"; break;
     70   case ONIGERR_UNDEFINED_BYTECODE:
     71     p = "undefined bytecode (bug)"; break;
     72   case ONIGERR_UNEXPECTED_BYTECODE:
     73     p = "unexpected bytecode (bug)"; break;
     74   case ONIGERR_DEFAULT_ENCODING_IS_NOT_SETTED:
     75     p = "default multibyte-encoding is not setted"; break;
     76   case ONIGERR_SPECIFIED_ENCODING_CANT_CONVERT_TO_WIDE_CHAR:
     77     p = "can't convert to wide-char on specified multibyte-encoding"; break;
     78   case ONIGERR_INVALID_ARGUMENT:
     79     p = "invalid argument"; break;
     80   case ONIGERR_END_PATTERN_AT_LEFT_BRACE:
     81     p = "end pattern at left brace"; break;
     82   case ONIGERR_END_PATTERN_AT_LEFT_BRACKET:
     83     p = "end pattern at left bracket"; break;
     84   case ONIGERR_EMPTY_CHAR_CLASS:
     85     p = "empty char-class"; break;
     86   case ONIGERR_PREMATURE_END_OF_CHAR_CLASS:
     87     p = "premature end of char-class"; break;
     88   case ONIGERR_END_PATTERN_AT_ESCAPE:
     89     p = "end pattern at escape"; break;
     90   case ONIGERR_END_PATTERN_AT_META:
     91     p = "end pattern at meta"; break;
     92   case ONIGERR_END_PATTERN_AT_CONTROL:
     93     p = "end pattern at control"; break;
     94   case ONIGERR_META_CODE_SYNTAX:
     95     p = "invalid meta-code syntax"; break;
     96   case ONIGERR_CONTROL_CODE_SYNTAX:
     97     p = "invalid control-code syntax"; break;
     98   case ONIGERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE:
     99     p = "char-class value at end of range"; break;
    100   case ONIGERR_CHAR_CLASS_VALUE_AT_START_OF_RANGE:
    101     p = "char-class value at start of range"; break;
    102   case ONIGERR_UNMATCHED_RANGE_SPECIFIER_IN_CHAR_CLASS:
    103     p = "unmatched range specifier in char-class"; break;
    104   case ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED:
    105     p = "target of repeat operator is not specified"; break;
    106   case ONIGERR_TARGET_OF_REPEAT_OPERATOR_INVALID:
    107     p = "target of repeat operator is invalid"; break;
    108   case ONIGERR_NESTED_REPEAT_OPERATOR:
    109     p = "nested repeat operator"; break;
    110   case ONIGERR_UNMATCHED_CLOSE_PARENTHESIS:
    111     p = "unmatched close parenthesis"; break;
    112   case ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS:
    113     p = "end pattern with unmatched parenthesis"; break;
    114   case ONIGERR_END_PATTERN_IN_GROUP:
    115     p = "end pattern in group"; break;
    116   case ONIGERR_UNDEFINED_GROUP_OPTION:
    117     p = "undefined group option"; break;
    118   case ONIGERR_INVALID_POSIX_BRACKET_TYPE:
    119     p = "invalid POSIX bracket type"; break;
    120   case ONIGERR_INVALID_LOOK_BEHIND_PATTERN:
    121     p = "invalid pattern in look-behind"; break;
    122   case ONIGERR_INVALID_REPEAT_RANGE_PATTERN:
    123     p = "invalid repeat range {lower,upper}"; break;
    124   case ONIGERR_TOO_BIG_NUMBER:
    125     p = "too big number"; break;
    126   case ONIGERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE:
    127     p = "too big number for repeat range"; break;
    128   case ONIGERR_UPPER_SMALLER_THAN_LOWER_IN_REPEAT_RANGE:
    129     p = "upper is smaller than lower in repeat range"; break;
    130   case ONIGERR_EMPTY_RANGE_IN_CHAR_CLASS:
    131     p = "empty range in char class"; break;
    132   case ONIGERR_MISMATCH_CODE_LENGTH_IN_CLASS_RANGE:
    133     p = "mismatch multibyte code length in char-class range"; break;
    134   case ONIGERR_TOO_MANY_MULTI_BYTE_RANGES:
    135     p = "too many multibyte code ranges are specified"; break;
    136   case ONIGERR_TOO_SHORT_MULTI_BYTE_STRING:
    137     p = "too short multibyte code string"; break;
    138   case ONIGERR_TOO_BIG_BACKREF_NUMBER:
    139     p = "too big backref number"; break;
    140   case ONIGERR_INVALID_BACKREF:
    141 #ifdef USE_NAMED_GROUP
    142     p = "invalid backref number/name"; break;
    143 #else
    144     p = "invalid backref number"; break;
    145 #endif
    146   case ONIGERR_NUMBERED_BACKREF_OR_CALL_NOT_ALLOWED:
    147     p = "numbered backref/call is not allowed. (use name)"; break;
    148   case ONIGERR_TOO_BIG_WIDE_CHAR_VALUE:
    149     p = "too big wide-char value"; break;
    150   case ONIGERR_TOO_LONG_WIDE_CHAR_VALUE:
    151     p = "too long wide-char value"; break;
    152   case ONIGERR_INVALID_CODE_POINT_VALUE:
    153     p = "invalid code point value"; break;
    154   case ONIGERR_EMPTY_GROUP_NAME:
    155     p = "group name is empty"; break;
    156   case ONIGERR_INVALID_GROUP_NAME:
    157     p = "invalid group name <%n>"; break;
    158   case ONIGERR_INVALID_CHAR_IN_GROUP_NAME:
    159 #ifdef USE_NAMED_GROUP
    160     p = "invalid char in group name <%n>"; break;
    161 #else
    162     p = "invalid char in group number <%n>"; break;
    163 #endif
    164   case ONIGERR_UNDEFINED_NAME_REFERENCE:
    165     p = "undefined name <%n> reference"; break;
    166   case ONIGERR_UNDEFINED_GROUP_REFERENCE:
    167     p = "undefined group <%n> reference"; break;
    168   case ONIGERR_MULTIPLEX_DEFINED_NAME:
    169     p = "multiplex defined name <%n>"; break;
    170   case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL:
    171     p = "multiplex definition name <%n> call"; break;
    172   case ONIGERR_NEVER_ENDING_RECURSION:
    173     p = "never ending recursion"; break;
    174   case ONIGERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY:
    175     p = "group number is too big for capture history"; break;
    176   case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
    177     p = "invalid character property name {%n}"; break;
    178   case ONIGERR_NOT_SUPPORTED_ENCODING_COMBINATION:
    179     p = "not supported encoding combination"; break;
    180   case ONIGERR_INVALID_COMBINATION_OF_OPTIONS:
    181     p = "invalid combination of options"; break;
    182   case ONIGERR_OVER_THREAD_PASS_LIMIT_COUNT:
    183     p = "over thread pass limit count"; break;
    184 
    185   default:
    186     p = "undefined error code"; break;
    187   }
    188 
    189   return (UChar* )p;
    190 }
    191 
    192 static void sprint_byte(char* s, unsigned int v)
    193 {
    194   sprintf_s(s, sizeof("00"), "%02x", (v & 0377));
    195 }
    196 
    197 static void sprint_byte_with_x(char* s, unsigned int v)
    198 {
    199   sprintf_s(s, sizeof("\\x00"), "\\x%02x", (v & 0377));
    200 }
    201 
    202 static int to_ascii(OnigEncoding enc, UChar *s, UChar *end,
    203 		    UChar buf[], int buf_size, int *is_over)
    204 {
    205   int len;
    206   UChar *p;
    207   OnigCodePoint code;
    208 
    209   if (ONIGENC_MBC_MINLEN(enc) > 1) {
    210     p = s;
    211     len = 0;
    212     while (p < end) {
    213       code = ONIGENC_MBC_TO_CODE(enc, p, end);
    214       if (code >= 0x80) {
    215 	if (code > 0xffff && len + 10 <= buf_size) {
    216 	  sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 24));
    217 	  sprint_byte((char*)(&(buf[len+4])),      (unsigned int)(code >> 16));
    218 	  sprint_byte((char*)(&(buf[len+6])),      (unsigned int)(code >>  8));
    219 	  sprint_byte((char*)(&(buf[len+8])),      (unsigned int)code);
    220 	  len += 10;
    221 	}
    222 	else if (len + 6 <= buf_size) {
    223 	  sprint_byte_with_x((char*)(&(buf[len])), (unsigned int)(code >> 8));
    224 	  sprint_byte((char*)(&(buf[len+4])),      (unsigned int)code);
    225 	  len += 6;
    226 	}
    227 	else {
    228 	  break;
    229 	}
    230       }
    231       else {
    232 	buf[len++] = (UChar )code;
    233       }
    234 
    235       p += enclen(enc, p);
    236       if (len >= buf_size) break;
    237     }
    238 
    239     *is_over = ((p < end) ? 1 : 0);
    240   }
    241   else {
    242     len = MIN((int)(end - s), buf_size);
    243     xmemcpy(buf, s, (size_t )len);
    244     *is_over = ((buf_size < (end - s)) ? 1 : 0);
    245   }
    246 
    247   return len;
    248 }
    249 
    250 
    251 /* for ONIG_MAX_ERROR_MESSAGE_LEN */
    252 #define MAX_ERROR_PAR_LEN   30
    253 
    254 extern int
    255 EFIAPI
    256 #ifdef HAVE_STDARG_PROTOTYPES
    257 onig_error_code_to_str(UChar* s, int code, ...)
    258 #else
    259 onig_error_code_to_str(s, code, va_alist)
    260   UChar* s;
    261   int code;
    262   va_dcl
    263 #endif
    264 {
    265   UChar *p, *q;
    266   OnigErrorInfo* einfo;
    267   int len, is_over;
    268   UChar parbuf[MAX_ERROR_PAR_LEN];
    269   va_list vargs;
    270 
    271   va_init_list(vargs, code);
    272 
    273   switch (code) {
    274   case ONIGERR_UNDEFINED_NAME_REFERENCE:
    275   case ONIGERR_UNDEFINED_GROUP_REFERENCE:
    276   case ONIGERR_MULTIPLEX_DEFINED_NAME:
    277   case ONIGERR_MULTIPLEX_DEFINITION_NAME_CALL:
    278   case ONIGERR_INVALID_GROUP_NAME:
    279   case ONIGERR_INVALID_CHAR_IN_GROUP_NAME:
    280   case ONIGERR_INVALID_CHAR_PROPERTY_NAME:
    281     einfo = va_arg(vargs, OnigErrorInfo*);
    282     len = to_ascii(einfo->enc, einfo->par, einfo->par_end,
    283 		   parbuf, MAX_ERROR_PAR_LEN - 3, &is_over);
    284     q = onig_error_code_to_format(code);
    285     p = s;
    286     while (*q != '\0') {
    287       if (*q == '%') {
    288 	q++;
    289 	if (*q == 'n') { /* '%n': name */
    290 	  xmemcpy(p, parbuf, len);
    291 	  p += len;
    292 	  if (is_over != 0) {
    293 	    xmemcpy(p, "...", 3);
    294 	    p += 3;
    295 	  }
    296 	  q++;
    297 	}
    298 	else
    299 	  goto normal_char;
    300       }
    301       else {
    302       normal_char:
    303 	*p++ = *q++;
    304       }
    305     }
    306     *p = '\0';
    307     len = (int)(p - s);
    308     break;
    309 
    310   default:
    311     q = onig_error_code_to_format(code);
    312     if (q == NULL) {
    313       len = 0;
    314       break;
    315     }
    316     len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, q);
    317     xmemcpy(s, q, len);
    318     s[len] = '\0';
    319     break;
    320   }
    321 
    322   va_end(vargs);
    323   return len;
    324 }
    325 
    326 
    327 void
    328 EFIAPI
    329 #ifdef HAVE_STDARG_PROTOTYPES
    330 onig_snprintf_with_pattern(UChar buf[], int bufsize, OnigEncoding enc,
    331                            UChar* pat, UChar* pat_end, const UChar *fmt, ...)
    332 #else
    333 onig_snprintf_with_pattern(buf, bufsize, enc, pat, pat_end, fmt, va_alist)
    334     UChar buf[];
    335     int bufsize;
    336     OnigEncoding enc;
    337     UChar* pat;
    338     UChar* pat_end;
    339     const UChar *fmt;
    340     va_dcl
    341 #endif
    342 {
    343   int n, need, len;
    344   UChar *p, *s, *bp;
    345   UChar bs[6];
    346   va_list args;
    347 
    348   va_init_list(args, fmt);
    349   n = xvsnprintf((char* )buf, bufsize, (const char* )fmt, args);
    350   va_end(args);
    351 
    352   need = (int)(pat_end - pat) * 4 + 4;
    353 
    354   if (n + need < bufsize) {
    355     strcat_s((char* )buf, bufsize, ": /");
    356     s = buf + onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, buf);
    357 
    358     p = pat;
    359     while (p < pat_end) {
    360       if (*p == '\\') {
    361 	*s++ = *p++;
    362 	len = enclen(enc, p);
    363 	while (len-- > 0) *s++ = *p++;
    364       }
    365       else if (*p == '/') {
    366 	*s++ = (unsigned char )'\\';
    367 	*s++ = *p++;
    368       }
    369       else if (ONIGENC_IS_MBC_HEAD(enc, p)) {
    370         len = enclen(enc, p);
    371         if (ONIGENC_MBC_MINLEN(enc) == 1) {
    372           while (len-- > 0) *s++ = *p++;
    373         }
    374         else { /* for UTF16 */
    375           int blen;
    376 
    377           while (len-- > 0) {
    378 	    sprint_byte_with_x((char* )bs, (unsigned int )(*p++));
    379             blen = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
    380             bp = bs;
    381             while (blen-- > 0) *s++ = *bp++;
    382           }
    383         }
    384       }
    385       else if (!ONIGENC_IS_CODE_PRINT(enc, *p) &&
    386 	       !ONIGENC_IS_CODE_SPACE(enc, *p)) {
    387 	sprint_byte_with_x((char* )bs, (unsigned int )(*p++));
    388 	len = onigenc_str_bytelen_null(ONIG_ENCODING_ASCII, bs);
    389         bp = bs;
    390 	while (len-- > 0) *s++ = *bp++;
    391       }
    392       else {
    393 	*s++ = *p++;
    394       }
    395     }
    396 
    397     *s++ = '/';
    398     *s   = '\0';
    399   }
    400 }
    401