1%option backup nostdinit noyywrap never-interactive full ecs 2%option 8bit backup nodefault perf-report perf-report 3%x COMMAND HELP STRING PARAM 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 <limits.h> 11#include <stdio.h> 12#include <stdlib.h> 13#include <string.h> 14#include <unistd.h> 15 16#define LKC_DIRECT_LINK 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 41void new_string(void) 42{ 43 text = malloc(START_STRSIZE); 44 text_asize = START_STRSIZE; 45 text_size = 0; 46 *text = 0; 47} 48 49void append_string(const char *str, int size) 50{ 51 int new_size = text_size + size + 1; 52 if (size > 70) { 53 fprintf (stderr, "%s:%d error: Overlong line\n", 54 current_file->name, current_file->lineno); 55 } 56 if (new_size > text_asize) { 57 new_size += START_STRSIZE - 1; 58 new_size &= -START_STRSIZE; 59 text = realloc(text, new_size); 60 text_asize = new_size; 61 } 62 memcpy(text + text_size, str, size); 63 text_size += size; 64 text[text_size] = 0; 65} 66 67void alloc_string(const char *str, int size) 68{ 69 text = malloc(size + 1); 70 memcpy(text, str, size); 71 text[size] = 0; 72} 73%} 74 75ws [ \n\t] 76n [A-Za-z0-9_] 77 78%% 79 int str = 0; 80 int ts, i; 81 82[ \t]*#.*\n | 83[ \t]*\n { 84 current_file->lineno++; 85 return T_EOL; 86} 87[ \t]*#.* 88 89 90[ \t]+ { 91 BEGIN(COMMAND); 92} 93 94. { 95 unput(yytext[0]); 96 BEGIN(COMMAND); 97} 98 99 100<COMMAND>{ 101 {n}+ { 102 struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 103 BEGIN(PARAM); 104 current_pos.file = current_file; 105 current_pos.lineno = current_file->lineno; 106 if (id && id->flags & TF_COMMAND) { 107 zconflval.id = id; 108 return id->token; 109 } 110 alloc_string(yytext, yyleng); 111 zconflval.string = text; 112 return T_WORD; 113 } 114 . 115 \n { 116 BEGIN(INITIAL); 117 current_file->lineno++; 118 return T_EOL; 119 } 120} 121 122<PARAM>{ 123 "&&" return T_AND; 124 "||" return T_OR; 125 "(" return T_OPEN_PAREN; 126 ")" return T_CLOSE_PAREN; 127 "!" return T_NOT; 128 "=" return T_EQUAL; 129 "!=" return T_UNEQUAL; 130 \"|\' { 131 str = yytext[0]; 132 new_string(); 133 BEGIN(STRING); 134 } 135 \n BEGIN(INITIAL); current_file->lineno++; return T_EOL; 136 --- /* ignore */ 137 ({n}|[-/.])+ { 138 struct kconf_id *id = kconf_id_lookup(yytext, yyleng); 139 if (id && id->flags & TF_PARAM) { 140 zconflval.id = id; 141 return id->token; 142 } 143 alloc_string(yytext, yyleng); 144 zconflval.string = text; 145 return T_WORD; 146 } 147 #.* /* comment */ 148 \\\n current_file->lineno++; 149 . 150 <<EOF>> { 151 BEGIN(INITIAL); 152 } 153} 154 155<STRING>{ 156 [^'"\\\n]+/\n { 157 append_string(yytext, yyleng); 158 zconflval.string = text; 159 return T_WORD_QUOTE; 160 } 161 [^'"\\\n]+ { 162 append_string(yytext, yyleng); 163 } 164 \\.?/\n { 165 append_string(yytext + 1, yyleng - 1); 166 zconflval.string = text; 167 return T_WORD_QUOTE; 168 } 169 \\.? { 170 append_string(yytext + 1, yyleng - 1); 171 } 172 \'|\" { 173 if (str == yytext[0]) { 174 BEGIN(PARAM); 175 zconflval.string = text; 176 return T_WORD_QUOTE; 177 } else 178 append_string(yytext, 1); 179 } 180 \n { 181 printf("%s:%d:warning: multi-line strings not supported\n", zconf_curname(), zconf_lineno()); 182 current_file->lineno++; 183 BEGIN(INITIAL); 184 return T_EOL; 185 } 186 <<EOF>> { 187 BEGIN(INITIAL); 188 } 189} 190 191<HELP>{ 192 [ \t]+ { 193 ts = 0; 194 for (i = 0; i < yyleng; i++) { 195 if (yytext[i] == '\t') 196 ts = (ts & ~7) + 8; 197 else 198 ts++; 199 } 200 last_ts = ts; 201 if (first_ts) { 202 if (ts < first_ts) { 203 zconf_endhelp(); 204 return T_HELPTEXT; 205 } 206 ts -= first_ts; 207 while (ts > 8) { 208 append_string(" ", 8); 209 ts -= 8; 210 } 211 append_string(" ", ts); 212 } 213 } 214 [ \t]*\n/[^ \t\n] { 215 current_file->lineno++; 216 zconf_endhelp(); 217 return T_HELPTEXT; 218 } 219 [ \t]*\n { 220 current_file->lineno++; 221 append_string("\n", 1); 222 } 223 [^ \t\n].* { 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%% 244void zconf_starthelp(void) 245{ 246 new_string(); 247 last_ts = first_ts = 0; 248 BEGIN(HELP); 249} 250 251static 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 */ 266FILE *zconf_fopen(const char *name) 267{ 268 char *env; 269 FILE *f; 270 271 f = fopen(name, "r"); 272 if (!f && name[0] != '/') { 273 env = getenv(SRCTREE); 274 if (env) { 275 char *fullname = alloca(strlen(env) + strlen(name) + 2); 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 current_file->flags = FILE_BUSY; 297} 298 299void zconf_nextfile(const char *name) 300{ 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(name); 307 if (!yyin) { 308 printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), 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 if (file->flags & FILE_BUSY) { 316 printf("recursive scan (%s)?\n", name); 317 exit(1); 318 } 319 if (file->flags & FILE_SCANNED) { 320 printf("file %s already scanned?\n", name); 321 exit(1); 322 } 323 file->flags |= FILE_BUSY; 324 file->lineno = 1; 325 file->parent = current_file; 326 current_file = file; 327} 328 329static void zconf_endfile(void) 330{ 331 struct buffer *parent; 332 333 current_file->flags |= FILE_SCANNED; 334 current_file->flags &= ~FILE_BUSY; 335 current_file = current_file->parent; 336 337 parent = current_buf->parent; 338 if (parent) { 339 fclose(yyin); 340 yy_delete_buffer(YY_CURRENT_BUFFER); 341 yy_switch_to_buffer(parent->state); 342 } 343 free(current_buf); 344 current_buf = parent; 345} 346 347int zconf_lineno(void) 348{ 349 return current_pos.lineno; 350} 351 352char *zconf_curname(void) 353{ 354 return current_pos.file ? current_pos.file->name : "<none>"; 355} 356