1 %{ 2 /* 3 * CDDL HEADER START 4 * 5 * The contents of this file are subject to the terms of the 6 * Common Development and Distribution License, Version 1.0 only 7 * (the "License"). You may not use this file except in compliance 8 * with the License. 9 * 10 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11 * or http://www.opensolaris.org/os/licensing. 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 * 23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 #pragma error_messages(off, E_STATEMENT_NOT_REACHED) 29 30 /* 31 * poolcfg.l 32 * 33 * Overview 34 * poolcfg.l implements a lexer for the poolcfg(1) utility.The lexer uses 35 * the token definitions generated by YACC in the file poolcfg_Grammar.h. 36 * To make token recognition simpler, the lexer uses a separate state for 37 * each of the different data types supported by poolcfg(1). 38 * 39 * States 40 * Lex provides the ability to minimise conflict between qualifying regexps 41 * by providing states. A regexp that is qualified by a state will only be 42 * used when the state is entered (using the BEGIN <state> command). (The 43 * exception to this rule, is that rules defined in the default state are 44 * available in all states.) 45 * 46 * poolcfg.l makes use of type states, one for each of the poolcfg(1) 47 * supported data types: 48 * 49 * ISTATE => int64_t 50 * USTATE => uint64_t 51 * BSTATE => uchar_t 52 * SSTATE => const char * 53 * DSTATE => double 54 * 55 * and a further state, CPUSTATE, to indicate the difference between matching 56 * a valid "name" (i.e. id) for a cpu and a valid name for other components of 57 * libpool. 58 * 59 * When a token indicating a variable declaration is matched, the corresponding 60 * state is saved in the state variable. Once the assignment ('=') token is 61 * matched, the stored state is entered and the additional state specific 62 * matching regular expressions become available. Once a state specific 63 * token is matched, the default state is restored. 64 * 65 */ 66 #include <stdlib.h> 67 #include <sys/types.h> 68 #include <assert.h> 69 #include <string.h> 70 #include <errno.h> 71 #include <libintl.h> 72 73 #include <pool.h> 74 #include "utils.h" 75 #include "poolcfg.h" 76 #include "poolcfg_grammar.h" 77 78 static int lex_lineno = 1; /* line-number for error reporting */ 79 static int state = INITIAL; /* state to be used */ 80 extern void yyerror(char *s); 81 extern int dofile; /* are we processing a file? */ 82 %} 83 84 %s ISTATE 85 %s USTATE 86 %s BSTATE 87 %s SSTATE 88 %s DSTATE 89 %s CPUSTATE 90 91 %% 92 93 \n lex_lineno++; 94 95 [ \t]+ ; 96 97 #.* ; 98 99 info { return PCC_INFO; } 100 101 create { return PCC_CREATE; } 102 103 destroy { return PCC_DESTROY; } 104 105 modify { return PCC_MODIFY; } 106 107 associate { return PCC_ASSOC; } 108 109 transfer { 110 BEGIN USTATE; 111 return PCC_TRANSFER; 112 } 113 114 discover { return PCC_DISC; } 115 116 rename { return PCC_RENAME; } 117 118 to { return PCK_TO; } 119 120 from { return PCK_FROM; } 121 122 int { 123 state=ISTATE; 124 return PCT_INT; 125 } 126 127 uint { 128 state=USTATE; 129 return PCT_UINT; 130 } 131 132 boolean { 133 state=BSTATE; 134 return PCT_BOOLEAN; 135 } 136 137 string { 138 state=SSTATE; 139 return PCT_STRING; 140 } 141 142 float { 143 state=DSTATE; 144 return PCT_FLOAT; 145 } 146 147 cpu { 148 BEGIN CPUSTATE; 149 return PCE_CPU; 150 } 151 152 pset { return PCE_PSET; } 153 154 pool { return PCE_POOL; } 155 156 system { return PCE_SYSTEM; } 157 158 \( { return PCK_OPENLST; } 159 160 \) { return PCK_CLOSELST; } 161 162 = { 163 BEGIN state; 164 return PCK_ASSIGN; 165 } 166 167 \; { return PCK_SEPLST; } 168 169 ~ { return PCK_UNDEF; } 170 171 <ISTATE>-?[0-9]+ { 172 yylval.ival = strtoll(yytext, NULL, 0); 173 if (errno == EINVAL || errno == ERANGE) { 174 yyerror(gettext("Invalid value")); 175 exit(E_ERROR); 176 } 177 BEGIN INITIAL; 178 return PCV_VAL_INT; 179 } 180 181 <USTATE>[0-9]+ { 182 yylval.uval = strtoull(yytext, NULL, 0); 183 if (errno == EINVAL || errno == ERANGE) { 184 yyerror(gettext("Invalid value")); 185 exit(E_ERROR); 186 } 187 BEGIN INITIAL; 188 return PCV_VAL_UINT; 189 } 190 191 192 <BSTATE>true|false { 193 if (strcmp(yytext, "true") == 0) 194 yylval.bval = 1; 195 else 196 yylval.bval = 0; 197 BEGIN INITIAL; 198 return PCV_VAL_BOOLEAN; 199 } 200 201 <SSTATE>\"[^\"\n]*[\"\n] { 202 if((yylval.sval = strdup(yytext+1)) == NULL) { 203 yyerror(gettext("Out of memory")); 204 exit(E_ERROR); 205 } 206 if (yylval.sval[yyleng-2] =='"') 207 yylval.sval[yyleng-2] = 0; 208 BEGIN INITIAL; 209 return PCV_VAL_STRING; 210 } 211 212 <DSTATE>([0-9]+|([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) { 213 yylval.dval = strtod(yytext, (char **)NULL); 214 if (errno == EINVAL || errno == ERANGE) { 215 yyerror(gettext("Invalid value")); 216 exit(E_ERROR); 217 } 218 BEGIN INITIAL; 219 return PCV_VAL_FLOAT; 220 } 221 222 [A-Za-z][A-Za-z0-9,._-]* { 223 if ((yylval.sval = strdup(yytext)) == NULL) { 224 yyerror(gettext("Out of memory")); 225 exit(E_ERROR); 226 } 227 return PCV_SYMBOL; 228 } 229 230 <CPUSTATE>[0-9]+ { 231 if ((yylval.sval = strdup(yytext)) == NULL) { 232 yyerror(gettext("Out of memory")); 233 exit(E_ERROR); 234 } 235 BEGIN INITIAL; 236 return PCV_SYMBOL; 237 } 238 . { 239 yyerror(gettext("Illegal character")); 240 exit(E_ERROR); 241 } 242 243 %% 244 245 void 246 yyerror(char *s) 247 { 248 if (dofile == PO_TRUE) { 249 if (yytext[0] == '\0') { 250 (void) warn(gettext("line %d, %s, token expected\n"), 251 lex_lineno, s); 252 return; 253 } 254 (void) warn(gettext("line %d, %s at '%s'\n"), lex_lineno, s, 255 yytext); 256 } else { 257 if (yytext[0] == '\0') { 258 (void) warn(gettext("%s, token expected\n"), s); 259 return; 260 } 261 (void) warn(gettext("%s at '%s'\n"), s, yytext); 262 } 263 } 264 265