linux/scripts/kconfig/zconf.l
<<
>>
Prefs
   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