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 PRINTF(1, 2) lexical_error(const char *fmt, ...);
  66
  67%}
  68
  69%%
  70<*>"/include/"{WS}*{STRING} {
  71                        char *name = strchr(yytext, '\"') + 1;
  72                        yytext[yyleng-1] = '\0';
  73                        push_input_file(name);
  74                }
  75
  76<*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)? {
  77                        char *line, *fnstart, *fnend;
  78                        struct data fn;
  79                        /* skip text before line # */
  80                        line = yytext;
  81                        while (!isdigit((unsigned char)*line))
  82                                line++;
  83
  84                        /* regexp ensures that first and list "
  85                         * in the whole yytext are those at
  86                         * beginning and end of the filename string */
  87                        fnstart = memchr(yytext, '"', yyleng);
  88                        for (fnend = yytext + yyleng - 1;
  89                             *fnend != '"'; fnend--)
  90                                ;
  91                        assert(fnstart && fnend && (fnend > fnstart));
  92
  93                        fn = data_copy_escape_string(fnstart + 1,
  94                                                     fnend - fnstart - 1);
  95
  96                        /* Don't allow nuls in filenames */
  97                        if (memchr(fn.val, '\0', fn.len - 1))
  98                                lexical_error("nul in line number directive");
  99
 100                        /* -1 since #line is the number of the next line */
 101                        srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
 102                        data_free(fn);
 103                }
 104
 105<*><<EOF>>              {
 106                        if (!pop_input_file()) {
 107                                yyterminate();
 108                        }
 109                }
 110
 111<*>{STRING}     {
 112                        DPRINT("String: %s\n", yytext);
 113                        yylval.data = data_copy_escape_string(yytext+1,
 114                                        yyleng-2);
 115                        return DT_STRING;
 116                }
 117
 118<*>"/dts-v1/"   {
 119                        DPRINT("Keyword: /dts-v1/\n");
 120                        dts_version = 1;
 121                        BEGIN_DEFAULT();
 122                        return DT_V1;
 123                }
 124
 125<*>"/plugin/"   {
 126                        DPRINT("Keyword: /plugin/\n");
 127                        return DT_PLUGIN;
 128                }
 129
 130<*>"/memreserve/"       {
 131                        DPRINT("Keyword: /memreserve/\n");
 132                        BEGIN_DEFAULT();
 133                        return DT_MEMRESERVE;
 134                }
 135
 136<*>"/bits/"     {
 137                        DPRINT("Keyword: /bits/\n");
 138                        BEGIN_DEFAULT();
 139                        return DT_BITS;
 140                }
 141
 142<*>"/delete-property/"  {
 143                        DPRINT("Keyword: /delete-property/\n");
 144                        DPRINT("<PROPNODENAME>\n");
 145                        BEGIN(PROPNODENAME);
 146                        return DT_DEL_PROP;
 147                }
 148
 149<*>"/delete-node/"      {
 150                        DPRINT("Keyword: /delete-node/\n");
 151                        DPRINT("<PROPNODENAME>\n");
 152                        BEGIN(PROPNODENAME);
 153                        return DT_DEL_NODE;
 154                }
 155
 156<*>{LABEL}:     {
 157                        DPRINT("Label: %s\n", yytext);
 158                        yylval.labelref = xstrdup(yytext);
 159                        yylval.labelref[yyleng-1] = '\0';
 160                        return DT_LABEL;
 161                }
 162
 163<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
 164                        char *e;
 165                        DPRINT("Integer Literal: '%s'\n", yytext);
 166
 167                        errno = 0;
 168                        yylval.integer = strtoull(yytext, &e, 0);
 169
 170                        if (*e && e[strspn(e, "UL")]) {
 171                                lexical_error("Bad integer literal '%s'",
 172                                              yytext);
 173                        }
 174
 175                        if (errno == ERANGE)
 176                                lexical_error("Integer literal '%s' out of range",
 177                                              yytext);
 178                        else
 179                                /* ERANGE is the only strtoull error triggerable
 180                                 *  by strings matching the pattern */
 181                                assert(errno == 0);
 182                        return DT_LITERAL;
 183                }
 184
 185<*>{CHAR_LITERAL}       {
 186                        struct data d;
 187                        DPRINT("Character literal: %s\n", yytext);
 188
 189                        d = data_copy_escape_string(yytext+1, yyleng-2);
 190                        if (d.len == 1) {
 191                                lexical_error("Empty character literal");
 192                                yylval.integer = 0;
 193                        } else {
 194                                yylval.integer = (unsigned char)d.val[0];
 195
 196                                if (d.len > 2)
 197                                        lexical_error("Character literal has %d"
 198                                                      " characters instead of 1",
 199                                                      d.len - 1);
 200                        }
 201
 202                        data_free(d);
 203                        return DT_CHAR_LITERAL;
 204                }
 205
 206<*>\&{LABEL}    {       /* label reference */
 207                        DPRINT("Ref: %s\n", yytext+1);
 208                        yylval.labelref = xstrdup(yytext+1);
 209                        return DT_REF;
 210                }
 211
 212<*>"&{/"{PATHCHAR}*\}   {       /* new-style path reference */
 213                        yytext[yyleng-1] = '\0';
 214                        DPRINT("Ref: %s\n", yytext+2);
 215                        yylval.labelref = xstrdup(yytext+2);
 216                        return DT_REF;
 217                }
 218
 219<BYTESTRING>[0-9a-fA-F]{2} {
 220                        yylval.byte = strtol(yytext, NULL, 16);
 221                        DPRINT("Byte: %02x\n", (int)yylval.byte);
 222                        return DT_BYTE;
 223                }
 224
 225<BYTESTRING>"]" {
 226                        DPRINT("/BYTESTRING\n");
 227                        BEGIN_DEFAULT();
 228                        return ']';
 229                }
 230
 231<PROPNODENAME>\\?{PROPNODECHAR}+ {
 232                        DPRINT("PropNodeName: %s\n", yytext);
 233                        yylval.propnodename = xstrdup((yytext[0] == '\\') ?
 234                                                        yytext + 1 : yytext);
 235                        BEGIN_DEFAULT();
 236                        return DT_PROPNODENAME;
 237                }
 238
 239"/incbin/"      {
 240                        DPRINT("Binary Include\n");
 241                        return DT_INCBIN;
 242                }
 243
 244<*>{WS}+        /* eat whitespace */
 245<*>{COMMENT}+   /* eat C-style comments */
 246<*>{LINECOMMENT}+ /* eat C++-style comments */
 247
 248<*>"<<"         { return DT_LSHIFT; };
 249<*>">>"         { return DT_RSHIFT; };
 250<*>"<="         { return DT_LE; };
 251<*>">="         { return DT_GE; };
 252<*>"=="         { return DT_EQ; };
 253<*>"!="         { return DT_NE; };
 254<*>"&&"         { return DT_AND; };
 255<*>"||"         { return DT_OR; };
 256
 257<*>.            {
 258                        DPRINT("Char: %c (\\x%02x)\n", yytext[0],
 259                                (unsigned)yytext[0]);
 260                        if (yytext[0] == '[') {
 261                                DPRINT("<BYTESTRING>\n");
 262                                BEGIN(BYTESTRING);
 263                        }
 264                        if ((yytext[0] == '{')
 265                            || (yytext[0] == ';')) {
 266                                DPRINT("<PROPNODENAME>\n");
 267                                BEGIN(PROPNODENAME);
 268                        }
 269                        return yytext[0];
 270                }
 271
 272%%
 273
 274static void push_input_file(const char *filename)
 275{
 276        assert(filename);
 277
 278        srcfile_push(filename);
 279
 280        yyin = current_srcfile->f;
 281
 282        yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
 283}
 284
 285
 286static bool pop_input_file(void)
 287{
 288        if (srcfile_pop() == 0)
 289                return false;
 290
 291        yypop_buffer_state();
 292        yyin = current_srcfile->f;
 293
 294        return true;
 295}
 296
 297static void lexical_error(const char *fmt, ...)
 298{
 299        va_list ap;
 300
 301        va_start(ap, fmt);
 302        srcpos_verror(&yylloc, "Lexical error", fmt, ap);
 303        va_end(ap);
 304
 305        treesource_error = true;
 306}
 307