1*6b5e5868SGarrett D'Amore /* 2*6b5e5868SGarrett D'Amore * This file and its contents are supplied under the terms of the 3*6b5e5868SGarrett D'Amore * Common Development and Distribution License ("CDDL"), version 1.0. 4*6b5e5868SGarrett D'Amore * You may only use this file in accordance with the terms version 1.0 5*6b5e5868SGarrett D'Amore * of the CDDL. 6*6b5e5868SGarrett D'Amore * 7*6b5e5868SGarrett D'Amore * A full copy of the text of the CDDL should have accompanied this 8*6b5e5868SGarrett D'Amore * source. A copy of the CDDL is also available via the Internet at 9*6b5e5868SGarrett D'Amore * http://www.illumos.org/license/CDDL. 10*6b5e5868SGarrett D'Amore */ 11*6b5e5868SGarrett D'Amore 12*6b5e5868SGarrett D'Amore /* 13*6b5e5868SGarrett D'Amore * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 14*6b5e5868SGarrett D'Amore */ 15*6b5e5868SGarrett D'Amore 16*6b5e5868SGarrett D'Amore /* 17*6b5e5868SGarrett D'Amore * This file contains the "scanner", which tokenizes the input files 18*6b5e5868SGarrett D'Amore * for localedef for processing by the higher level grammar processor. 19*6b5e5868SGarrett D'Amore */ 20*6b5e5868SGarrett D'Amore 21*6b5e5868SGarrett D'Amore #include <stdio.h> 22*6b5e5868SGarrett D'Amore #include <stdlib.h> 23*6b5e5868SGarrett D'Amore #include <ctype.h> 24*6b5e5868SGarrett D'Amore #include <limits.h> 25*6b5e5868SGarrett D'Amore #include <string.h> 26*6b5e5868SGarrett D'Amore #include <widec.h> 27*6b5e5868SGarrett D'Amore #include <sys/types.h> 28*6b5e5868SGarrett D'Amore #include <assert.h> 29*6b5e5868SGarrett D'Amore #include "localedef.h" 30*6b5e5868SGarrett D'Amore #include "parser.tab.h" 31*6b5e5868SGarrett D'Amore 32*6b5e5868SGarrett D'Amore int com_char = '#'; 33*6b5e5868SGarrett D'Amore int esc_char = '\\'; 34*6b5e5868SGarrett D'Amore int mb_cur_min = 1; 35*6b5e5868SGarrett D'Amore int mb_cur_max = 1; 36*6b5e5868SGarrett D'Amore int lineno = 1; 37*6b5e5868SGarrett D'Amore int warnings = 0; 38*6b5e5868SGarrett D'Amore static int nextline; 39*6b5e5868SGarrett D'Amore static FILE *input = stdin; 40*6b5e5868SGarrett D'Amore static const char *filename = "<stdin>"; 41*6b5e5868SGarrett D'Amore static int instring = 0; 42*6b5e5868SGarrett D'Amore static int escaped = 0; 43*6b5e5868SGarrett D'Amore 44*6b5e5868SGarrett D'Amore /* 45*6b5e5868SGarrett D'Amore * Token space ... grows on demand. 46*6b5e5868SGarrett D'Amore */ 47*6b5e5868SGarrett D'Amore static char *token = NULL; 48*6b5e5868SGarrett D'Amore static int tokidx; 49*6b5e5868SGarrett D'Amore static int toksz = 0; 50*6b5e5868SGarrett D'Amore static int hadtok = 0; 51*6b5e5868SGarrett D'Amore 52*6b5e5868SGarrett D'Amore /* 53*6b5e5868SGarrett D'Amore * Wide string space ... grows on demand. 54*6b5e5868SGarrett D'Amore */ 55*6b5e5868SGarrett D'Amore static wchar_t *widestr = NULL; 56*6b5e5868SGarrett D'Amore static int wideidx = 0; 57*6b5e5868SGarrett D'Amore static int widesz = 0; 58*6b5e5868SGarrett D'Amore 59*6b5e5868SGarrett D'Amore /* 60*6b5e5868SGarrett D'Amore * The last keyword seen. This is useful to trigger the special lexer rules 61*6b5e5868SGarrett D'Amore * for "copy" and also collating symbols and elements. 62*6b5e5868SGarrett D'Amore */ 63*6b5e5868SGarrett D'Amore int last_kw = 0; 64*6b5e5868SGarrett D'Amore static int category = T_END; 65*6b5e5868SGarrett D'Amore 66*6b5e5868SGarrett D'Amore static struct token { 67*6b5e5868SGarrett D'Amore int id; 68*6b5e5868SGarrett D'Amore const char *name; 69*6b5e5868SGarrett D'Amore } keywords[] = { 70*6b5e5868SGarrett D'Amore { T_COM_CHAR, "comment_char" }, 71*6b5e5868SGarrett D'Amore { T_ESC_CHAR, "escape_char" }, 72*6b5e5868SGarrett D'Amore { T_END, "END" }, 73*6b5e5868SGarrett D'Amore { T_COPY, "copy" }, 74*6b5e5868SGarrett D'Amore { T_MESSAGES, "LC_MESSAGES" }, 75*6b5e5868SGarrett D'Amore { T_YESSTR, "yesstr" }, 76*6b5e5868SGarrett D'Amore { T_YESEXPR, "yesexpr" }, 77*6b5e5868SGarrett D'Amore { T_NOSTR, "nostr" }, 78*6b5e5868SGarrett D'Amore { T_NOEXPR, "noexpr" }, 79*6b5e5868SGarrett D'Amore { T_MONETARY, "LC_MONETARY" }, 80*6b5e5868SGarrett D'Amore { T_INT_CURR_SYMBOL, "int_curr_symbol" }, 81*6b5e5868SGarrett D'Amore { T_CURRENCY_SYMBOL, "currency_symbol" }, 82*6b5e5868SGarrett D'Amore { T_MON_DECIMAL_POINT, "mon_decimal_point" }, 83*6b5e5868SGarrett D'Amore { T_MON_THOUSANDS_SEP, "mon_thousands_sep" }, 84*6b5e5868SGarrett D'Amore { T_POSITIVE_SIGN, "positive_sign" }, 85*6b5e5868SGarrett D'Amore { T_NEGATIVE_SIGN, "negative_sign" }, 86*6b5e5868SGarrett D'Amore { T_MON_GROUPING, "mon_grouping" }, 87*6b5e5868SGarrett D'Amore { T_INT_FRAC_DIGITS, "int_frac_digits" }, 88*6b5e5868SGarrett D'Amore { T_FRAC_DIGITS, "frac_digits" }, 89*6b5e5868SGarrett D'Amore { T_P_CS_PRECEDES, "p_cs_precedes" }, 90*6b5e5868SGarrett D'Amore { T_P_SEP_BY_SPACE, "p_sep_by_space" }, 91*6b5e5868SGarrett D'Amore { T_N_CS_PRECEDES, "n_cs_precedes" }, 92*6b5e5868SGarrett D'Amore { T_N_SEP_BY_SPACE, "n_sep_by_space" }, 93*6b5e5868SGarrett D'Amore { T_P_SIGN_POSN, "p_sign_posn" }, 94*6b5e5868SGarrett D'Amore { T_N_SIGN_POSN, "n_sign_posn" }, 95*6b5e5868SGarrett D'Amore { T_INT_P_CS_PRECEDES, "int_p_cs_precedes" }, 96*6b5e5868SGarrett D'Amore { T_INT_N_CS_PRECEDES, "int_n_cs_precedes" }, 97*6b5e5868SGarrett D'Amore { T_INT_P_SEP_BY_SPACE, "int_p_sep_by_space" }, 98*6b5e5868SGarrett D'Amore { T_INT_N_SEP_BY_SPACE, "int_n_sep_by_space" }, 99*6b5e5868SGarrett D'Amore { T_INT_P_SIGN_POSN, "int_p_sign_posn" }, 100*6b5e5868SGarrett D'Amore { T_INT_N_SIGN_POSN, "int_n_sign_posn" }, 101*6b5e5868SGarrett D'Amore { T_COLLATE, "LC_COLLATE" }, 102*6b5e5868SGarrett D'Amore { T_COLLATING_SYMBOL, "collating-symbol" }, 103*6b5e5868SGarrett D'Amore { T_COLLATING_ELEMENT, "collating-element" }, 104*6b5e5868SGarrett D'Amore { T_FROM, "from" }, 105*6b5e5868SGarrett D'Amore { T_ORDER_START, "order_start" }, 106*6b5e5868SGarrett D'Amore { T_ORDER_END, "order_end" }, 107*6b5e5868SGarrett D'Amore { T_FORWARD, "forward" }, 108*6b5e5868SGarrett D'Amore { T_BACKWARD, "backward" }, 109*6b5e5868SGarrett D'Amore { T_POSITION, "position" }, 110*6b5e5868SGarrett D'Amore { T_IGNORE, "IGNORE" }, 111*6b5e5868SGarrett D'Amore { T_UNDEFINED, "UNDEFINED" }, 112*6b5e5868SGarrett D'Amore { T_NUMERIC, "LC_NUMERIC" }, 113*6b5e5868SGarrett D'Amore { T_DECIMAL_POINT, "decimal_point" }, 114*6b5e5868SGarrett D'Amore { T_THOUSANDS_SEP, "thousands_sep" }, 115*6b5e5868SGarrett D'Amore { T_GROUPING, "grouping" }, 116*6b5e5868SGarrett D'Amore { T_TIME, "LC_TIME" }, 117*6b5e5868SGarrett D'Amore { T_ABDAY, "abday" }, 118*6b5e5868SGarrett D'Amore { T_DAY, "day" }, 119*6b5e5868SGarrett D'Amore { T_ABMON, "abmon" }, 120*6b5e5868SGarrett D'Amore { T_MON, "mon" }, 121*6b5e5868SGarrett D'Amore { T_D_T_FMT, "d_t_fmt" }, 122*6b5e5868SGarrett D'Amore { T_D_FMT, "d_fmt" }, 123*6b5e5868SGarrett D'Amore { T_T_FMT, "t_fmt" }, 124*6b5e5868SGarrett D'Amore { T_AM_PM, "am_pm" }, 125*6b5e5868SGarrett D'Amore { T_T_FMT_AMPM, "t_fmt_ampm" }, 126*6b5e5868SGarrett D'Amore { T_ERA, "era" }, 127*6b5e5868SGarrett D'Amore { T_ERA_D_FMT, "era_d_fmt" }, 128*6b5e5868SGarrett D'Amore { T_ERA_T_FMT, "era_t_fmt" }, 129*6b5e5868SGarrett D'Amore { T_ERA_D_T_FMT, "era_d_t_fmt" }, 130*6b5e5868SGarrett D'Amore { T_ALT_DIGITS, "alt_digits" }, 131*6b5e5868SGarrett D'Amore { T_CTYPE, "LC_CTYPE" }, 132*6b5e5868SGarrett D'Amore { T_ISUPPER, "upper" }, 133*6b5e5868SGarrett D'Amore { T_ISLOWER, "lower" }, 134*6b5e5868SGarrett D'Amore { T_ISALPHA, "alpha" }, 135*6b5e5868SGarrett D'Amore { T_ISDIGIT, "digit" }, 136*6b5e5868SGarrett D'Amore { T_ISPUNCT, "punct" }, 137*6b5e5868SGarrett D'Amore { T_ISXDIGIT, "xdigit" }, 138*6b5e5868SGarrett D'Amore { T_ISSPACE, "space" }, 139*6b5e5868SGarrett D'Amore { T_ISPRINT, "print" }, 140*6b5e5868SGarrett D'Amore { T_ISGRAPH, "graph" }, 141*6b5e5868SGarrett D'Amore { T_ISBLANK, "blank" }, 142*6b5e5868SGarrett D'Amore { T_ISCNTRL, "cntrl" }, 143*6b5e5868SGarrett D'Amore /* 144*6b5e5868SGarrett D'Amore * These entries are local additions, and not specified by 145*6b5e5868SGarrett D'Amore * TOG. Note that they are not guaranteed to be accurate for 146*6b5e5868SGarrett D'Amore * all locales, and so applications should not depend on them. 147*6b5e5868SGarrett D'Amore */ 148*6b5e5868SGarrett D'Amore { T_ISSPECIAL, "special" }, 149*6b5e5868SGarrett D'Amore { T_ISENGLISH, "english" }, 150*6b5e5868SGarrett D'Amore { T_ISPHONOGRAM, "phonogram" }, 151*6b5e5868SGarrett D'Amore { T_ISIDEOGRAM, "ideogram" }, 152*6b5e5868SGarrett D'Amore { T_ISNUMBER, "number" }, 153*6b5e5868SGarrett D'Amore /* 154*6b5e5868SGarrett D'Amore * We have to support this in the grammar, but it would be a 155*6b5e5868SGarrett D'Amore * syntax error to define a character as one of these without 156*6b5e5868SGarrett D'Amore * also defining it as an alpha or digit. We ignore it in our 157*6b5e5868SGarrett D'Amore * parsing. 158*6b5e5868SGarrett D'Amore */ 159*6b5e5868SGarrett D'Amore { T_ISALNUM, "alnum" }, 160*6b5e5868SGarrett D'Amore { T_TOUPPER, "toupper" }, 161*6b5e5868SGarrett D'Amore { T_TOLOWER, "tolower" }, 162*6b5e5868SGarrett D'Amore 163*6b5e5868SGarrett D'Amore /* 164*6b5e5868SGarrett D'Amore * These are keywords used in the charmap file. Note that 165*6b5e5868SGarrett D'Amore * Solaris orginally used angle brackets to wrap some of them, 166*6b5e5868SGarrett D'Amore * but we removed that to simplify our parser. The first of these 167*6b5e5868SGarrett D'Amore * items are "global items." 168*6b5e5868SGarrett D'Amore */ 169*6b5e5868SGarrett D'Amore { T_CHARMAP, "CHARMAP" }, 170*6b5e5868SGarrett D'Amore { T_WIDTH, "WIDTH" }, 171*6b5e5868SGarrett D'Amore { T_WIDTH_DEFAULT, "WIDTH_DEFAULT" }, 172*6b5e5868SGarrett D'Amore 173*6b5e5868SGarrett D'Amore { -1, NULL }, 174*6b5e5868SGarrett D'Amore }; 175*6b5e5868SGarrett D'Amore 176*6b5e5868SGarrett D'Amore /* 177*6b5e5868SGarrett D'Amore * These special words are only used in a charmap file, enclosed in <>. 178*6b5e5868SGarrett D'Amore */ 179*6b5e5868SGarrett D'Amore static struct token symwords[] = { 180*6b5e5868SGarrett D'Amore { T_COM_CHAR, "comment_char" }, 181*6b5e5868SGarrett D'Amore { T_ESC_CHAR, "escape_char" }, 182*6b5e5868SGarrett D'Amore { T_CODE_SET, "code_set_name" }, 183*6b5e5868SGarrett D'Amore { T_MB_CUR_MAX, "mb_cur_max" }, 184*6b5e5868SGarrett D'Amore { T_MB_CUR_MIN, "mb_cur_min" }, 185*6b5e5868SGarrett D'Amore { -1, NULL }, 186*6b5e5868SGarrett D'Amore }; 187*6b5e5868SGarrett D'Amore 188*6b5e5868SGarrett D'Amore static int categories[] = { 189*6b5e5868SGarrett D'Amore T_CHARMAP, 190*6b5e5868SGarrett D'Amore T_CTYPE, 191*6b5e5868SGarrett D'Amore T_COLLATE, 192*6b5e5868SGarrett D'Amore T_MESSAGES, 193*6b5e5868SGarrett D'Amore T_MONETARY, 194*6b5e5868SGarrett D'Amore T_NUMERIC, 195*6b5e5868SGarrett D'Amore T_TIME, 196*6b5e5868SGarrett D'Amore 0 197*6b5e5868SGarrett D'Amore }; 198*6b5e5868SGarrett D'Amore 199*6b5e5868SGarrett D'Amore void 200*6b5e5868SGarrett D'Amore reset_scanner(const char *fname) 201*6b5e5868SGarrett D'Amore { 202*6b5e5868SGarrett D'Amore if (fname == NULL) { 203*6b5e5868SGarrett D'Amore filename = "<stdin>"; 204*6b5e5868SGarrett D'Amore input = stdin; 205*6b5e5868SGarrett D'Amore } else { 206*6b5e5868SGarrett D'Amore if (input != stdin) 207*6b5e5868SGarrett D'Amore (void) fclose(input); 208*6b5e5868SGarrett D'Amore if ((input = fopen(fname, "r")) == NULL) { 209*6b5e5868SGarrett D'Amore perror("fopen"); 210*6b5e5868SGarrett D'Amore exit(4); 211*6b5e5868SGarrett D'Amore } 212*6b5e5868SGarrett D'Amore filename = fname; 213*6b5e5868SGarrett D'Amore } 214*6b5e5868SGarrett D'Amore com_char = '#'; 215*6b5e5868SGarrett D'Amore esc_char = '\\'; 216*6b5e5868SGarrett D'Amore instring = 0; 217*6b5e5868SGarrett D'Amore escaped = 0; 218*6b5e5868SGarrett D'Amore lineno = 1; 219*6b5e5868SGarrett D'Amore nextline = 1; 220*6b5e5868SGarrett D'Amore tokidx = 0; 221*6b5e5868SGarrett D'Amore wideidx = 0; 222*6b5e5868SGarrett D'Amore } 223*6b5e5868SGarrett D'Amore 224*6b5e5868SGarrett D'Amore #define hex(x) \ 225*6b5e5868SGarrett D'Amore (isdigit(x) ? (x - '0') : ((islower(x) ? (x - 'a') : (x - 'A')) + 10)) 226*6b5e5868SGarrett D'Amore #define isodigit(x) ((x >= '0') && (x <= '7')) 227*6b5e5868SGarrett D'Amore 228*6b5e5868SGarrett D'Amore static int 229*6b5e5868SGarrett D'Amore scanc(void) 230*6b5e5868SGarrett D'Amore { 231*6b5e5868SGarrett D'Amore int c; 232*6b5e5868SGarrett D'Amore 233*6b5e5868SGarrett D'Amore c = getc(input); 234*6b5e5868SGarrett D'Amore lineno = nextline; 235*6b5e5868SGarrett D'Amore if (c == '\n') { 236*6b5e5868SGarrett D'Amore nextline++; 237*6b5e5868SGarrett D'Amore } 238*6b5e5868SGarrett D'Amore return (c); 239*6b5e5868SGarrett D'Amore } 240*6b5e5868SGarrett D'Amore 241*6b5e5868SGarrett D'Amore static void 242*6b5e5868SGarrett D'Amore unscanc(int c) 243*6b5e5868SGarrett D'Amore { 244*6b5e5868SGarrett D'Amore if (c == '\n') { 245*6b5e5868SGarrett D'Amore nextline--; 246*6b5e5868SGarrett D'Amore } 247*6b5e5868SGarrett D'Amore if (ungetc(c, input) < 0) { 248*6b5e5868SGarrett D'Amore yyerror(_("ungetc failed")); 249*6b5e5868SGarrett D'Amore } 250*6b5e5868SGarrett D'Amore } 251*6b5e5868SGarrett D'Amore 252*6b5e5868SGarrett D'Amore static int 253*6b5e5868SGarrett D'Amore scan_hex_byte(void) 254*6b5e5868SGarrett D'Amore { 255*6b5e5868SGarrett D'Amore int c1, c2; 256*6b5e5868SGarrett D'Amore int v; 257*6b5e5868SGarrett D'Amore 258*6b5e5868SGarrett D'Amore c1 = scanc(); 259*6b5e5868SGarrett D'Amore if (!isxdigit(c1)) { 260*6b5e5868SGarrett D'Amore yyerror(_("malformed hex digit")); 261*6b5e5868SGarrett D'Amore return (0); 262*6b5e5868SGarrett D'Amore } 263*6b5e5868SGarrett D'Amore c2 = scanc(); 264*6b5e5868SGarrett D'Amore if (!isxdigit(c2)) { 265*6b5e5868SGarrett D'Amore yyerror(_("malformed hex digit")); 266*6b5e5868SGarrett D'Amore return (0); 267*6b5e5868SGarrett D'Amore } 268*6b5e5868SGarrett D'Amore v = ((hex(c1) << 4) | hex(c2)); 269*6b5e5868SGarrett D'Amore return (v); 270*6b5e5868SGarrett D'Amore } 271*6b5e5868SGarrett D'Amore 272*6b5e5868SGarrett D'Amore static int 273*6b5e5868SGarrett D'Amore scan_dec_byte(void) 274*6b5e5868SGarrett D'Amore { 275*6b5e5868SGarrett D'Amore int c1, c2, c3; 276*6b5e5868SGarrett D'Amore int b; 277*6b5e5868SGarrett D'Amore 278*6b5e5868SGarrett D'Amore c1 = scanc(); 279*6b5e5868SGarrett D'Amore if (!isdigit(c1)) { 280*6b5e5868SGarrett D'Amore yyerror(_("malformed decimal digit")); 281*6b5e5868SGarrett D'Amore return (0); 282*6b5e5868SGarrett D'Amore } 283*6b5e5868SGarrett D'Amore b = c1 - '0'; 284*6b5e5868SGarrett D'Amore c2 = scanc(); 285*6b5e5868SGarrett D'Amore if (!isdigit(c2)) { 286*6b5e5868SGarrett D'Amore yyerror(_("malformed decimal digit")); 287*6b5e5868SGarrett D'Amore return (0); 288*6b5e5868SGarrett D'Amore } 289*6b5e5868SGarrett D'Amore b *= 10; 290*6b5e5868SGarrett D'Amore b += (c2 - '0'); 291*6b5e5868SGarrett D'Amore c3 = scanc(); 292*6b5e5868SGarrett D'Amore if (!isdigit(c3)) { 293*6b5e5868SGarrett D'Amore unscanc(c3); 294*6b5e5868SGarrett D'Amore } else { 295*6b5e5868SGarrett D'Amore b *= 10; 296*6b5e5868SGarrett D'Amore b += (c3 - '0'); 297*6b5e5868SGarrett D'Amore } 298*6b5e5868SGarrett D'Amore return (b); 299*6b5e5868SGarrett D'Amore } 300*6b5e5868SGarrett D'Amore 301*6b5e5868SGarrett D'Amore static int 302*6b5e5868SGarrett D'Amore scan_oct_byte(void) 303*6b5e5868SGarrett D'Amore { 304*6b5e5868SGarrett D'Amore int c1, c2, c3; 305*6b5e5868SGarrett D'Amore int b; 306*6b5e5868SGarrett D'Amore 307*6b5e5868SGarrett D'Amore b = 0; 308*6b5e5868SGarrett D'Amore 309*6b5e5868SGarrett D'Amore c1 = scanc(); 310*6b5e5868SGarrett D'Amore if (!isodigit(c1)) { 311*6b5e5868SGarrett D'Amore yyerror(_("malformed octal digit")); 312*6b5e5868SGarrett D'Amore return (0); 313*6b5e5868SGarrett D'Amore } 314*6b5e5868SGarrett D'Amore b = c1 - '0'; 315*6b5e5868SGarrett D'Amore c2 = scanc(); 316*6b5e5868SGarrett D'Amore if (!isodigit(c2)) { 317*6b5e5868SGarrett D'Amore yyerror(_("malformed octal digit")); 318*6b5e5868SGarrett D'Amore return (0); 319*6b5e5868SGarrett D'Amore } 320*6b5e5868SGarrett D'Amore b *= 8; 321*6b5e5868SGarrett D'Amore b += (c2 - '0'); 322*6b5e5868SGarrett D'Amore c3 = scanc(); 323*6b5e5868SGarrett D'Amore if (!isodigit(c3)) { 324*6b5e5868SGarrett D'Amore unscanc(c3); 325*6b5e5868SGarrett D'Amore } else { 326*6b5e5868SGarrett D'Amore b *= 8; 327*6b5e5868SGarrett D'Amore b += (c3 - '0'); 328*6b5e5868SGarrett D'Amore } 329*6b5e5868SGarrett D'Amore return (b); 330*6b5e5868SGarrett D'Amore } 331*6b5e5868SGarrett D'Amore 332*6b5e5868SGarrett D'Amore void 333*6b5e5868SGarrett D'Amore add_tok(int c) 334*6b5e5868SGarrett D'Amore { 335*6b5e5868SGarrett D'Amore if ((tokidx + 1) >= toksz) { 336*6b5e5868SGarrett D'Amore toksz += 64; 337*6b5e5868SGarrett D'Amore if ((token = realloc(token, toksz)) == NULL) { 338*6b5e5868SGarrett D'Amore yyerror(_("out of memory")); 339*6b5e5868SGarrett D'Amore tokidx = 0; 340*6b5e5868SGarrett D'Amore toksz = 0; 341*6b5e5868SGarrett D'Amore return; 342*6b5e5868SGarrett D'Amore } 343*6b5e5868SGarrett D'Amore } 344*6b5e5868SGarrett D'Amore 345*6b5e5868SGarrett D'Amore token[tokidx++] = (char)c; 346*6b5e5868SGarrett D'Amore token[tokidx] = 0; 347*6b5e5868SGarrett D'Amore } 348*6b5e5868SGarrett D'Amore void 349*6b5e5868SGarrett D'Amore add_wcs(wchar_t c) 350*6b5e5868SGarrett D'Amore { 351*6b5e5868SGarrett D'Amore if ((wideidx + 1) >= widesz) { 352*6b5e5868SGarrett D'Amore widesz += 64; 353*6b5e5868SGarrett D'Amore widestr = realloc(widestr, (widesz * sizeof (wchar_t))); 354*6b5e5868SGarrett D'Amore if (widestr == NULL) { 355*6b5e5868SGarrett D'Amore yyerror(_("out of memory")); 356*6b5e5868SGarrett D'Amore wideidx = 0; 357*6b5e5868SGarrett D'Amore widesz = 0; 358*6b5e5868SGarrett D'Amore return; 359*6b5e5868SGarrett D'Amore } 360*6b5e5868SGarrett D'Amore } 361*6b5e5868SGarrett D'Amore 362*6b5e5868SGarrett D'Amore widestr[wideidx++] = c; 363*6b5e5868SGarrett D'Amore widestr[wideidx] = 0; 364*6b5e5868SGarrett D'Amore } 365*6b5e5868SGarrett D'Amore 366*6b5e5868SGarrett D'Amore wchar_t * 367*6b5e5868SGarrett D'Amore get_wcs(void) 368*6b5e5868SGarrett D'Amore { 369*6b5e5868SGarrett D'Amore wchar_t *ws = widestr; 370*6b5e5868SGarrett D'Amore wideidx = 0; 371*6b5e5868SGarrett D'Amore widestr = NULL; 372*6b5e5868SGarrett D'Amore widesz = 0; 373*6b5e5868SGarrett D'Amore if (ws == NULL) { 374*6b5e5868SGarrett D'Amore if ((ws = wsdup(L"")) == NULL) { 375*6b5e5868SGarrett D'Amore yyerror(_("out of memory")); 376*6b5e5868SGarrett D'Amore } 377*6b5e5868SGarrett D'Amore } 378*6b5e5868SGarrett D'Amore return (ws); 379*6b5e5868SGarrett D'Amore } 380*6b5e5868SGarrett D'Amore 381*6b5e5868SGarrett D'Amore static int 382*6b5e5868SGarrett D'Amore get_byte(void) 383*6b5e5868SGarrett D'Amore { 384*6b5e5868SGarrett D'Amore int c; 385*6b5e5868SGarrett D'Amore 386*6b5e5868SGarrett D'Amore if ((c = scanc()) != esc_char) { 387*6b5e5868SGarrett D'Amore unscanc(c); 388*6b5e5868SGarrett D'Amore return (EOF); 389*6b5e5868SGarrett D'Amore } 390*6b5e5868SGarrett D'Amore c = scanc(); 391*6b5e5868SGarrett D'Amore 392*6b5e5868SGarrett D'Amore switch (c) { 393*6b5e5868SGarrett D'Amore case 'd': 394*6b5e5868SGarrett D'Amore case 'D': 395*6b5e5868SGarrett D'Amore return (scan_dec_byte()); 396*6b5e5868SGarrett D'Amore case 'x': 397*6b5e5868SGarrett D'Amore case 'X': 398*6b5e5868SGarrett D'Amore return (scan_hex_byte()); 399*6b5e5868SGarrett D'Amore case '0': 400*6b5e5868SGarrett D'Amore case '1': 401*6b5e5868SGarrett D'Amore case '2': 402*6b5e5868SGarrett D'Amore case '3': 403*6b5e5868SGarrett D'Amore case '4': 404*6b5e5868SGarrett D'Amore case '5': 405*6b5e5868SGarrett D'Amore case '6': 406*6b5e5868SGarrett D'Amore case '7': 407*6b5e5868SGarrett D'Amore /* put the character back so we can get it */ 408*6b5e5868SGarrett D'Amore unscanc(c); 409*6b5e5868SGarrett D'Amore return (scan_oct_byte()); 410*6b5e5868SGarrett D'Amore default: 411*6b5e5868SGarrett D'Amore unscanc(c); 412*6b5e5868SGarrett D'Amore unscanc(esc_char); 413*6b5e5868SGarrett D'Amore return (EOF); 414*6b5e5868SGarrett D'Amore } 415*6b5e5868SGarrett D'Amore } 416*6b5e5868SGarrett D'Amore 417*6b5e5868SGarrett D'Amore int 418*6b5e5868SGarrett D'Amore get_escaped(int c) 419*6b5e5868SGarrett D'Amore { 420*6b5e5868SGarrett D'Amore switch (c) { 421*6b5e5868SGarrett D'Amore case 'n': 422*6b5e5868SGarrett D'Amore return ('\n'); 423*6b5e5868SGarrett D'Amore case 'r': 424*6b5e5868SGarrett D'Amore return ('\r'); 425*6b5e5868SGarrett D'Amore case 't': 426*6b5e5868SGarrett D'Amore return ('\t'); 427*6b5e5868SGarrett D'Amore case 'f': 428*6b5e5868SGarrett D'Amore return ('\f'); 429*6b5e5868SGarrett D'Amore case 'v': 430*6b5e5868SGarrett D'Amore return ('\v'); 431*6b5e5868SGarrett D'Amore case 'b': 432*6b5e5868SGarrett D'Amore return ('\b'); 433*6b5e5868SGarrett D'Amore case 'a': 434*6b5e5868SGarrett D'Amore return ('\a'); 435*6b5e5868SGarrett D'Amore default: 436*6b5e5868SGarrett D'Amore return (c); 437*6b5e5868SGarrett D'Amore } 438*6b5e5868SGarrett D'Amore } 439*6b5e5868SGarrett D'Amore 440*6b5e5868SGarrett D'Amore int 441*6b5e5868SGarrett D'Amore get_wide(void) 442*6b5e5868SGarrett D'Amore { 443*6b5e5868SGarrett D'Amore static char mbs[MB_LEN_MAX + 1] = ""; 444*6b5e5868SGarrett D'Amore static int mbi = 0; 445*6b5e5868SGarrett D'Amore int c; 446*6b5e5868SGarrett D'Amore wchar_t wc; 447*6b5e5868SGarrett D'Amore 448*6b5e5868SGarrett D'Amore if (mb_cur_max >= sizeof (mbs)) { 449*6b5e5868SGarrett D'Amore yyerror(_("max multibyte character size too big")); 450*6b5e5868SGarrett D'Amore mbi = 0; 451*6b5e5868SGarrett D'Amore return (T_NULL); 452*6b5e5868SGarrett D'Amore } 453*6b5e5868SGarrett D'Amore for (;;) { 454*6b5e5868SGarrett D'Amore if ((mbi == mb_cur_max) || ((c = get_byte()) == EOF)) { 455*6b5e5868SGarrett D'Amore /* 456*6b5e5868SGarrett D'Amore * end of the byte sequence reached, but no 457*6b5e5868SGarrett D'Amore * valid wide decoding. fatal error. 458*6b5e5868SGarrett D'Amore */ 459*6b5e5868SGarrett D'Amore mbi = 0; 460*6b5e5868SGarrett D'Amore yyerror(_("not a valid character encoding")); 461*6b5e5868SGarrett D'Amore return (T_NULL); 462*6b5e5868SGarrett D'Amore } 463*6b5e5868SGarrett D'Amore mbs[mbi++] = c; 464*6b5e5868SGarrett D'Amore mbs[mbi] = 0; 465*6b5e5868SGarrett D'Amore 466*6b5e5868SGarrett D'Amore /* does it decode? */ 467*6b5e5868SGarrett D'Amore if (to_wide(&wc, mbs) >= 0) { 468*6b5e5868SGarrett D'Amore break; 469*6b5e5868SGarrett D'Amore } 470*6b5e5868SGarrett D'Amore } 471*6b5e5868SGarrett D'Amore 472*6b5e5868SGarrett D'Amore mbi = 0; 473*6b5e5868SGarrett D'Amore if (category != T_CHARMAP) { 474*6b5e5868SGarrett D'Amore if (check_charmap(wc) < 0) { 475*6b5e5868SGarrett D'Amore yyerror(_("no symbolic name for character")); 476*6b5e5868SGarrett D'Amore return (T_NULL); 477*6b5e5868SGarrett D'Amore } 478*6b5e5868SGarrett D'Amore } 479*6b5e5868SGarrett D'Amore 480*6b5e5868SGarrett D'Amore yylval.wc = wc; 481*6b5e5868SGarrett D'Amore return (T_CHAR); 482*6b5e5868SGarrett D'Amore } 483*6b5e5868SGarrett D'Amore 484*6b5e5868SGarrett D'Amore int 485*6b5e5868SGarrett D'Amore get_symbol(void) 486*6b5e5868SGarrett D'Amore { 487*6b5e5868SGarrett D'Amore int c; 488*6b5e5868SGarrett D'Amore 489*6b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) { 490*6b5e5868SGarrett D'Amore if (escaped) { 491*6b5e5868SGarrett D'Amore escaped = 0; 492*6b5e5868SGarrett D'Amore if (c == '\n') 493*6b5e5868SGarrett D'Amore continue; 494*6b5e5868SGarrett D'Amore add_tok(get_escaped(c)); 495*6b5e5868SGarrett D'Amore continue; 496*6b5e5868SGarrett D'Amore } 497*6b5e5868SGarrett D'Amore if (c == esc_char) { 498*6b5e5868SGarrett D'Amore escaped = 1; 499*6b5e5868SGarrett D'Amore continue; 500*6b5e5868SGarrett D'Amore } 501*6b5e5868SGarrett D'Amore if (c == '\n') { /* well that's strange! */ 502*6b5e5868SGarrett D'Amore yyerror(_("unterminated symbolic name")); 503*6b5e5868SGarrett D'Amore continue; 504*6b5e5868SGarrett D'Amore } 505*6b5e5868SGarrett D'Amore if (c == '>') { /* end of symbol */ 506*6b5e5868SGarrett D'Amore 507*6b5e5868SGarrett D'Amore /* 508*6b5e5868SGarrett D'Amore * This restarts the token from the beginning 509*6b5e5868SGarrett D'Amore * the next time we scan a character. (This 510*6b5e5868SGarrett D'Amore * token is complete.) 511*6b5e5868SGarrett D'Amore */ 512*6b5e5868SGarrett D'Amore 513*6b5e5868SGarrett D'Amore if (token == NULL) { 514*6b5e5868SGarrett D'Amore yyerror(_("missing symbolic name")); 515*6b5e5868SGarrett D'Amore return (T_NULL); 516*6b5e5868SGarrett D'Amore } 517*6b5e5868SGarrett D'Amore tokidx = 0; 518*6b5e5868SGarrett D'Amore 519*6b5e5868SGarrett D'Amore /* 520*6b5e5868SGarrett D'Amore * A few symbols are handled as keywords outside 521*6b5e5868SGarrett D'Amore * of the normal categories. 522*6b5e5868SGarrett D'Amore */ 523*6b5e5868SGarrett D'Amore if (category == T_END) { 524*6b5e5868SGarrett D'Amore int i; 525*6b5e5868SGarrett D'Amore for (i = 0; symwords[i].name != 0; i++) { 526*6b5e5868SGarrett D'Amore if (strcmp(token, symwords[i].name) == 527*6b5e5868SGarrett D'Amore 0) { 528*6b5e5868SGarrett D'Amore last_kw = symwords[i].id; 529*6b5e5868SGarrett D'Amore return (last_kw); 530*6b5e5868SGarrett D'Amore } 531*6b5e5868SGarrett D'Amore } 532*6b5e5868SGarrett D'Amore } 533*6b5e5868SGarrett D'Amore /* 534*6b5e5868SGarrett D'Amore * Contextual rule: Only literal characters are 535*6b5e5868SGarrett D'Amore * permitted in CHARMAP. Anywhere else the symbolic 536*6b5e5868SGarrett D'Amore * forms are fine. 537*6b5e5868SGarrett D'Amore */ 538*6b5e5868SGarrett D'Amore if ((category != T_CHARMAP) && 539*6b5e5868SGarrett D'Amore (lookup_charmap(token, &yylval.wc)) != -1) { 540*6b5e5868SGarrett D'Amore return (T_CHAR); 541*6b5e5868SGarrett D'Amore } 542*6b5e5868SGarrett D'Amore if ((yylval.collsym = lookup_collsym(token)) != NULL) { 543*6b5e5868SGarrett D'Amore return (T_COLLSYM); 544*6b5e5868SGarrett D'Amore } 545*6b5e5868SGarrett D'Amore if ((yylval.collelem = lookup_collelem(token)) != 546*6b5e5868SGarrett D'Amore NULL) { 547*6b5e5868SGarrett D'Amore return (T_COLLELEM); 548*6b5e5868SGarrett D'Amore } 549*6b5e5868SGarrett D'Amore /* its an undefined symbol */ 550*6b5e5868SGarrett D'Amore yylval.token = strdup(token); 551*6b5e5868SGarrett D'Amore token = NULL; 552*6b5e5868SGarrett D'Amore toksz = 0; 553*6b5e5868SGarrett D'Amore tokidx = 0; 554*6b5e5868SGarrett D'Amore return (T_SYMBOL); 555*6b5e5868SGarrett D'Amore } 556*6b5e5868SGarrett D'Amore add_tok(c); 557*6b5e5868SGarrett D'Amore } 558*6b5e5868SGarrett D'Amore 559*6b5e5868SGarrett D'Amore yyerror(_("unterminated symbolic name")); 560*6b5e5868SGarrett D'Amore return (EOF); 561*6b5e5868SGarrett D'Amore } 562*6b5e5868SGarrett D'Amore 563*6b5e5868SGarrett D'Amore int 564*6b5e5868SGarrett D'Amore get_category(void) 565*6b5e5868SGarrett D'Amore { 566*6b5e5868SGarrett D'Amore return (category); 567*6b5e5868SGarrett D'Amore } 568*6b5e5868SGarrett D'Amore 569*6b5e5868SGarrett D'Amore static int 570*6b5e5868SGarrett D'Amore consume_token(void) 571*6b5e5868SGarrett D'Amore { 572*6b5e5868SGarrett D'Amore int len = tokidx; 573*6b5e5868SGarrett D'Amore int i; 574*6b5e5868SGarrett D'Amore 575*6b5e5868SGarrett D'Amore tokidx = 0; 576*6b5e5868SGarrett D'Amore if (token == NULL) 577*6b5e5868SGarrett D'Amore return (T_NULL); 578*6b5e5868SGarrett D'Amore 579*6b5e5868SGarrett D'Amore /* 580*6b5e5868SGarrett D'Amore * this one is special, because we don't want it to alter the 581*6b5e5868SGarrett D'Amore * last_kw field. 582*6b5e5868SGarrett D'Amore */ 583*6b5e5868SGarrett D'Amore if (strcmp(token, "...") == 0) { 584*6b5e5868SGarrett D'Amore return (T_ELLIPSIS); 585*6b5e5868SGarrett D'Amore } 586*6b5e5868SGarrett D'Amore 587*6b5e5868SGarrett D'Amore /* search for reserved words first */ 588*6b5e5868SGarrett D'Amore for (i = 0; keywords[i].name; i++) { 589*6b5e5868SGarrett D'Amore int j; 590*6b5e5868SGarrett D'Amore if (strcmp(keywords[i].name, token) != 0) { 591*6b5e5868SGarrett D'Amore continue; 592*6b5e5868SGarrett D'Amore } 593*6b5e5868SGarrett D'Amore 594*6b5e5868SGarrett D'Amore last_kw = keywords[i].id; 595*6b5e5868SGarrett D'Amore 596*6b5e5868SGarrett D'Amore /* clear the top level category if we're done with it */ 597*6b5e5868SGarrett D'Amore if (last_kw == T_END) { 598*6b5e5868SGarrett D'Amore category = T_END; 599*6b5e5868SGarrett D'Amore } 600*6b5e5868SGarrett D'Amore 601*6b5e5868SGarrett D'Amore /* set the top level category if we're changing */ 602*6b5e5868SGarrett D'Amore for (j = 0; categories[j]; j++) { 603*6b5e5868SGarrett D'Amore if (categories[j] != last_kw) 604*6b5e5868SGarrett D'Amore continue; 605*6b5e5868SGarrett D'Amore category = last_kw; 606*6b5e5868SGarrett D'Amore } 607*6b5e5868SGarrett D'Amore 608*6b5e5868SGarrett D'Amore return (keywords[i].id); 609*6b5e5868SGarrett D'Amore } 610*6b5e5868SGarrett D'Amore 611*6b5e5868SGarrett D'Amore /* maybe its a numeric constant? */ 612*6b5e5868SGarrett D'Amore if (isdigit(*token) || (*token == '-' && isdigit(token[1]))) { 613*6b5e5868SGarrett D'Amore char *eptr; 614*6b5e5868SGarrett D'Amore yylval.num = strtol(token, &eptr, 10); 615*6b5e5868SGarrett D'Amore if (*eptr != 0) 616*6b5e5868SGarrett D'Amore yyerror(_("malformed number")); 617*6b5e5868SGarrett D'Amore return (T_NUMBER); 618*6b5e5868SGarrett D'Amore } 619*6b5e5868SGarrett D'Amore 620*6b5e5868SGarrett D'Amore /* 621*6b5e5868SGarrett D'Amore * A single lone character is treated as a character literal. 622*6b5e5868SGarrett D'Amore * To avoid duplication of effort, we stick in the charmap. 623*6b5e5868SGarrett D'Amore */ 624*6b5e5868SGarrett D'Amore if (len == 1) { 625*6b5e5868SGarrett D'Amore yylval.wc = token[0]; 626*6b5e5868SGarrett D'Amore return (T_CHAR); 627*6b5e5868SGarrett D'Amore } 628*6b5e5868SGarrett D'Amore 629*6b5e5868SGarrett D'Amore /* anything else is treated as a symbolic name */ 630*6b5e5868SGarrett D'Amore yylval.token = strdup(token); 631*6b5e5868SGarrett D'Amore token = NULL; 632*6b5e5868SGarrett D'Amore toksz = 0; 633*6b5e5868SGarrett D'Amore tokidx = 0; 634*6b5e5868SGarrett D'Amore return (T_NAME); 635*6b5e5868SGarrett D'Amore } 636*6b5e5868SGarrett D'Amore 637*6b5e5868SGarrett D'Amore void 638*6b5e5868SGarrett D'Amore scan_to_eol(void) 639*6b5e5868SGarrett D'Amore { 640*6b5e5868SGarrett D'Amore int c; 641*6b5e5868SGarrett D'Amore while ((c = scanc()) != '\n') { 642*6b5e5868SGarrett D'Amore if (c == EOF) { 643*6b5e5868SGarrett D'Amore /* end of file without newline! */ 644*6b5e5868SGarrett D'Amore errf(_("missing newline")); 645*6b5e5868SGarrett D'Amore return; 646*6b5e5868SGarrett D'Amore } 647*6b5e5868SGarrett D'Amore } 648*6b5e5868SGarrett D'Amore assert(c == '\n'); 649*6b5e5868SGarrett D'Amore } 650*6b5e5868SGarrett D'Amore 651*6b5e5868SGarrett D'Amore int 652*6b5e5868SGarrett D'Amore yylex(void) 653*6b5e5868SGarrett D'Amore { 654*6b5e5868SGarrett D'Amore int c; 655*6b5e5868SGarrett D'Amore 656*6b5e5868SGarrett D'Amore while ((c = scanc()) != EOF) { 657*6b5e5868SGarrett D'Amore 658*6b5e5868SGarrett D'Amore /* special handling for quoted string */ 659*6b5e5868SGarrett D'Amore if (instring) { 660*6b5e5868SGarrett D'Amore if (escaped) { 661*6b5e5868SGarrett D'Amore escaped = 0; 662*6b5e5868SGarrett D'Amore 663*6b5e5868SGarrett D'Amore /* if newline, just eat and forget it */ 664*6b5e5868SGarrett D'Amore if (c == '\n') 665*6b5e5868SGarrett D'Amore continue; 666*6b5e5868SGarrett D'Amore 667*6b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) { 668*6b5e5868SGarrett D'Amore unscanc(c); 669*6b5e5868SGarrett D'Amore unscanc(esc_char); 670*6b5e5868SGarrett D'Amore return (get_wide()); 671*6b5e5868SGarrett D'Amore } 672*6b5e5868SGarrett D'Amore yylval.wc = get_escaped(c); 673*6b5e5868SGarrett D'Amore return (T_CHAR); 674*6b5e5868SGarrett D'Amore } 675*6b5e5868SGarrett D'Amore if (c == esc_char) { 676*6b5e5868SGarrett D'Amore escaped = 1; 677*6b5e5868SGarrett D'Amore continue; 678*6b5e5868SGarrett D'Amore } 679*6b5e5868SGarrett D'Amore switch (c) { 680*6b5e5868SGarrett D'Amore case '<': 681*6b5e5868SGarrett D'Amore return (get_symbol()); 682*6b5e5868SGarrett D'Amore case '>': 683*6b5e5868SGarrett D'Amore /* oops! should generate syntax error */ 684*6b5e5868SGarrett D'Amore return (T_GT); 685*6b5e5868SGarrett D'Amore case '"': 686*6b5e5868SGarrett D'Amore instring = 0; 687*6b5e5868SGarrett D'Amore return (T_QUOTE); 688*6b5e5868SGarrett D'Amore default: 689*6b5e5868SGarrett D'Amore yylval.wc = c; 690*6b5e5868SGarrett D'Amore return (T_CHAR); 691*6b5e5868SGarrett D'Amore } 692*6b5e5868SGarrett D'Amore } 693*6b5e5868SGarrett D'Amore 694*6b5e5868SGarrett D'Amore /* escaped characters first */ 695*6b5e5868SGarrett D'Amore if (escaped) { 696*6b5e5868SGarrett D'Amore escaped = 0; 697*6b5e5868SGarrett D'Amore if (c == '\n') { 698*6b5e5868SGarrett D'Amore /* eat the newline */ 699*6b5e5868SGarrett D'Amore continue; 700*6b5e5868SGarrett D'Amore } 701*6b5e5868SGarrett D'Amore hadtok = 1; 702*6b5e5868SGarrett D'Amore if (tokidx) { 703*6b5e5868SGarrett D'Amore /* an escape mid-token is nonsense */ 704*6b5e5868SGarrett D'Amore return (T_NULL); 705*6b5e5868SGarrett D'Amore } 706*6b5e5868SGarrett D'Amore 707*6b5e5868SGarrett D'Amore /* numeric escapes are treated as wide characters */ 708*6b5e5868SGarrett D'Amore if (strchr("xXd01234567", c)) { 709*6b5e5868SGarrett D'Amore unscanc(c); 710*6b5e5868SGarrett D'Amore unscanc(esc_char); 711*6b5e5868SGarrett D'Amore return (get_wide()); 712*6b5e5868SGarrett D'Amore } 713*6b5e5868SGarrett D'Amore 714*6b5e5868SGarrett D'Amore add_tok(get_escaped(c)); 715*6b5e5868SGarrett D'Amore continue; 716*6b5e5868SGarrett D'Amore } 717*6b5e5868SGarrett D'Amore 718*6b5e5868SGarrett D'Amore /* if it is the escape charter itself note it */ 719*6b5e5868SGarrett D'Amore if (c == esc_char) { 720*6b5e5868SGarrett D'Amore escaped = 1; 721*6b5e5868SGarrett D'Amore continue; 722*6b5e5868SGarrett D'Amore } 723*6b5e5868SGarrett D'Amore 724*6b5e5868SGarrett D'Amore /* remove from the comment char to end of line */ 725*6b5e5868SGarrett D'Amore if (c == com_char) { 726*6b5e5868SGarrett D'Amore while (c != '\n') { 727*6b5e5868SGarrett D'Amore if ((c = scanc()) == EOF) { 728*6b5e5868SGarrett D'Amore /* end of file without newline! */ 729*6b5e5868SGarrett D'Amore return (EOF); 730*6b5e5868SGarrett D'Amore } 731*6b5e5868SGarrett D'Amore } 732*6b5e5868SGarrett D'Amore assert(c == '\n'); 733*6b5e5868SGarrett D'Amore if (!hadtok) { 734*6b5e5868SGarrett D'Amore /* 735*6b5e5868SGarrett D'Amore * If there were no tokens on this line, 736*6b5e5868SGarrett D'Amore * then just pretend it didn't exist at all. 737*6b5e5868SGarrett D'Amore */ 738*6b5e5868SGarrett D'Amore continue; 739*6b5e5868SGarrett D'Amore } 740*6b5e5868SGarrett D'Amore hadtok = 0; 741*6b5e5868SGarrett D'Amore return (T_NL); 742*6b5e5868SGarrett D'Amore } 743*6b5e5868SGarrett D'Amore 744*6b5e5868SGarrett D'Amore if (strchr(" \t\n;()<>,\"", c) && (tokidx != 0)) { 745*6b5e5868SGarrett D'Amore /* 746*6b5e5868SGarrett D'Amore * These are all token delimiters. If there 747*6b5e5868SGarrett D'Amore * is a token already in progress, we need to 748*6b5e5868SGarrett D'Amore * process it. 749*6b5e5868SGarrett D'Amore */ 750*6b5e5868SGarrett D'Amore unscanc(c); 751*6b5e5868SGarrett D'Amore return (consume_token()); 752*6b5e5868SGarrett D'Amore } 753*6b5e5868SGarrett D'Amore 754*6b5e5868SGarrett D'Amore switch (c) { 755*6b5e5868SGarrett D'Amore case '\n': 756*6b5e5868SGarrett D'Amore if (!hadtok) { 757*6b5e5868SGarrett D'Amore /* 758*6b5e5868SGarrett D'Amore * If the line was completely devoid of tokens, 759*6b5e5868SGarrett D'Amore * then just ignore it. 760*6b5e5868SGarrett D'Amore */ 761*6b5e5868SGarrett D'Amore continue; 762*6b5e5868SGarrett D'Amore } 763*6b5e5868SGarrett D'Amore /* we're starting a new line, reset the token state */ 764*6b5e5868SGarrett D'Amore hadtok = 0; 765*6b5e5868SGarrett D'Amore return (T_NL); 766*6b5e5868SGarrett D'Amore case ',': 767*6b5e5868SGarrett D'Amore hadtok = 1; 768*6b5e5868SGarrett D'Amore return (T_COMMA); 769*6b5e5868SGarrett D'Amore case ';': 770*6b5e5868SGarrett D'Amore hadtok = 1; 771*6b5e5868SGarrett D'Amore return (T_SEMI); 772*6b5e5868SGarrett D'Amore case '(': 773*6b5e5868SGarrett D'Amore hadtok = 1; 774*6b5e5868SGarrett D'Amore return (T_LPAREN); 775*6b5e5868SGarrett D'Amore case ')': 776*6b5e5868SGarrett D'Amore hadtok = 1; 777*6b5e5868SGarrett D'Amore return (T_RPAREN); 778*6b5e5868SGarrett D'Amore case '>': 779*6b5e5868SGarrett D'Amore hadtok = 1; 780*6b5e5868SGarrett D'Amore return (T_GT); 781*6b5e5868SGarrett D'Amore case '<': 782*6b5e5868SGarrett D'Amore /* symbol start! */ 783*6b5e5868SGarrett D'Amore hadtok = 1; 784*6b5e5868SGarrett D'Amore return (get_symbol()); 785*6b5e5868SGarrett D'Amore case ' ': 786*6b5e5868SGarrett D'Amore case '\t': 787*6b5e5868SGarrett D'Amore /* whitespace, just ignore it */ 788*6b5e5868SGarrett D'Amore continue; 789*6b5e5868SGarrett D'Amore case '"': 790*6b5e5868SGarrett D'Amore hadtok = 1; 791*6b5e5868SGarrett D'Amore instring = 1; 792*6b5e5868SGarrett D'Amore return (T_QUOTE); 793*6b5e5868SGarrett D'Amore default: 794*6b5e5868SGarrett D'Amore hadtok = 1; 795*6b5e5868SGarrett D'Amore add_tok(c); 796*6b5e5868SGarrett D'Amore continue; 797*6b5e5868SGarrett D'Amore } 798*6b5e5868SGarrett D'Amore } 799*6b5e5868SGarrett D'Amore return (EOF); 800*6b5e5868SGarrett D'Amore } 801*6b5e5868SGarrett D'Amore 802*6b5e5868SGarrett D'Amore void 803*6b5e5868SGarrett D'Amore yyerror(const char *msg) 804*6b5e5868SGarrett D'Amore { 805*6b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"), 806*6b5e5868SGarrett D'Amore filename, lineno, msg); 807*6b5e5868SGarrett D'Amore exit(4); 808*6b5e5868SGarrett D'Amore } 809*6b5e5868SGarrett D'Amore 810*6b5e5868SGarrett D'Amore void 811*6b5e5868SGarrett D'Amore errf(const char *fmt, ...) 812*6b5e5868SGarrett D'Amore { 813*6b5e5868SGarrett D'Amore char *msg; 814*6b5e5868SGarrett D'Amore 815*6b5e5868SGarrett D'Amore va_list va; 816*6b5e5868SGarrett D'Amore va_start(va, fmt); 817*6b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va); 818*6b5e5868SGarrett D'Amore va_end(va); 819*6b5e5868SGarrett D'Amore 820*6b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: error: %s\n"), 821*6b5e5868SGarrett D'Amore filename, lineno, msg); 822*6b5e5868SGarrett D'Amore free(msg); 823*6b5e5868SGarrett D'Amore exit(4); 824*6b5e5868SGarrett D'Amore } 825*6b5e5868SGarrett D'Amore 826*6b5e5868SGarrett D'Amore void 827*6b5e5868SGarrett D'Amore warn(const char *fmt, ...) 828*6b5e5868SGarrett D'Amore { 829*6b5e5868SGarrett D'Amore char *msg; 830*6b5e5868SGarrett D'Amore 831*6b5e5868SGarrett D'Amore va_list va; 832*6b5e5868SGarrett D'Amore va_start(va, fmt); 833*6b5e5868SGarrett D'Amore (void) vasprintf(&msg, fmt, va); 834*6b5e5868SGarrett D'Amore va_end(va); 835*6b5e5868SGarrett D'Amore 836*6b5e5868SGarrett D'Amore (void) fprintf(stderr, _("%s: %d: warning: %s\n"), 837*6b5e5868SGarrett D'Amore filename, lineno, msg); 838*6b5e5868SGarrett D'Amore free(msg); 839*6b5e5868SGarrett D'Amore warnings++; 840*6b5e5868SGarrett D'Amore if (!warnok) 841*6b5e5868SGarrett D'Amore exit(4); 842*6b5e5868SGarrett D'Amore } 843