linux/scripts/dtc/dtc-lexer.l
<<
>>
Prefs
   1/*
   2 * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
   3 *
   4 *
   5 * This program is free software; you can redistribute it and/or
   6 * modify it under the terms of the GNU General Public License as
   7 * published by the Free Software Foundation; either version 2 of the
   8 * License, or (at your option) any later version.
   9 *
  10 *  This program is distributed in the hope that it will be useful,
  11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13 *  General Public License for more details.
  14 *
  15 *  You should have received a copy of the GNU General Public License
  16 *  along with this program; if not, write to the Free Software
  17 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
  18 *                                                                   USA
  19 */
  20
  21%option noyywrap nounput noinput never-interactive
  22
  23%x BYTESTRING
  24%x PROPNODENAME
  25%s V1
  26
  27PROPNODECHAR    [a-zA-Z0-9,._+*#?@-]
  28PATHCHAR        ({PROPNODECHAR}|[/])
  29LABEL           [a-zA-Z_][a-zA-Z0-9_]*
  30STRING          \"([^\\"]|\\.)*\"
  31CHAR_LITERAL    '([^']|\\')*'
  32WS              [[:space:]]
  33COMMENT         "/*"([^*]|\*+[^*/])*\*+"/"
  34LINECOMMENT     "//".*\n
  35
  36%{
  37#include "dtc.h"
  38#include "srcpos.h"
  39#include "dtc-parser.tab.h"
  40
  41YYLTYPE yylloc;
  42extern bool treesource_error;
  43
  44/* CAUTION: this will stop working if we ever use yyless() or yyunput() */
  45#define YY_USER_ACTION \
  46        { \
  47                srcpos_update(&yylloc, yytext, yyleng); \
  48        }
  49
  50/*#define LEXDEBUG      1*/
  51
  52#ifdef LEXDEBUG
  53#define DPRINT(fmt, ...)        fprintf(stderr, fmt, ##__VA_ARGS__)
  54#else
  55#define DPRINT(fmt, ...)        do { } while (0)
  56#endif
  57
  58static int dts_version = 1;
  59
  60#define BEGIN_DEFAULT()         DPRINT("<V1>\n"); \
  61                                BEGIN(V1); \
  62
  63static void push_input_file(const char *filename);
  64static bool pop_input_file(void);
  65static void lexical_error(const char *fmt, ...);
  66%}
  67
  68%%
  69<*>"/include/"{WS}*{STRING} {
  70                        char *name = strchr(yytext, '\"') + 1;
  71                        yytext[yyleng-1] = '\0';
  72                        push_input_file(name);
  73                }
  74
  75<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
  76                        char *line, *tmp, *fn;
  77                        /* skip text before line # */
  78                        line = yytext;
  79                        while (!isdigit((unsigned char)*line))
  80                                line++;
  81                        /* skip digits in line # */
  82                        tmp = line;
  83                        while (!isspace((unsigned char)*tmp))
  84                                tmp++;
  85                        /* "NULL"-terminate line # */
  86                        *tmp = '\0';
  87                        /* start of filename */
  88                        fn = strchr(tmp + 1, '"') + 1;
  89                        /* strip trailing " from filename */
  90                        tmp = strchr(fn, '"');
  91                        *tmp = 0;
  92                        /* -1 since #line is the number of the next line */
  93                        srcpos_set_line(xstrdup(fn), atoi(line) - 1);
  94                }
  95
  96<*><<EOF>>              {
  97                        if (!pop_input_file()) {
  98                                yyterminate();
  99                        }
 100                }
 101
 102<*>{STRING}     {
 103                        DPRINT("String: %s\n", yytext);
 104                        yylval.data = data_copy_escape_string(yytext+1,
 105                                        yyleng-2);
 106                        return DT_STRING;
 107                }
 108
 109<*>"/dts-v1/"   {
 110                        DPRINT("Keyword: /dts-v1/\n");
 111                        dts_version = 1;
 112                        BEGIN_DEFAULT();
 113                        return DT_V1;
 114                }
 115
 116<*>"/memreserve/"       {
 117                        DPRINT("Keyword: /memreserve/\n");
 118                        BEGIN_DEFAULT();
 119                        return DT_MEMRESERVE;
 120                }
 121
 122<*>"/bits/"     {
 123                        DPRINT("Keyword: /bits/\n");
 124                        BEGIN_DEFAULT();
 125                        return DT_BITS;
 126                }
 127
 128<*>"/delete-property/"  {
 129                        DPRINT("Keyword: /delete-property/\n");
 130                        DPRINT("<PROPNODENAME>\n");
 131                        BEGIN(PROPNODENAME);
 132                        return DT_DEL_PROP;
 133                }
 134
 135<*>"/delete-node/"      {
 136                        DPRINT("Keyword: /delete-node/\n");
 137                        DPRINT("<PROPNODENAME>\n");
 138                        BEGIN(PROPNODENAME);
 139                        return DT_DEL_NODE;
 140                }
 141
 142<*>{LABEL}:     {
 143                        DPRINT("Label: %s\n", yytext);
 144                        yylval.labelref = xstrdup(yytext);
 145                        yylval.labelref[yyleng-1] = '\0';
 146                        return DT_LABEL;
 147                }
 148
 149<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
 150                        char *e;
 151                        DPRINT("Integer Literal: '%s'\n", yytext);
 152
 153                        errno = 0;
 154                        yylval.integer = strtoull(yytext, &e, 0);
 155
 156                        assert(!(*e) || !e[strspn(e, "UL")]);
 157
 158                        if (errno == ERANGE)
 159                                lexical_error("Integer literal '%s' out of range",
 160                                              yytext);
 161                        else
 162                                /* ERANGE is the only strtoull error triggerable
 163                                 *  by strings matching the pattern */
 164                                assert(errno == 0);
 165                        return DT_LITERAL;
 166                }
 167
 168<*>{CHAR_LITERAL}       {
 169                        struct data d;
 170                        DPRINT("Character literal: %s\n", yytext);
 171
 172                        d = data_copy_escape_string(yytext+1, yyleng-2);
 173                        if (d.len == 1) {
 174                                lexical_error("Empty character literal");
 175                                yylval.integer = 0;
 176                                return DT_CHAR_LITERAL;
 177                        }
 178
 179                        yylval.integer = (unsigned char)d.val[0];
 180
 181                        if (d.len > 2)
 182                                lexical_error("Character literal has %d"
 183                                              " characters instead of 1",
 184                                              d.len - 1);
 185
 186                        return DT_CHAR_LITERAL;
 187                }
 188
 189<*>\&{LABEL}    {       /* label reference */
 190                        DPRINT("Ref: %s\n", yytext+1);
 191                        yylval.labelref = xstrdup(yytext+1);
 192                        return DT_REF;
 193                }
 194
 195<*>"&{/"{PATHCHAR}*\}   {       /* new-style path reference */
 196                        yytext[yyleng-1] = '\0';
 197                        DPRINT("Ref: %s\n", yytext+2);
 198                        yylval.labelref = xstrdup(yytext+2);
 199                        return DT_REF;
 200                }
 201
 202<BYTESTRING>[0-9a-fA-F]{2} {
 203                        yylval.byte = strtol(yytext, NULL, 16);
 204                        DPRINT("Byte: %02x\n", (int)yylval.byte);
 205                        return DT_BYTE;
 206                }
 207
 208<BYTESTRING>"]" {
 209                        DPRINT("/BYTESTRING\n");
 210                        BEGIN_DEFAULT();
 211                        return ']';
 212                }
 213
 214<PROPNODENAME>\\?{PROPNODECHAR}+ {
 215                        DPRINT("PropNodeName: %s\n", yytext);
 216                        yylval.propnodename = xstrdup((yytext[0] == '\\') ?
 217                                                        yytext + 1 : yytext);
 218                        BEGIN_DEFAULT();
 219                        return DT_PROPNODENAME;
 220                }
 221
 222"/incbin/"      {
 223                        DPRINT("Binary Include\n");
 224                        return DT_INCBIN;
 225                }
 226
 227<*>{WS}+        /* eat whitespace */
 228<*>{COMMENT}+   /* eat C-style comments */
 229<*>{LINECOMMENT}+ /* eat C++-style comments */
 230
 231<*>"<<"         { return DT_LSHIFT; };
 232<*>">>"         { return DT_RSHIFT; };
 233<*>"<="         { return DT_LE; };
 234<*>">="         { return DT_GE; };
 235<*>"=="         { return DT_EQ; };
 236<*>"!="         { return DT_NE; };
 237<*>"&&"         { return DT_AND; };
 238<*>"||"         { return DT_OR; };
 239
 240<*>.            {
 241                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 242                                (unsigned)yytext[0]);
 243                        if (yytext[0] == '[') {
 244                                DPRINT("<BYTESTRING>\n");
 245                                BEGIN(BYTESTRING);
 246                        }
 247                        if ((yytext[0] == '{')
 248                            || (yytext[0] == ';')) {
 249                                DPRINT("<PROPNODENAME>\n");
 250                                BEGIN(PROPNODENAME);
 251                        }
 252                        return yytext[0];
 253                }
 254
 255%%
 256
 257static void push_input_file(const char *filename)
 258{
 259        assert(filename);
 260
 261        srcfile_push(filename);
 262
 263        yyin = current_srcfile->f;
 264
 265        yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
 266}
 267
 268
 269static bool pop_input_file(void)
 270{
 271        if (srcfile_pop() == 0)
 272                return false;
 273
 274        yypop_buffer_state();
 275        yyin = current_srcfile->f;
 276
 277        return true;
 278}
 279
 280static void lexical_error(const char *fmt, ...)
 281{
 282        va_list ap;
 283
 284        va_start(ap, fmt);
 285        srcpos_verror(&yylloc, "Lexical error", fmt, ap);
 286        va_end(ap);
 287
 288        treesource_error = true;
 289}
 290