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