1%option backup nostdinit noyywrap never-interactive full ecs 2%option 8bit backup 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#define LKC_DIRECT_LINK 18#include "lkc.h" 19 20#define START_STRSIZE 16 21 22static struct { 23 struct file *file; 24 int lineno; 25} current_pos; 26 27static char *text; 28static int text_size, text_asize; 29 30struct buffer { 31 struct buffer *parent; 32 YY_BUFFER_STATE state; 33}; 34 35struct buffer *current_buf; 36 37static int last_ts, first_ts; 38 39static void zconf_endhelp(void); 40static void zconf_endfile(void); 41 42static void new_string(void) 43{ 44 text = malloc(START_STRSIZE); 45 text_asize = START_STRSIZE; 46 text_size = 0; 47 *text = 0; 48} 49 50static void append_string(const char *str, int size) 51{ 52 int new_size = text_size + size + 1; 53 if (new_size > text_asize) { 54 new_size += START_STRSIZE - 1; 55 new_size &= -START_STRSIZE; 56 text = realloc(text, new_size); 57 text_asize = new_size; 58 } 59 memcpy(text + text_size, str, size); 60 text_size += size; 61 text[text_size] = 0; 62} 63 64static void alloc_string(const char *str, int size) 65{ 66 text = malloc(size + 1); 67 memcpy(text, str, size); 68 text[size] = 0; 69} 70%} 71 72ws [ \n\t] 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 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 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 = malloc(sizeof(*current_buf)); 293 memset(current_buf, 0, sizeof(*current_buf)); 294 295 current_file = file_lookup(name); 296 current_file->lineno = 1; 297 current_file->flags = FILE_BUSY; 298} 299 300void zconf_nextfile(const char *name) 301{ 302 struct file *file = file_lookup(name); 303 struct buffer *buf = malloc(sizeof(*buf)); 304 memset(buf, 0, sizeof(*buf)); 305 306 current_buf->state = YY_CURRENT_BUFFER; 307 yyin = zconf_fopen(name); 308 if (!yyin) { 309 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), 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 if (file->flags & FILE_BUSY) { 317 printf("%s:%d: do not source '%s' from itself\n", 318 zconf_curname(), zconf_lineno(), name); 319 exit(1); 320 } 321 if (file->flags & FILE_SCANNED) { 322 printf("%s:%d: file '%s' is already sourced from '%s'\n", 323 zconf_curname(), zconf_lineno(), name, 324 file->parent->name); 325 exit(1); 326 } 327 file->flags |= FILE_BUSY; 328 file->lineno = 1; 329 file->parent = current_file; 330 current_file = file; 331} 332 333static void zconf_endfile(void) 334{ 335 struct buffer *parent; 336 337 current_file->flags |= FILE_SCANNED; 338 current_file->flags &= ~FILE_BUSY; 339 current_file = current_file->parent; 340 341 parent = current_buf->parent; 342 if (parent) { 343 fclose(yyin); 344 yy_delete_buffer(YY_CURRENT_BUFFER); 345 yy_switch_to_buffer(parent->state); 346 } 347 free(current_buf); 348 current_buf = parent; 349} 350 351int zconf_lineno(void) 352{ 353 return current_pos.lineno; 354} 355 356char *zconf_curname(void) 357{ 358 return current_pos.file ? current_pos.file->name : "<none>"; 359} 360