1 %option nostdinit noyywrap never-interactive full ecs 2 %option 8bit nodefault perf-report perf-report 3 %option noinput 4 %x COMMAND HELP STRING PARAM 5 %{ 6 /* 7 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 8 * Released under the terms of the GNU GPL v2.0. 9 */ 10 11 #include <limits.h> 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 17 #include "lkc.h" 18 19 #define START_STRSIZE 16 20 21 static struct { 22 struct file *file; 23 int lineno; 24 } current_pos; 25 26 static char *text; 27 static int text_size, text_asize; 28 29 struct buffer { 30 struct buffer *parent; 31 YY_BUFFER_STATE state; 32 }; 33 34 struct buffer *current_buf; 35 36 static int last_ts, first_ts; 37 38 static void zconf_endhelp(void); 39 static void zconf_endfile(void); 40 41 static void new_string(void) 42 { 43 text = xmalloc(START_STRSIZE); 44 text_asize = START_STRSIZE; 45 text_size = 0; 46 *text = 0; 47 } 48 49 static void append_string(const char *str, int size) 50 { 51 int new_size = text_size + size + 1; 52 if (new_size > text_asize) { 53 new_size += START_STRSIZE - 1; 54 new_size &= -START_STRSIZE; 55 text = realloc(text, new_size); 56 text_asize = new_size; 57 } 58 memcpy(text + text_size, str, size); 59 text_size += size; 60 text[text_size] = 0; 61 } 62 63 static void alloc_string(const char *str, int size) 64 { 65 text = xmalloc(size + 1); 66 memcpy(text, str, size); 67 text[size] = 0; 68 } 69 70 static void warn_ignored_character(char chr) 71 { 72 fprintf(stderr, 73 "%s:%d:warning: ignoring unsupported character '%c'\n", 74 zconf_curname(), zconf_lineno(), chr); 75 } 76 %} 77 78 n [A-Za-z0-9_-] 79 80 %% 81 int str = 0; 82 int ts, i; 83 84 [ \t]*#.*\n | 85 [ \t]*\n { 86 current_file->lineno++; 87 return T_EOL; 88 } 89 [ \t]*#.* 90 91 92 [ \t]+ { 93 BEGIN(COMMAND); 94 } 95 96 . { 97 unput(yytext[0]); 98 BEGIN(COMMAND); 99 } 100 101 102 <COMMAND>{ 103 {n}+ { 104 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 105 BEGIN(PARAM); 106 current_pos.file = current_file; 107 current_pos.lineno = current_file->lineno; 108 if (id && id->flags & TF_COMMAND) { 109 zconflval.id = id; 110 return id->token; 111 } 112 alloc_string(yytext, yyleng); 113 zconflval.string = text; 114 return T_WORD; 115 } 116 . warn_ignored_character(*yytext); 117 \n { 118 BEGIN(INITIAL); 119 current_file->lineno++; 120 return T_EOL; 121 } 122 } 123 124 <PARAM>{ 125 "&&" return T_AND; 126 "||" return T_OR; 127 "(" return T_OPEN_PAREN; 128 ")" return T_CLOSE_PAREN; 129 "!" return T_NOT; 130 "=" return T_EQUAL; 131 "!=" return T_UNEQUAL; 132 "<=" return T_LESS_EQUAL; 133 ">=" return T_GREATER_EQUAL; 134 "<" return T_LESS; 135 ">" return T_GREATER; 136 \"|\' { 137 str = yytext[0]; 138 new_string(); 139 BEGIN(STRING); 140 } 141 \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; 142 ({n}|[/.])+ { 143 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 144 if (id && id->flags & TF_PARAM) { 145 zconflval.id = id; 146 return id->token; 147 } 148 alloc_string(yytext, yyleng); 149 zconflval.string = text; 150 return T_WORD; 151 } 152 #.* /* comment */ 153 \\\n current_file->lineno++; 154 [[:blank:]]+ 155 . warn_ignored_character(*yytext); 156 <<EOF>> { 157 BEGIN(INITIAL); 158 } 159 } 160 161 <STRING>{ 162 [^'"\\\n]+/\n { 163 append_string(yytext, yyleng); 164 zconflval.string = text; 165 return T_WORD_QUOTE; 166 } 167 [^'"\\\n]+ { 168 append_string(yytext, yyleng); 169 } 170 \\.?/\n { 171 append_string(yytext + 1, yyleng - 1); 172 zconflval.string = text; 173 return T_WORD_QUOTE; 174 } 175 \\.? { 176 append_string(yytext + 1, yyleng - 1); 177 } 178 \'|\" { 179 if (str == yytext[0]) { 180 BEGIN(PARAM); 181 zconflval.string = text; 182 return T_WORD_QUOTE; 183 } else 184 append_string(yytext, 1); 185 } 186 \n { 187 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); 188 current_file->lineno++; 189 BEGIN(INITIAL); 190 return T_EOL; 191 } 192 <<EOF>> { 193 BEGIN(INITIAL); 194 } 195 } 196 197 <HELP>{ 198 [ \t]+ { 199 ts = 0; 200 for (i = 0; i < yyleng; i++) { 201 if (yytext[i] == '\t') 202 ts = (ts & ~7) + 8; 203 else 204 ts++; 205 } 206 last_ts = ts; 207 if (first_ts) { 208 if (ts < first_ts) { 209 zconf_endhelp(); 210 return T_HELPTEXT; 211 } 212 ts -= first_ts; 213 while (ts > 8) { 214 append_string(" ", 8); 215 ts -= 8; 216 } 217 append_string(" ", ts); 218 } 219 } 220 [ \t]*\n/[^ \t\n] { 221 current_file->lineno++; 222 zconf_endhelp(); 223 return T_HELPTEXT; 224 } 225 [ \t]*\n { 226 current_file->lineno++; 227 append_string("\n", 1); 228 } 229 [^ \t\n].* { 230 while (yyleng) { 231 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) 232 break; 233 yyleng--; 234 } 235 append_string(yytext, yyleng); 236 if (!first_ts) 237 first_ts = last_ts; 238 } 239 <<EOF>> { 240 zconf_endhelp(); 241 return T_HELPTEXT; 242 } 243 } 244 245 <<EOF>> { 246 if (current_file) { 247 zconf_endfile(); 248 return T_EOL; 249 } 250 fclose(yyin); 251 yyterminate(); 252 } 253 254 %% 255 void zconf_starthelp(void) 256 { 257 new_string(); 258 last_ts = first_ts = 0; 259 BEGIN(HELP); 260 } 261 262 static void zconf_endhelp(void) 263 { 264 zconflval.string = text; 265 BEGIN(INITIAL); 266 } 267 268 269 /* 270 * Try to open specified file with following names: 271 * ./name 272 * $(srctree)/name 273 * The latter is used when srctree is separate from objtree 274 * when compiling the kernel. 275 * Return NULL if file is not found. 276 */ 277 FILE *zconf_fopen(const char *name) 278 { 279 char *env, fullname[PATH_MAX+1]; 280 FILE *f; 281 282 f = fopen(name, "r"); 283 if (!f && name != NULL && name[0] != '/') { 284 env = getenv(SRCTREE); 285 if (env) { 286 sprintf(fullname, "%s/%s", env, name); 287 f = fopen(fullname, "r"); 288 } 289 } 290 return f; 291 } 292 293 void zconf_initscan(const char *name) 294 { 295 yyin = zconf_fopen(name); 296 if (!yyin) { 297 printf("can't find file %s\n", name); 298 exit(1); 299 } 300 301 current_buf = xmalloc(sizeof(*current_buf)); 302 memset(current_buf, 0, sizeof(*current_buf)); 303 304 current_file = file_lookup(name); 305 current_file->lineno = 1; 306 } 307 308 void zconf_nextfile(const char *name) 309 { 310 struct file *iter; 311 struct file *file = file_lookup(name); 312 struct buffer *buf = xmalloc(sizeof(*buf)); 313 memset(buf, 0, sizeof(*buf)); 314 315 current_buf->state = YY_CURRENT_BUFFER; 316 yyin = zconf_fopen(file->name); 317 if (!yyin) { 318 printf("%s:%d: can't open file \"%s\"\n", 319 zconf_curname(), zconf_lineno(), file->name); 320 exit(1); 321 } 322 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 323 buf->parent = current_buf; 324 current_buf = buf; 325 326 for (iter = current_file->parent; iter; iter = iter->parent ) { 327 if (!strcmp(current_file->name,iter->name) ) { 328 printf("%s:%d: recursive inclusion detected. " 329 "Inclusion path:\n current file : '%s'\n", 330 zconf_curname(), zconf_lineno(), 331 zconf_curname()); 332 iter = current_file->parent; 333 while (iter && \ 334 strcmp(iter->name,current_file->name)) { 335 printf(" included from: '%s:%d'\n", 336 iter->name, iter->lineno-1); 337 iter = iter->parent; 338 } 339 if (iter) 340 printf(" included from: '%s:%d'\n", 341 iter->name, iter->lineno+1); 342 exit(1); 343 } 344 } 345 file->lineno = 1; 346 file->parent = current_file; 347 current_file = file; 348 } 349 350 static void zconf_endfile(void) 351 { 352 struct buffer *parent; 353 354 current_file = current_file->parent; 355 356 parent = current_buf->parent; 357 if (parent) { 358 fclose(yyin); 359 yy_delete_buffer(YY_CURRENT_BUFFER); 360 yy_switch_to_buffer(parent->state); 361 } 362 free(current_buf); 363 current_buf = parent; 364 } 365 366 int zconf_lineno(void) 367 { 368 return current_pos.lineno; 369 } 370 371 const char *zconf_curname(void) 372 { 373 return current_pos.file ? current_pos.file->name : "<none>"; 374 } 375