linux/scripts/dtc/dtc-parser.y
<<
>>
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%{
  22#include <stdio.h>
  23
  24#include "dtc.h"
  25#include "srcpos.h"
  26
  27YYLTYPE yylloc;
  28
  29extern int yylex(void);
  30extern void print_error(char const *fmt, ...);
  31extern void yyerror(char const *s);
  32
  33extern struct boot_info *the_boot_info;
  34extern int treesource_error;
  35
  36static unsigned long long eval_literal(const char *s, int base, int bits);
  37%}
  38
  39%union {
  40        char *propnodename;
  41        char *literal;
  42        char *labelref;
  43        unsigned int cbase;
  44        uint8_t byte;
  45        struct data data;
  46
  47        uint64_t addr;
  48        cell_t cell;
  49        struct property *prop;
  50        struct property *proplist;
  51        struct node *node;
  52        struct node *nodelist;
  53        struct reserve_info *re;
  54}
  55
  56%token DT_V1
  57%token DT_MEMRESERVE
  58%token <propnodename> DT_PROPNODENAME
  59%token <literal> DT_LITERAL
  60%token <cbase> DT_BASE
  61%token <byte> DT_BYTE
  62%token <data> DT_STRING
  63%token <labelref> DT_LABEL
  64%token <labelref> DT_REF
  65%token DT_INCBIN
  66
  67%type <data> propdata
  68%type <data> propdataprefix
  69%type <re> memreserve
  70%type <re> memreserves
  71%type <addr> addr
  72%type <data> celllist
  73%type <cell> cellval
  74%type <data> bytestring
  75%type <prop> propdef
  76%type <proplist> proplist
  77
  78%type <node> devicetree
  79%type <node> nodedef
  80%type <node> subnode
  81%type <nodelist> subnodes
  82
  83%%
  84
  85sourcefile:
  86          DT_V1 ';' memreserves devicetree
  87                {
  88                        the_boot_info = build_boot_info($3, $4,
  89                                                        guess_boot_cpuid($4));
  90                }
  91        ;
  92
  93memreserves:
  94          /* empty */
  95                {
  96                        $$ = NULL;
  97                }
  98        | memreserve memreserves
  99                {
 100                        $$ = chain_reserve_entry($1, $2);
 101                }
 102        ;
 103
 104memreserve:
 105          DT_MEMRESERVE addr addr ';'
 106                {
 107                        $$ = build_reserve_entry($2, $3);
 108                }
 109        | DT_LABEL memreserve
 110                {
 111                        add_label(&$2->labels, $1);
 112                        $$ = $2;
 113                }
 114        ;
 115
 116addr:
 117          DT_LITERAL
 118                {
 119                        $$ = eval_literal($1, 0, 64);
 120                }
 121          ;
 122
 123devicetree:
 124          '/' nodedef
 125                {
 126                        $$ = name_node($2, "");
 127                }
 128        | devicetree '/' nodedef
 129                {
 130                        $$ = merge_nodes($1, $3);
 131                }
 132        | devicetree DT_REF nodedef
 133                {
 134                        struct node *target = get_node_by_ref($1, $2);
 135
 136                        if (target)
 137                                merge_nodes(target, $3);
 138                        else
 139                                print_error("label or path, '%s', not found", $2);
 140                        $$ = $1;
 141                }
 142        ;
 143
 144nodedef:
 145          '{' proplist subnodes '}' ';'
 146                {
 147                        $$ = build_node($2, $3);
 148                }
 149        ;
 150
 151proplist:
 152          /* empty */
 153                {
 154                        $$ = NULL;
 155                }
 156        | proplist propdef
 157                {
 158                        $$ = chain_property($2, $1);
 159                }
 160        ;
 161
 162propdef:
 163          DT_PROPNODENAME '=' propdata ';'
 164                {
 165                        $$ = build_property($1, $3);
 166                }
 167        | DT_PROPNODENAME ';'
 168                {
 169                        $$ = build_property($1, empty_data);
 170                }
 171        | DT_LABEL propdef
 172                {
 173                        add_label(&$2->labels, $1);
 174                        $$ = $2;
 175                }
 176        ;
 177
 178propdata:
 179          propdataprefix DT_STRING
 180                {
 181                        $$ = data_merge($1, $2);
 182                }
 183        | propdataprefix '<' celllist '>'
 184                {
 185                        $$ = data_merge($1, $3);
 186                }
 187        | propdataprefix '[' bytestring ']'
 188                {
 189                        $$ = data_merge($1, $3);
 190                }
 191        | propdataprefix DT_REF
 192                {
 193                        $$ = data_add_marker($1, REF_PATH, $2);
 194                }
 195        | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
 196                {
 197                        FILE *f = srcfile_relative_open($4.val, NULL);
 198                        struct data d;
 199
 200                        if ($6 != 0)
 201                                if (fseek(f, $6, SEEK_SET) != 0)
 202                                        print_error("Couldn't seek to offset %llu in \"%s\": %s",
 203                                                     (unsigned long long)$6,
 204                                                     $4.val,
 205                                                     strerror(errno));
 206
 207                        d = data_copy_file(f, $8);
 208
 209                        $$ = data_merge($1, d);
 210                        fclose(f);
 211                }
 212        | propdataprefix DT_INCBIN '(' DT_STRING ')'
 213                {
 214                        FILE *f = srcfile_relative_open($4.val, NULL);
 215                        struct data d = empty_data;
 216
 217                        d = data_copy_file(f, -1);
 218
 219                        $$ = data_merge($1, d);
 220                        fclose(f);
 221                }
 222        | propdata DT_LABEL
 223                {
 224                        $$ = data_add_marker($1, LABEL, $2);
 225                }
 226        ;
 227
 228propdataprefix:
 229          /* empty */
 230                {
 231                        $$ = empty_data;
 232                }
 233        | propdata ','
 234                {
 235                        $$ = $1;
 236                }
 237        | propdataprefix DT_LABEL
 238                {
 239                        $$ = data_add_marker($1, LABEL, $2);
 240                }
 241        ;
 242
 243celllist:
 244          /* empty */
 245                {
 246                        $$ = empty_data;
 247                }
 248        | celllist cellval
 249                {
 250                        $$ = data_append_cell($1, $2);
 251                }
 252        | celllist DT_REF
 253                {
 254                        $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
 255                                                              $2), -1);
 256                }
 257        | celllist DT_LABEL
 258                {
 259                        $$ = data_add_marker($1, LABEL, $2);
 260                }
 261        ;
 262
 263cellval:
 264          DT_LITERAL
 265                {
 266                        $$ = eval_literal($1, 0, 32);
 267                }
 268        ;
 269
 270bytestring:
 271          /* empty */
 272                {
 273                        $$ = empty_data;
 274                }
 275        | bytestring DT_BYTE
 276                {
 277                        $$ = data_append_byte($1, $2);
 278                }
 279        | bytestring DT_LABEL
 280                {
 281                        $$ = data_add_marker($1, LABEL, $2);
 282                }
 283        ;
 284
 285subnodes:
 286          /* empty */
 287                {
 288                        $$ = NULL;
 289                }
 290        | subnode subnodes
 291                {
 292                        $$ = chain_node($1, $2);
 293                }
 294        | subnode propdef
 295                {
 296                        print_error("syntax error: properties must precede subnodes");
 297                        YYERROR;
 298                }
 299        ;
 300
 301subnode:
 302          DT_PROPNODENAME nodedef
 303                {
 304                        $$ = name_node($2, $1);
 305                }
 306        | DT_LABEL subnode
 307                {
 308                        add_label(&$2->labels, $1);
 309                        $$ = $2;
 310                }
 311        ;
 312
 313%%
 314
 315void print_error(char const *fmt, ...)
 316{
 317        va_list va;
 318
 319        va_start(va, fmt);
 320        srcpos_verror(&yylloc, fmt, va);
 321        va_end(va);
 322
 323        treesource_error = 1;
 324}
 325
 326void yyerror(char const *s) {
 327        print_error("%s", s);
 328}
 329
 330static unsigned long long eval_literal(const char *s, int base, int bits)
 331{
 332        unsigned long long val;
 333        char *e;
 334
 335        errno = 0;
 336        val = strtoull(s, &e, base);
 337        if (*e)
 338                print_error("bad characters in literal");
 339        else if ((errno == ERANGE)
 340                 || ((bits < 64) && (val >= (1ULL << bits))))
 341                print_error("literal out of range");
 342        else if (errno != 0)
 343                print_error("bad literal");
 344        return val;
 345}
 346
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.