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