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#include <glob.h> 17#include <libgen.h> 18 19#include "lkc.h" 20 21#define START_STRSIZE 16 22 23static struct { 24 struct file *file; 25 int lineno; 26} current_pos; 27 28static char *text; 29static int text_size, text_asize; 30 31struct buffer { 32 struct buffer *parent; 33 YY_BUFFER_STATE state; 34}; 35 36struct buffer *current_buf; 37 38static int last_ts, first_ts; 39 40static void zconf_endhelp(void); 41static void zconf_endfile(void); 42 43static void new_string(void) 44{ 45 text = xmalloc(START_STRSIZE); 46 text_asize = START_STRSIZE; 47 text_size = 0; 48 *text = 0; 49} 50 51static void append_string(const char *str, int size) 52{ 53 int new_size = text_size + size + 1; 54 if (new_size > text_asize) { 55 new_size += START_STRSIZE - 1; 56 new_size &= -START_STRSIZE; 57 text = realloc(text, new_size); 58 text_asize = new_size; 59 } 60 memcpy(text + text_size, str, size); 61 text_size += size; 62 text[text_size] = 0; 63} 64 65static void alloc_string(const char *str, int size) 66{ 67 text = xmalloc(size + 1); 68 memcpy(text, str, size); 69 text[size] = 0; 70} 71%} 72 73n [A-Za-z0-9_] 74 75%% 76 int str = 0; 77 int ts, i; 78 79[ \t]*#.*\n | 80[ \t]*\n { 81 current_file->lineno++; 82 return T_EOL; 83} 84[ \t]*#.* 85 86 87[ \t]+ { 88 BEGIN(COMMAND); 89} 90 91. { 92 unput(yytext[0]); 93 BEGIN(COMMAND); 94} 95 96 97<COMMAND>{ 98 {n}+ { 99 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 100 BEGIN(PARAM); 101 current_pos.file = current_file; 102 current_pos.lineno = current_file->lineno; 103 if (id && id->flags & TF_COMMAND) { 104 zconflval.id = id; 105 return id->token; 106 } 107 alloc_string(yytext, yyleng); 108 zconflval.string = text; 109 return T_WORD; 110 } 111 . 112 \n { 113 BEGIN(INITIAL); 114 current_file->lineno++; 115 return T_EOL; 116 } 117} 118 119<PARAM>{ 120 "&&" return T_AND; 121 "||" return T_OR; 122 "(" return T_OPEN_PAREN; 123 ")" return T_CLOSE_PAREN; 124 "!" return T_NOT; 125 "=" return T_EQUAL; 126 "!=" return T_UNEQUAL; 127 \"|\' { 128 str = yytext[0]; 129 new_string(); 130 BEGIN(STRING); 131 } 132 \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; 133 --- /* ignore */ 134 ({n}|[-/.])+ { 135 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 136 if (id && id->flags & TF_PARAM) { 137 zconflval.id = id; 138 return id->token; 139 } 140 alloc_string(yytext, yyleng); 141 zconflval.string = text; 142 return T_WORD; 143 } 144 #.* /* comment */ 145 \\\n current_file->lineno++; 146 . 147 <<EOF>> { 148 BEGIN(INITIAL); 149 } 150} 151 152<STRING>{ 153 [^'"\\\n]+/\n { 154 append_string(yytext, yyleng); 155 zconflval.string = text; 156 return T_WORD_QUOTE; 157 } 158 [^'"\\\n]+ { 159 append_string(yytext, yyleng); 160 } 161 \\.?/\n { 162 append_string(yytext + 1, yyleng - 1); 163 zconflval.string = text; 164 return T_WORD_QUOTE; 165 } 166 \\.? { 167 append_string(yytext + 1, yyleng - 1); 168 } 169 \'|\" { 170 if (str == yytext[0]) { 171 BEGIN(PARAM); 172 zconflval.string = text; 173 return T_WORD_QUOTE; 174 } else 175 append_string(yytext, 1); 176 } 177 \n { 178 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); 179 current_file->lineno++; 180 BEGIN(INITIAL); 181 return T_EOL; 182 } 183 <<EOF>> { 184 BEGIN(INITIAL); 185 } 186} 187 188<HELP>{ 189 [ \t]+ { 190 ts = 0; 191 for (i = 0; i < yyleng; i++) { 192 if (yytext[i] == '\t') 193 ts = (ts & ~7) + 8; 194 else 195 ts++; 196 } 197 last_ts = ts; 198 if (first_ts) { 199 if (ts < first_ts) { 200 zconf_endhelp(); 201 return T_HELPTEXT; 202 } 203 ts -= first_ts; 204 while (ts > 8) { 205 append_string(" ", 8); 206 ts -= 8; 207 } 208 append_string(" ", ts); 209 } 210 } 211 [ \t]*\n/[^ \t\n] { 212 current_file->lineno++; 213 zconf_endhelp(); 214 return T_HELPTEXT; 215 } 216 [ \t]*\n { 217 current_file->lineno++; 218 append_string("\n", 1); 219 } 220 [^ \t\n].* { 221 while (yyleng) { 222 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) 223 break; 224 yyleng--; 225 } 226 append_string(yytext, yyleng); 227 if (!first_ts) 228 first_ts = last_ts; 229 } 230 <<EOF>> { 231 zconf_endhelp(); 232 return T_HELPTEXT; 233 } 234} 235 236<<EOF>> { 237 if (current_file) { 238 zconf_endfile(); 239 return T_EOL; 240 } 241 fclose(yyin); 242 yyterminate(); 243} 244 245%% 246void zconf_starthelp(void) 247{ 248 new_string(); 249 last_ts = first_ts = 0; 250 BEGIN(HELP); 251} 252 253static void zconf_endhelp(void) 254{ 255 zconflval.string = text; 256 BEGIN(INITIAL); 257} 258 259 260/* 261 * Try to open specified file with following names: 262 * ./name 263 * $(srctree)/name 264 * The latter is used when srctree is separate from objtree 265 * when compiling the kernel. 266 * Return NULL if file is not found. 267 */ 268FILE *zconf_fopen(const char *name) 269{ 270 char *env, fullname[PATH_MAX+1]; 271 FILE *f; 272 273 f = fopen(name, "r"); 274 if (!f && name != NULL && name[0] != '/') { 275 env = getenv(SRCTREE); 276 if (env) { 277 sprintf(fullname, "%s/%s", env, name); 278 f = fopen(fullname, "r"); 279 } 280 } 281 return f; 282} 283 284void zconf_initscan(const char *name) 285{ 286 yyin = zconf_fopen(name); 287 if (!yyin) { 288 printf("can't find file %s\n", name); 289 exit(1); 290 } 291 292 current_buf = xmalloc(sizeof(*current_buf)); 293 memset(current_buf, 0, sizeof(*current_buf)); 294 295 current_file = file_lookup(name); 296 current_file->lineno = 1; 297} 298 299static void __zconf_nextfile(const char *name) 300{ 301 struct file *iter; 302 struct file *file = file_lookup(name); 303 struct buffer *buf = xmalloc(sizeof(*buf)); 304 memset(buf, 0, sizeof(*buf)); 305 306 current_buf->state = YY_CURRENT_BUFFER; 307 yyin = zconf_fopen(file->name); 308 if (!yyin) { 309 printf("%s:%d: can't open file \"%s\"\n", 310 zconf_curname(), zconf_lineno(), file->name); 311 exit(1); 312 } 313 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 314 buf->parent = current_buf; 315 current_buf = buf; 316 317 for (iter = current_file->parent; iter; iter = iter->parent ) { 318 if (!strcmp(current_file->name,iter->name) ) { 319 printf("%s:%d: recursive inclusion detected. " 320 "Inclusion path:\n current file : '%s'\n", 321 zconf_curname(), zconf_lineno(), 322 zconf_curname()); 323 iter = current_file->parent; 324 while (iter && \ 325 strcmp(iter->name,current_file->name)) { 326 printf(" included from: '%s:%d'\n", 327 iter->name, iter->lineno-1); 328 iter = iter->parent; 329 } 330 if (iter) 331 printf(" included from: '%s:%d'\n", 332 iter->name, iter->lineno+1); 333 exit(1); 334 } 335 } 336 file->lineno = 1; 337 file->parent = current_file; 338 current_file = file; 339} 340 341void zconf_nextfile(const char *name) 342{ 343 glob_t gl; 344 int err; 345 int i; 346 char path[PATH_MAX], *p; 347 348 err = glob(name, GLOB_ERR | GLOB_MARK, NULL, &gl); 349 350 /* ignore wildcard patterns that return no result */ 351 if (err == GLOB_NOMATCH && strchr(name, '*')) { 352 err = 0; 353 gl.gl_pathc = 0; 354 } 355 356 if (err == GLOB_NOMATCH) { 357 p = strdup(current_file->name); 358 if (p) { 359 snprintf(path, sizeof(path), "%s/%s", dirname(p), name); 360 err = glob(path, GLOB_ERR | GLOB_MARK, NULL, &gl); 361 free(p); 362 } 363 } 364 365 if (err) { 366 const char *reason = "unknown error"; 367 368 switch (err) { 369 case GLOB_NOSPACE: 370 reason = "out of memory"; 371 break; 372 case GLOB_ABORTED: 373 reason = "read error"; 374 break; 375 case GLOB_NOMATCH: 376 reason = "No files found"; 377 break; 378 default: 379 break; 380 } 381 382 printf("%s:%d: glob failed: %s \"%s\"\n", zconf_curname(), zconf_lineno(), 383 reason, name); 384 385 exit(1); 386 } 387 388 for (i = 0; i < gl.gl_pathc; i++) 389 __zconf_nextfile(gl.gl_pathv[i]); 390} 391 392static void zconf_endfile(void) 393{ 394 struct buffer *parent; 395 396 current_file = current_file->parent; 397 398 parent = current_buf->parent; 399 if (parent) { 400 fclose(yyin); 401 yy_delete_buffer(YY_CURRENT_BUFFER); 402 yy_switch_to_buffer(parent->state); 403 } 404 free(current_buf); 405 current_buf = parent; 406} 407 408int zconf_lineno(void) 409{ 410 return current_pos.lineno; 411} 412 413const char *zconf_curname(void) 414{ 415 return current_pos.file ? current_pos.file->name : "<none>"; 416} 417