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