Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation.  2005.
0004  */
0005 
0006 %option noyywrap nounput noinput never-interactive
0007 
0008 %x BYTESTRING
0009 %x PROPNODENAME
0010 %s V1
0011 
0012 PROPNODECHAR    [a-zA-Z0-9,._+*#?@-]
0013 PATHCHAR        ({PROPNODECHAR}|[/])
0014 LABEL           [a-zA-Z_][a-zA-Z0-9_]*
0015 STRING          \"([^\\"]|\\.)*\"
0016 CHAR_LITERAL    '([^']|\\')*'
0017 WS              [[:space:]]
0018 COMMENT         "/*"([^*]|\*+[^*/])*\*+"/"
0019 LINECOMMENT     "//".*\n
0020 
0021 %{
0022 #include "dtc.h"
0023 #include "srcpos.h"
0024 #include "dtc-parser.tab.h"
0025 
0026 extern bool treesource_error;
0027 
0028 /* CAUTION: this will stop working if we ever use yyless() or yyunput() */
0029 #define YY_USER_ACTION \
0030         { \
0031                 srcpos_update(&yylloc, yytext, yyleng); \
0032         }
0033 
0034 /*#define LEXDEBUG      1*/
0035 
0036 #ifdef LEXDEBUG
0037 #define DPRINT(fmt, ...)        fprintf(stderr, fmt, ##__VA_ARGS__)
0038 #else
0039 #define DPRINT(fmt, ...)        do { } while (0)
0040 #endif
0041 
0042 static int dts_version = 1;
0043 
0044 #define BEGIN_DEFAULT()         DPRINT("<V1>\n"); \
0045                                 BEGIN(V1); \
0046 
0047 static void push_input_file(const char *filename);
0048 static bool pop_input_file(void);
0049 static void PRINTF(1, 2) lexical_error(const char *fmt, ...);
0050 
0051 %}
0052 
0053 %%
0054 <*>"/include/"{WS}*{STRING} {
0055                         char *name = strchr(yytext, '\"') + 1;
0056                         yytext[yyleng-1] = '\0';
0057                         push_input_file(name);
0058                 }
0059 
0060 <*>^"#"(line)?[ \t]+[0-9]+[ \t]+{STRING}([ \t]+[0-9]+)* {
0061                         char *line, *fnstart, *fnend;
0062                         struct data fn;
0063                         /* skip text before line # */
0064                         line = yytext;
0065                         while (!isdigit((unsigned char)*line))
0066                                 line++;
0067 
0068                         /* regexp ensures that first and list "
0069                          * in the whole yytext are those at
0070                          * beginning and end of the filename string */
0071                         fnstart = memchr(yytext, '"', yyleng);
0072                         for (fnend = yytext + yyleng - 1;
0073                              *fnend != '"'; fnend--)
0074                                 ;
0075                         assert(fnstart && fnend && (fnend > fnstart));
0076 
0077                         fn = data_copy_escape_string(fnstart + 1,
0078                                                      fnend - fnstart - 1);
0079 
0080                         /* Don't allow nuls in filenames */
0081                         if (memchr(fn.val, '\0', fn.len - 1))
0082                                 lexical_error("nul in line number directive");
0083 
0084                         /* -1 since #line is the number of the next line */
0085                         srcpos_set_line(xstrdup(fn.val), atoi(line) - 1);
0086                         data_free(fn);
0087                 }
0088 
0089 <*><<EOF>>              {
0090                         if (!pop_input_file()) {
0091                                 yyterminate();
0092                         }
0093                 }
0094 
0095 <*>{STRING}     {
0096                         DPRINT("String: %s\n", yytext);
0097                         yylval.data = data_copy_escape_string(yytext+1,
0098                                         yyleng-2);
0099                         return DT_STRING;
0100                 }
0101 
0102 <*>"/dts-v1/"   {
0103                         DPRINT("Keyword: /dts-v1/\n");
0104                         dts_version = 1;
0105                         BEGIN_DEFAULT();
0106                         return DT_V1;
0107                 }
0108 
0109 <*>"/plugin/"   {
0110                         DPRINT("Keyword: /plugin/\n");
0111                         return DT_PLUGIN;
0112                 }
0113 
0114 <*>"/memreserve/"       {
0115                         DPRINT("Keyword: /memreserve/\n");
0116                         BEGIN_DEFAULT();
0117                         return DT_MEMRESERVE;
0118                 }
0119 
0120 <*>"/bits/"     {
0121                         DPRINT("Keyword: /bits/\n");
0122                         BEGIN_DEFAULT();
0123                         return DT_BITS;
0124                 }
0125 
0126 <*>"/delete-property/"  {
0127                         DPRINT("Keyword: /delete-property/\n");
0128                         DPRINT("<PROPNODENAME>\n");
0129                         BEGIN(PROPNODENAME);
0130                         return DT_DEL_PROP;
0131                 }
0132 
0133 <*>"/delete-node/"      {
0134                         DPRINT("Keyword: /delete-node/\n");
0135                         DPRINT("<PROPNODENAME>\n");
0136                         BEGIN(PROPNODENAME);
0137                         return DT_DEL_NODE;
0138                 }
0139 
0140 <*>"/omit-if-no-ref/"   {
0141                         DPRINT("Keyword: /omit-if-no-ref/\n");
0142                         DPRINT("<PROPNODENAME>\n");
0143                         BEGIN(PROPNODENAME);
0144                         return DT_OMIT_NO_REF;
0145                 }
0146 
0147 <*>{LABEL}:     {
0148                         DPRINT("Label: %s\n", yytext);
0149                         yylval.labelref = xstrdup(yytext);
0150                         yylval.labelref[yyleng-1] = '\0';
0151                         return DT_LABEL;
0152                 }
0153 
0154 <V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
0155                         char *e;
0156                         DPRINT("Integer Literal: '%s'\n", yytext);
0157 
0158                         errno = 0;
0159                         yylval.integer = strtoull(yytext, &e, 0);
0160 
0161                         if (*e && e[strspn(e, "UL")]) {
0162                                 lexical_error("Bad integer literal '%s'",
0163                                               yytext);
0164                         }
0165 
0166                         if (errno == ERANGE)
0167                                 lexical_error("Integer literal '%s' out of range",
0168                                               yytext);
0169                         else
0170                                 /* ERANGE is the only strtoull error triggerable
0171                                  *  by strings matching the pattern */
0172                                 assert(errno == 0);
0173                         return DT_LITERAL;
0174                 }
0175 
0176 <*>{CHAR_LITERAL}       {
0177                         struct data d;
0178                         DPRINT("Character literal: %s\n", yytext);
0179 
0180                         d = data_copy_escape_string(yytext+1, yyleng-2);
0181                         if (d.len == 1) {
0182                                 lexical_error("Empty character literal");
0183                                 yylval.integer = 0;
0184                         } else {
0185                                 yylval.integer = (unsigned char)d.val[0];
0186 
0187                                 if (d.len > 2)
0188                                         lexical_error("Character literal has %d"
0189                                                       " characters instead of 1",
0190                                                       d.len - 1);
0191                         }
0192 
0193                         data_free(d);
0194                         return DT_CHAR_LITERAL;
0195                 }
0196 
0197 <*>\&{LABEL}    {       /* label reference */
0198                         DPRINT("Ref: %s\n", yytext+1);
0199                         yylval.labelref = xstrdup(yytext+1);
0200                         return DT_LABEL_REF;
0201                 }
0202 
0203 <*>"&{/"{PATHCHAR}*\}   {       /* new-style path reference */
0204                         yytext[yyleng-1] = '\0';
0205                         DPRINT("Ref: %s\n", yytext+2);
0206                         yylval.labelref = xstrdup(yytext+2);
0207                         return DT_PATH_REF;
0208                 }
0209 
0210 <BYTESTRING>[0-9a-fA-F]{2} {
0211                         yylval.byte = strtol(yytext, NULL, 16);
0212                         DPRINT("Byte: %02x\n", (int)yylval.byte);
0213                         return DT_BYTE;
0214                 }
0215 
0216 <BYTESTRING>"]" {
0217                         DPRINT("/BYTESTRING\n");
0218                         BEGIN_DEFAULT();
0219                         return ']';
0220                 }
0221 
0222 <PROPNODENAME>\\?{PROPNODECHAR}+ {
0223                         DPRINT("PropNodeName: %s\n", yytext);
0224                         yylval.propnodename = xstrdup((yytext[0] == '\\') ?
0225                                                         yytext + 1 : yytext);
0226                         BEGIN_DEFAULT();
0227                         return DT_PROPNODENAME;
0228                 }
0229 
0230 "/incbin/"      {
0231                         DPRINT("Binary Include\n");
0232                         return DT_INCBIN;
0233                 }
0234 
0235 <*>{WS}+        /* eat whitespace */
0236 <*>{COMMENT}+   /* eat C-style comments */
0237 <*>{LINECOMMENT}+ /* eat C++-style comments */
0238 
0239 <*>"<<"         { return DT_LSHIFT; };
0240 <*>">>"         { return DT_RSHIFT; };
0241 <*>"<="         { return DT_LE; };
0242 <*>">="         { return DT_GE; };
0243 <*>"=="         { return DT_EQ; };
0244 <*>"!="         { return DT_NE; };
0245 <*>"&&"         { return DT_AND; };
0246 <*>"||"         { return DT_OR; };
0247 
0248 <*>.            {
0249                         DPRINT("Char: %c (\\x%02x)\n", yytext[0],
0250                                 (unsigned)yytext[0]);
0251                         if (yytext[0] == '[') {
0252                                 DPRINT("<BYTESTRING>\n");
0253                                 BEGIN(BYTESTRING);
0254                         }
0255                         if ((yytext[0] == '{')
0256                             || (yytext[0] == ';')) {
0257                                 DPRINT("<PROPNODENAME>\n");
0258                                 BEGIN(PROPNODENAME);
0259                         }
0260                         return yytext[0];
0261                 }
0262 
0263 %%
0264 
0265 static void push_input_file(const char *filename)
0266 {
0267         assert(filename);
0268 
0269         srcfile_push(filename);
0270 
0271         yyin = current_srcfile->f;
0272 
0273         yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
0274 }
0275 
0276 
0277 static bool pop_input_file(void)
0278 {
0279         if (srcfile_pop() == 0)
0280                 return false;
0281 
0282         yypop_buffer_state();
0283         yyin = current_srcfile->f;
0284 
0285         return true;
0286 }
0287 
0288 static void lexical_error(const char *fmt, ...)
0289 {
0290         va_list ap;
0291 
0292         va_start(ap, fmt);
0293         srcpos_verror(&yylloc, "Lexical error", fmt, ap);
0294         va_end(ap);
0295 
0296         treesource_error = true;
0297 }