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