1%option nostdinit noyywrap never-interactive full ecs 2%option 8bit nodefault yylineno 3%x COMMAND HELP STRING PARAM ASSIGN_VAL 4%{ 5/* 6 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 7 * Released under the terms of the GNU GPL v2.0. 8 */ 9 10#include <assert.h> 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 21static struct { 22 struct file *file; 23 int lineno; 24} current_pos; 25 26static char *text; 27static int text_size, text_asize; 28 29struct buffer { 30 struct buffer *parent; 31 YY_BUFFER_STATE state; 32}; 33 34struct buffer *current_buf; 35 36static int last_ts, first_ts; 37 38static char *expand_token(const char *in, size_t n); 39static void append_expanded_string(const char *in); 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 = xrealloc(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 72static void warn_ignored_character(char chr) 73{ 74 fprintf(stderr, 75 "%s:%d:warning: ignoring unsupported character '%c'\n", 76 zconf_curname(), zconf_lineno(), chr); 77} 78%} 79 80n [A-Za-z0-9_-] 81 82%% 83 int str = 0; 84 int ts, i; 85 86[ \t]*#.*\n | 87[ \t]*\n { 88 return T_EOL; 89} 90[ \t]*#.* 91 92 93[ \t]+ { 94 BEGIN(COMMAND); 95} 96 97. { 98 unput(yytext[0]); 99 BEGIN(COMMAND); 100} 101 102 103<COMMAND>{ 104 {n}+ { 105 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 106 current_pos.file = current_file; 107 current_pos.lineno = yylineno; 108 if (id && id->flags & TF_COMMAND) { 109 BEGIN(PARAM); 110 yylval.id = id; 111 return id->token; 112 } 113 alloc_string(yytext, yyleng); 114 yylval.string = text; 115 return T_VARIABLE; 116 } 117 ({n}|$)+ { 118 /* this token includes at least one '$' */ 119 yylval.string = expand_token(yytext, yyleng); 120 if (strlen(yylval.string)) 121 return T_VARIABLE; 122 free(yylval.string); 123 } 124 "=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_RECURSIVE; return T_ASSIGN; } 125 ":=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_SIMPLE; return T_ASSIGN; } 126 "+=" { BEGIN(ASSIGN_VAL); yylval.flavor = VAR_APPEND; return T_ASSIGN; } 127 [[:blank:]]+ 128 . warn_ignored_character(*yytext); 129 \n { 130 BEGIN(INITIAL); 131 return T_EOL; 132 } 133} 134 135<ASSIGN_VAL>{ 136 [^[:blank:]\n]+.* { 137 alloc_string(yytext, yyleng); 138 yylval.string = text; 139 return T_ASSIGN_VAL; 140 } 141 \n { BEGIN(INITIAL); return T_EOL; } 142 . 143} 144 145<PARAM>{ 146 "&&" return T_AND; 147 "||" return T_OR; 148 "(" return T_OPEN_PAREN; 149 ")" return T_CLOSE_PAREN; 150 "!" return T_NOT; 151 "=" return T_EQUAL; 152 "!=" return T_UNEQUAL; 153 "<=" return T_LESS_EQUAL; 154 ">=" return T_GREATER_EQUAL; 155 "<" return T_LESS; 156 ">" return T_GREATER; 157 \"|\' { 158 str = yytext[0]; 159 new_string(); 160 BEGIN(STRING); 161 } 162 \n BEGIN(INITIAL); return T_EOL; 163 ({n}|[/.])+ { 164 const struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 165 if (id && id->flags & TF_PARAM) { 166 yylval.id = id; 167 return id->token; 168 } 169 alloc_string(yytext, yyleng); 170 yylval.string = text; 171 return T_WORD; 172 } 173 ({n}|[/.$])+ { 174 /* this token includes at least one '$' */ 175 yylval.string = expand_token(yytext, yyleng); 176 if (strlen(yylval.string)) 177 return T_WORD; 178 free(yylval.string); 179 } 180 #.* /* comment */ 181 \\\n ; 182 [[:blank:]]+ 183 . warn_ignored_character(*yytext); 184 <<EOF>> { 185 BEGIN(INITIAL); 186 } 187} 188 189<STRING>{ 190 "$".* append_expanded_string(yytext); 191 [^$'"\\\n]+/\n { 192 append_string(yytext, yyleng); 193 yylval.string = text; 194 return T_WORD_QUOTE; 195 } 196 [^$'"\\\n]+ { 197 append_string(yytext, yyleng); 198 } 199 \\.?/\n { 200 append_string(yytext + 1, yyleng - 1); 201 yylval.string = text; 202 return T_WORD_QUOTE; 203 } 204 \\.? { 205 append_string(yytext + 1, yyleng - 1); 206 } 207 \'|\" { 208 if (str == yytext[0]) { 209 BEGIN(PARAM); 210 yylval.string = text; 211 return T_WORD_QUOTE; 212 } else 213 append_string(yytext, 1); 214 } 215 \n { 216 fprintf(stderr, 217 "%s:%d:warning: multi-line strings not supported\n", 218 zconf_curname(), zconf_lineno()); 219 BEGIN(INITIAL); 220 return T_EOL; 221 } 222 <<EOF>> { 223 BEGIN(INITIAL); 224 } 225} 226 227<HELP>{ 228 [ \t]+ { 229 ts = 0; 230 for (i = 0; i < yyleng; i++) { 231 if (yytext[i] == '\t') 232 ts = (ts & ~7) + 8; 233 else 234 ts++; 235 } 236 last_ts = ts; 237 if (first_ts) { 238 if (ts < first_ts) { 239 zconf_endhelp(); 240 return T_HELPTEXT; 241 } 242 ts -= first_ts; 243 while (ts > 8) { 244 append_string(" ", 8); 245 ts -= 8; 246 } 247 append_string(" ", ts); 248 } 249 } 250 [ \t]*\n/[^ \t\n] { 251 zconf_endhelp(); 252 return T_HELPTEXT; 253 } 254 [ \t]*\n { 255 append_string("\n", 1); 256 } 257 [^ \t\n].* { 258 while (yyleng) { 259 if ((yytext[yyleng-1] != ' ') && (yytext[yyleng-1] != '\t')) 260 break; 261 yyleng--; 262 } 263 append_string(yytext, yyleng); 264 if (!first_ts) 265 first_ts = last_ts; 266 } 267 <<EOF>> { 268 zconf_endhelp(); 269 return T_HELPTEXT; 270 } 271} 272 273<<EOF>> { 274 if (current_file) { 275 zconf_endfile(); 276 return T_EOL; 277 } 278 fclose(yyin); 279 yyterminate(); 280} 281 282%% 283static char *expand_token(const char *in, size_t n) 284{ 285 char *out; 286 int c; 287 char c2; 288 const char *rest, *end; 289 290 new_string(); 291 append_string(in, n); 292 293 /* get the whole line because we do not know the end of token. */ 294 while ((c = input()) != EOF) { 295 if (c == '\n') { 296 unput(c); 297 break; 298 } 299 c2 = c; 300 append_string(&c2, 1); 301 } 302 303 rest = text; 304 out = expand_one_token(&rest); 305 306 /* push back unused characters to the input stream */ 307 end = rest + strlen(rest); 308 while (end > rest) 309 unput(*--end); 310 311 free(text); 312 313 return out; 314} 315 316static void append_expanded_string(const char *str) 317{ 318 const char *end; 319 char *res; 320 321 str++; 322 323 res = expand_dollar(&str); 324 325 /* push back unused characters to the input stream */ 326 end = str + strlen(str); 327 while (end > str) 328 unput(*--end); 329 330 append_string(res, strlen(res)); 331 332 free(res); 333} 334 335void zconf_starthelp(void) 336{ 337 new_string(); 338 last_ts = first_ts = 0; 339 BEGIN(HELP); 340} 341 342static void zconf_endhelp(void) 343{ 344 yylval.string = text; 345 BEGIN(INITIAL); 346} 347 348 349/* 350 * Try to open specified file with following names: 351 * ./name 352 * $(srctree)/name 353 * The latter is used when srctree is separate from objtree 354 * when compiling the kernel. 355 * Return NULL if file is not found. 356 */ 357FILE *zconf_fopen(const char *name) 358{ 359 char *env, fullname[PATH_MAX+1]; 360 FILE *f; 361 362 f = fopen(name, "r"); 363 if (!f && name != NULL && name[0] != '/') { 364 env = getenv(SRCTREE); 365 if (env) { 366 sprintf(fullname, "%s/%s", env, name); 367 f = fopen(fullname, "r"); 368 } 369 } 370 return f; 371} 372 373void zconf_initscan(const char *name) 374{ 375 yyin = zconf_fopen(name); 376 if (!yyin) { 377 fprintf(stderr, "can't find file %s\n", name); 378 exit(1); 379 } 380 381 current_buf = xmalloc(sizeof(*current_buf)); 382 memset(current_buf, 0, sizeof(*current_buf)); 383 384 current_file = file_lookup(name); 385 yylineno = 1; 386} 387 388void zconf_nextfile(const char *name) 389{ 390 struct file *iter; 391 struct file *file = file_lookup(name); 392 struct buffer *buf = xmalloc(sizeof(*buf)); 393 memset(buf, 0, sizeof(*buf)); 394 395 current_buf->state = YY_CURRENT_BUFFER; 396 yyin = zconf_fopen(file->name); 397 if (!yyin) { 398 fprintf(stderr, "%s:%d: can't open file \"%s\"\n", 399 zconf_curname(), zconf_lineno(), file->name); 400 exit(1); 401 } 402 yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); 403 buf->parent = current_buf; 404 current_buf = buf; 405 406 current_file->lineno = yylineno; 407 file->parent = current_file; 408 409 for (iter = current_file; iter; iter = iter->parent) { 410 if (!strcmp(iter->name, file->name)) { 411 fprintf(stderr, 412 "Recursive inclusion detected.\n" 413 "Inclusion path:\n" 414 " current file : %s\n", file->name); 415 iter = file; 416 do { 417 iter = iter->parent; 418 fprintf(stderr, " included from: %s:%d\n", 419 iter->name, iter->lineno - 1); 420 } while (strcmp(iter->name, file->name)); 421 exit(1); 422 } 423 } 424 425 yylineno = 1; 426 current_file = file; 427} 428 429static void zconf_endfile(void) 430{ 431 struct buffer *parent; 432 433 current_file = current_file->parent; 434 if (current_file) 435 yylineno = current_file->lineno; 436 437 parent = current_buf->parent; 438 if (parent) { 439 fclose(yyin); 440 yy_delete_buffer(YY_CURRENT_BUFFER); 441 yy_switch_to_buffer(parent->state); 442 } 443 free(current_buf); 444 current_buf = parent; 445} 446 447int zconf_lineno(void) 448{ 449 return current_pos.lineno; 450} 451 452const char *zconf_curname(void) 453{ 454 return current_pos.file ? current_pos.file->name : "<none>"; 455} 456