aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Kbuild.include14
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.asm-generic2
-rw-r--r--scripts/Makefile.build11
-rw-r--r--scripts/Makefile.headersinst52
-rw-r--r--scripts/Makefile.modinst4
-rw-r--r--scripts/Makefile.modpost2
-rw-r--r--scripts/asn1_compiler.c1545
-rwxr-xr-xscripts/checkpatch.pl37
-rwxr-xr-xscripts/coccicheck3
-rw-r--r--scripts/coccinelle/api/ptr_ret.cocci26
-rw-r--r--scripts/coccinelle/tests/odd_ptr_err.cocci65
-rw-r--r--scripts/dtc/Makefile.dtc13
-rw-r--r--scripts/dtc/checks.c203
-rw-r--r--scripts/dtc/data.c124
-rw-r--r--scripts/dtc/dtc-lexer.l65
-rw-r--r--scripts/dtc/dtc-lexer.lex.c_shipped503
-rw-r--r--scripts/dtc/dtc-parser.tab.c_shipped780
-rw-r--r--scripts/dtc/dtc-parser.tab.h_shipped47
-rw-r--r--scripts/dtc/dtc-parser.y255
-rw-r--r--scripts/dtc/dtc.c21
-rw-r--r--scripts/dtc/dtc.h31
-rw-r--r--scripts/dtc/fdtdump.c162
-rw-r--r--scripts/dtc/fdtget.c366
-rw-r--r--scripts/dtc/fdtput.c362
-rw-r--r--scripts/dtc/flattree.c3
-rw-r--r--scripts/dtc/libfdt/Makefile.libfdt6
-rw-r--r--scripts/dtc/libfdt/fdt.c61
-rw-r--r--scripts/dtc/libfdt/fdt_empty_tree.c84
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c275
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c29
-rw-r--r--scripts/dtc/libfdt/fdt_sw.c11
-rw-r--r--scripts/dtc/libfdt/fdt_wip.c41
-rw-r--r--scripts/dtc/libfdt/libfdt.h440
-rw-r--r--scripts/dtc/libfdt/libfdt_env.h16
-rw-r--r--scripts/dtc/libfdt/libfdt_internal.h2
-rw-r--r--scripts/dtc/livetree.c128
-rw-r--r--scripts/dtc/srcpos.c98
-rw-r--r--scripts/dtc/srcpos.h31
-rw-r--r--scripts/dtc/treesource.c2
-rw-r--r--scripts/dtc/util.c272
-rw-r--r--scripts/dtc/util.h97
-rw-r--r--scripts/gcc-version.sh6
-rw-r--r--scripts/gcc-x86_32-has-stack-protector.sh2
-rw-r--r--scripts/gcc-x86_64-has-stack-protector.sh2
-rw-r--r--scripts/headers_install.pl14
-rw-r--r--scripts/kconfig/Makefile12
-rwxr-xr-xscripts/kconfig/check.sh2
-rw-r--r--scripts/kconfig/conf.c25
-rw-r--r--scripts/kconfig/expr.h11
-rw-r--r--scripts/kconfig/lkc_proto.h6
-rw-r--r--scripts/kconfig/lxdialog/check-lxdialog.sh2
-rw-r--r--scripts/kconfig/lxdialog/dialog.h9
-rw-r--r--scripts/kconfig/lxdialog/textbox.c171
-rw-r--r--scripts/kconfig/lxdialog/util.c7
-rw-r--r--scripts/kconfig/mconf.c123
-rw-r--r--scripts/kconfig/menu.c53
-rw-r--r--scripts/kconfig/nconf.c2
-rw-r--r--scripts/kconfig/streamline_config.pl50
-rwxr-xr-xscripts/kernel-doc296
-rw-r--r--scripts/mod/file2alias.c15
-rw-r--r--scripts/mod/modpost.c3
-rw-r--r--scripts/package/buildtar8
-rw-r--r--scripts/recordmcount.h4
-rwxr-xr-xscripts/sign-file429
-rw-r--r--scripts/sortextable.c10
-rwxr-xr-xscripts/tags.sh8
68 files changed, 6632 insertions, 930 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 65f362d931b..fb070fa1038 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -10,3 +10,4 @@ ihex2fw
recordmcount
docproc
sortextable
+asn1_compiler
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 6a3ee981931..978416dd31c 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -98,24 +98,24 @@ try-run = $(shell set -e; \
# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
as-option = $(call try-run,\
- $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
# as-instr
# Usage: cflags-y += $(call as-instr,instr,option1,option2)
as-instr = $(call try-run,\
- printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
+ printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
cc-option = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
cc-option-yn = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
@@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\
# cc-disable-warning
# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
cc-disable-warning = $(call try-run,\
- $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+ $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
# cc-version
# Usage gcc-ver := $(call cc-version)
@@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
# cc-ldoption
# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
cc-ldoption = $(call try-run,\
- $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
+ $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
# ld-option
# Usage: LDFLAGS += $(call ld-option, -X)
@@ -209,7 +209,7 @@ endif
# >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...']
# in $(cmd_xxx) double $$ your perl vars
-make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
+make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
# Find any prerequisites that is newer than target or that does not exist.
# PHONY targets skipped in both cases.
diff --git a/scripts/Makefile b/scripts/Makefile
index a55b0067758..01e7adb838d 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash
hostprogs-$(CONFIG_IKCONFIG) += bin2c
hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
+hostprogs-$(CONFIG_ASN1) += asn1_compiler
HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
+HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
always := $(hostprogs-y) $(hostprogs-m)
diff --git a/scripts/Makefile.asm-generic b/scripts/Makefile.asm-generic
index 40caf3c26cd..d17e0ea911e 100644
--- a/scripts/Makefile.asm-generic
+++ b/scripts/Makefile.asm-generic
@@ -5,7 +5,7 @@
# and for each file listed in this file with generic-y creates
# a small wrapper file in $(obj) (arch/$(SRCARCH)/include/generated/asm)
-kbuild-file := $(srctree)/arch/$(SRCARCH)/include/asm/Kbuild
+kbuild-file := $(srctree)/arch/$(SRCARCH)/include/$(src)/Kbuild
-include $(kbuild-file)
include scripts/Kbuild.include
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index ff1720d28d0..0e801c3cdaf 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@
$(obj)/%.lds: $(src)/%.lds.S FORCE
$(call if_changed_dep,cpp_lds_S)
+# ASN.1 grammar
+# ---------------------------------------------------------------------------
+quiet_cmd_asn1_compiler = ASN.1 $@
+ cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
+ $(subst .h,.c,$@) $(subst .c,.h,$@)
+
+.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
+
+$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
+ $(call cmd,asn1_compiler)
+
# Build the compiled-in targets
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index d3bae5e7b60..06ba4a70bd4 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -3,13 +3,12 @@
#
# header-y - list files to be installed. They are preprocessed
# to remove __KERNEL__ section of the file
-# objhdr-y - Same as header-y but for generated files
-# genhdr-y - Same as objhdr-y but in a generated/ directory
+# genhdr-y - Same as header-y but in a generated/ directory
#
# ==========================================================================
# called may set destination dir (when installing to asm/)
-_dst := $(if $(dst),$(dst),$(obj))
+_dst := $(or $(destination-y),$(dst),$(obj))
# generated header directory
gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
@@ -17,49 +16,64 @@ gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
kbuild-file := $(srctree)/$(obj)/Kbuild
include $(kbuild-file)
-_dst := $(if $(destination-y),$(destination-y),$(_dst))
+old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
+ifneq ($(wildcard $(old-kbuild-file)),)
+include $(old-kbuild-file)
+endif
include scripts/Kbuild.include
-install := $(INSTALL_HDR_PATH)/$(_dst)
+installdir := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst))
header-y := $(sort $(header-y))
subdirs := $(patsubst %/,%,$(filter %/, $(header-y)))
header-y := $(filter-out %/, $(header-y))
# files used to track state of install/check
-install-file := $(install)/.install
-check-file := $(install)/.check
+install-file := $(installdir)/.install
+check-file := $(installdir)/.check
# generic-y list all files an architecture uses from asm-generic
# Use this to build a list of headers which require a wrapper
wrapper-files := $(filter $(header-y), $(generic-y))
+srcdir := $(srctree)/$(obj)
+gendir := $(objtree)/$(gen)
+
+oldsrcdir := $(srctree)/$(subst /uapi,,$(obj))
+
# all headers files for this dir
header-y := $(filter-out $(generic-y), $(header-y))
-all-files := $(header-y) $(objhdr-y) $(genhdr-y) $(wrapper-files)
-input-files := $(addprefix $(srctree)/$(obj)/,$(header-y)) \
- $(addprefix $(objtree)/$(obj)/,$(objhdr-y)) \
- $(addprefix $(objtree)/$(gen)/,$(genhdr-y))
-output-files := $(addprefix $(install)/, $(all-files))
+all-files := $(header-y) $(genhdr-y) $(wrapper-files)
+output-files := $(addprefix $(installdir)/, $(all-files))
+
+input-files := $(foreach hdr, $(header-y), \
+ $(or \
+ $(wildcard $(srcdir)/$(hdr)), \
+ $(wildcard $(oldsrcdir)/$(hdr)), \
+ $(error Missing UAPI file $(srcdir)/$(hdr)) \
+ )) \
+ $(foreach hdr, $(genhdr-y), \
+ $(or \
+ $(wildcard $(gendir)/$(hdr)), \
+ $(error Missing generated UAPI file $(gendir)/$(hdr)) \
+ ))
# Work out what needs to be removed
-oldheaders := $(patsubst $(install)/%,%,$(wildcard $(install)/*.h))
+oldheaders := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
unwanted := $(filter-out $(all-files),$(oldheaders))
# Prefix unwanted with full paths to $(INSTALL_HDR_PATH)
-unwanted-file := $(addprefix $(install)/, $(unwanted))
+unwanted-file := $(addprefix $(installdir)/, $(unwanted))
printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
file$(if $(word 2, $(all-files)),s))
cmd_install = \
- $(PERL) $< $(srctree)/$(obj) $(install) $(SRCARCH) $(header-y); \
- $(PERL) $< $(objtree)/$(obj) $(install) $(SRCARCH) $(objhdr-y); \
- $(PERL) $< $(objtree)/$(gen) $(install) $(SRCARCH) $(genhdr-y); \
+ $(PERL) $< $(installdir) $(SRCARCH) $(input-files); \
for F in $(wrapper-files); do \
- echo "\#include <asm-generic/$$F>" > $(install)/$$F; \
+ echo "\#include <asm-generic/$$F>" > $(installdir)/$$F; \
done; \
touch $@
@@ -70,7 +84,7 @@ quiet_cmd_check = CHECK $(printdir) ($(words $(all-files)) files)
# Headers list can be pretty long, xargs helps to avoid
# the "Argument list too long" error.
cmd_check = for f in $(all-files); do \
- echo "$(install)/$${f}"; done \
+ echo "$(installdir)/$${f}"; done \
| xargs \
$(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
touch $@
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index efa5d940e63..dda4b2b6192 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -9,7 +9,7 @@ include scripts/Kbuild.include
#
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
PHONY += $(modules)
@@ -17,7 +17,7 @@ __modinst: $(modules)
@:
quiet_cmd_modules_install = INSTALL $@
- cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@)
+ cmd_modules_install = mkdir -p $(2); cp $@ $(2) ; $(mod_strip_cmd) $(2)/$(notdir $@) ; $(mod_sign_cmd) $(2)/$(notdir $@)
# Modules built outside the kernel source tree go into extra by default
INSTALL_MOD_DIR ?= extra
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 08dce14f2dc..a1cb0222ebe 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -60,7 +60,7 @@ kernelsymfile := $(objtree)/Module.symvers
modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
# Step 1), find all modules listed in $(MODVERDIR)/
-__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
+__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
new file mode 100644
index 00000000000..db0e5cd34c7
--- /dev/null
+++ b/scripts/asn1_compiler.c
@@ -0,0 +1,1545 @@
+/* Simplified ASN.1 notation parser
+ *
+ * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <linux/asn1_ber_bytecode.h>
+
+enum token_type {
+ DIRECTIVE_ABSENT,
+ DIRECTIVE_ALL,
+ DIRECTIVE_ANY,
+ DIRECTIVE_APPLICATION,
+ DIRECTIVE_AUTOMATIC,
+ DIRECTIVE_BEGIN,
+ DIRECTIVE_BIT,
+ DIRECTIVE_BMPString,
+ DIRECTIVE_BOOLEAN,
+ DIRECTIVE_BY,
+ DIRECTIVE_CHARACTER,
+ DIRECTIVE_CHOICE,
+ DIRECTIVE_CLASS,
+ DIRECTIVE_COMPONENT,
+ DIRECTIVE_COMPONENTS,
+ DIRECTIVE_CONSTRAINED,
+ DIRECTIVE_CONTAINING,
+ DIRECTIVE_DEFAULT,
+ DIRECTIVE_DEFINED,
+ DIRECTIVE_DEFINITIONS,
+ DIRECTIVE_EMBEDDED,
+ DIRECTIVE_ENCODED,
+ DIRECTIVE_ENCODING_CONTROL,
+ DIRECTIVE_END,
+ DIRECTIVE_ENUMERATED,
+ DIRECTIVE_EXCEPT,
+ DIRECTIVE_EXPLICIT,
+ DIRECTIVE_EXPORTS,
+ DIRECTIVE_EXTENSIBILITY,
+ DIRECTIVE_EXTERNAL,
+ DIRECTIVE_FALSE,
+ DIRECTIVE_FROM,
+ DIRECTIVE_GeneralString,
+ DIRECTIVE_GeneralizedTime,
+ DIRECTIVE_GraphicString,
+ DIRECTIVE_IA5String,
+ DIRECTIVE_IDENTIFIER,
+ DIRECTIVE_IMPLICIT,
+ DIRECTIVE_IMPLIED,
+ DIRECTIVE_IMPORTS,
+ DIRECTIVE_INCLUDES,
+ DIRECTIVE_INSTANCE,
+ DIRECTIVE_INSTRUCTIONS,
+ DIRECTIVE_INTEGER,
+ DIRECTIVE_INTERSECTION,
+ DIRECTIVE_ISO646String,
+ DIRECTIVE_MAX,
+ DIRECTIVE_MIN,
+ DIRECTIVE_MINUS_INFINITY,
+ DIRECTIVE_NULL,
+ DIRECTIVE_NumericString,
+ DIRECTIVE_OBJECT,
+ DIRECTIVE_OCTET,
+ DIRECTIVE_OF,
+ DIRECTIVE_OPTIONAL,
+ DIRECTIVE_ObjectDescriptor,
+ DIRECTIVE_PATTERN,
+ DIRECTIVE_PDV,
+ DIRECTIVE_PLUS_INFINITY,
+ DIRECTIVE_PRESENT,
+ DIRECTIVE_PRIVATE,
+ DIRECTIVE_PrintableString,
+ DIRECTIVE_REAL,
+ DIRECTIVE_RELATIVE_OID,
+ DIRECTIVE_SEQUENCE,
+ DIRECTIVE_SET,
+ DIRECTIVE_SIZE,
+ DIRECTIVE_STRING,
+ DIRECTIVE_SYNTAX,
+ DIRECTIVE_T61String,
+ DIRECTIVE_TAGS,
+ DIRECTIVE_TRUE,
+ DIRECTIVE_TeletexString,
+ DIRECTIVE_UNION,
+ DIRECTIVE_UNIQUE,
+ DIRECTIVE_UNIVERSAL,
+ DIRECTIVE_UTCTime,
+ DIRECTIVE_UTF8String,
+ DIRECTIVE_UniversalString,
+ DIRECTIVE_VideotexString,
+ DIRECTIVE_VisibleString,
+ DIRECTIVE_WITH,
+ NR__DIRECTIVES,
+ TOKEN_ASSIGNMENT = NR__DIRECTIVES,
+ TOKEN_OPEN_CURLY,
+ TOKEN_CLOSE_CURLY,
+ TOKEN_OPEN_SQUARE,
+ TOKEN_CLOSE_SQUARE,
+ TOKEN_OPEN_ACTION,
+ TOKEN_CLOSE_ACTION,
+ TOKEN_COMMA,
+ TOKEN_NUMBER,
+ TOKEN_TYPE_NAME,
+ TOKEN_ELEMENT_NAME,
+ NR__TOKENS
+};
+
+static const unsigned char token_to_tag[NR__TOKENS] = {
+ /* EOC goes first */
+ [DIRECTIVE_BOOLEAN] = ASN1_BOOL,
+ [DIRECTIVE_INTEGER] = ASN1_INT,
+ [DIRECTIVE_BIT] = ASN1_BTS,
+ [DIRECTIVE_OCTET] = ASN1_OTS,
+ [DIRECTIVE_NULL] = ASN1_NULL,
+ [DIRECTIVE_OBJECT] = ASN1_OID,
+ [DIRECTIVE_ObjectDescriptor] = ASN1_ODE,
+ [DIRECTIVE_EXTERNAL] = ASN1_EXT,
+ [DIRECTIVE_REAL] = ASN1_REAL,
+ [DIRECTIVE_ENUMERATED] = ASN1_ENUM,
+ [DIRECTIVE_EMBEDDED] = 0,
+ [DIRECTIVE_UTF8String] = ASN1_UTF8STR,
+ [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID,
+ /* 14 */
+ /* 15 */
+ [DIRECTIVE_SEQUENCE] = ASN1_SEQ,
+ [DIRECTIVE_SET] = ASN1_SET,
+ [DIRECTIVE_NumericString] = ASN1_NUMSTR,
+ [DIRECTIVE_PrintableString] = ASN1_PRNSTR,
+ [DIRECTIVE_T61String] = ASN1_TEXSTR,
+ [DIRECTIVE_TeletexString] = ASN1_TEXSTR,
+ [DIRECTIVE_VideotexString] = ASN1_VIDSTR,
+ [DIRECTIVE_IA5String] = ASN1_IA5STR,
+ [DIRECTIVE_UTCTime] = ASN1_UNITIM,
+ [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM,
+ [DIRECTIVE_GraphicString] = ASN1_GRASTR,
+ [DIRECTIVE_VisibleString] = ASN1_VISSTR,
+ [DIRECTIVE_GeneralString] = ASN1_GENSTR,
+ [DIRECTIVE_UniversalString] = ASN1_UNITIM,
+ [DIRECTIVE_CHARACTER] = ASN1_CHRSTR,
+ [DIRECTIVE_BMPString] = ASN1_BMPSTR,
+};
+
+static const char asn1_classes[4][5] = {
+ [ASN1_UNIV] = "UNIV",
+ [ASN1_APPL] = "APPL",
+ [ASN1_CONT] = "CONT",
+ [ASN1_PRIV] = "PRIV"
+};
+
+static const char asn1_methods[2][5] = {
+ [ASN1_UNIV] = "PRIM",
+ [ASN1_APPL] = "CONS"
+};
+
+static const char *const asn1_universal_tags[32] = {
+ "EOC",
+ "BOOL",
+ "INT",
+ "BTS",
+ "OTS",
+ "NULL",
+ "OID",
+ "ODE",
+ "EXT",
+ "REAL",
+ "ENUM",
+ "EPDV",
+ "UTF8STR",
+ "RELOID",
+ NULL, /* 14 */
+ NULL, /* 15 */
+ "SEQ",
+ "SET",
+ "NUMSTR",
+ "PRNSTR",
+ "TEXSTR",
+ "VIDSTR",
+ "IA5STR",
+ "UNITIM",
+ "GENTIM",
+ "GRASTR",
+ "VISSTR",
+ "GENSTR",
+ "UNISTR",
+ "CHRSTR",
+ "BMPSTR",
+ NULL /* 31 */
+};
+
+static const char *filename;
+static const char *grammar_name;
+static const char *outputname;
+static const char *headername;
+
+static const char *const directives[NR__DIRECTIVES] = {
+#define _(X) [DIRECTIVE_##X] = #X
+ _(ABSENT),
+ _(ALL),
+ _(ANY),
+ _(APPLICATION),
+ _(AUTOMATIC),
+ _(BEGIN),
+ _(BIT),
+ _(BMPString),
+ _(BOOLEAN),
+ _(BY),
+ _(CHARACTER),
+ _(CHOICE),
+ _(CLASS),
+ _(COMPONENT),
+ _(COMPONENTS),
+ _(CONSTRAINED),
+ _(CONTAINING),
+ _(DEFAULT),
+ _(DEFINED),
+ _(DEFINITIONS),
+ _(EMBEDDED),
+ _(ENCODED),
+ [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
+ _(END),
+ _(ENUMERATED),
+ _(EXCEPT),
+ _(EXPLICIT),
+ _(EXPORTS),
+ _(EXTENSIBILITY),
+ _(EXTERNAL),
+ _(FALSE),
+ _(FROM),
+ _(GeneralString),
+ _(GeneralizedTime),
+ _(GraphicString),
+ _(IA5String),
+ _(IDENTIFIER),
+ _(IMPLICIT),
+ _(IMPLIED),
+ _(IMPORTS),
+ _(INCLUDES),
+ _(INSTANCE),
+ _(INSTRUCTIONS),
+ _(INTEGER),
+ _(INTERSECTION),
+ _(ISO646String),
+ _(MAX),
+ _(MIN),
+ [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
+ [DIRECTIVE_NULL] = "NULL",
+ _(NumericString),
+ _(OBJECT),
+ _(OCTET),
+ _(OF),
+ _(OPTIONAL),
+ _(ObjectDescriptor),
+ _(PATTERN),
+ _(PDV),
+ [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
+ _(PRESENT),
+ _(PRIVATE),
+ _(PrintableString),
+ _(REAL),
+ [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
+ _(SEQUENCE),
+ _(SET),
+ _(SIZE),
+ _(STRING),
+ _(SYNTAX),
+ _(T61String),
+ _(TAGS),
+ _(TRUE),
+ _(TeletexString),
+ _(UNION),
+ _(UNIQUE),
+ _(UNIVERSAL),
+ _(UTCTime),
+ _(UTF8String),
+ _(UniversalString),
+ _(VideotexString),
+ _(VisibleString),
+ _(WITH)
+};
+
+struct action {
+ struct action *next;
+ unsigned char index;
+ char name[];
+};
+
+static struct action *action_list;
+static unsigned nr_actions;
+
+struct token {
+ unsigned short line;
+ enum token_type token_type : 8;
+ unsigned char size;
+ struct action *action;
+ const char *value;
+ struct type *type;
+};
+
+static struct token *token_list;
+static unsigned nr_tokens;
+
+static int directive_compare(const void *_key, const void *_pdir)
+{
+ const struct token *token = _key;
+ const char *const *pdir = _pdir, *dir = *pdir;
+ size_t dlen, clen;
+ int val;
+
+ dlen = strlen(dir);
+ clen = (dlen < token->size) ? dlen : token->size;
+
+ //printf("cmp(%*.*s,%s) = ",
+ // (int)token->size, (int)token->size, token->value,
+ // dir);
+
+ val = memcmp(token->value, dir, clen);
+ if (val != 0) {
+ //printf("%d [cmp]\n", val);
+ return val;
+ }
+
+ if (dlen == token->size) {
+ //printf("0\n");
+ return 0;
+ }
+ //printf("%d\n", (int)dlen - (int)token->size);
+ return dlen - token->size; /* shorter -> negative */
+}
+
+/*
+ * Tokenise an ASN.1 grammar
+ */
+static void tokenise(char *buffer, char *end)
+{
+ struct token *tokens;
+ char *line, *nl, *p, *q;
+ unsigned tix, lineno;
+
+ /* Assume we're going to have half as many tokens as we have
+ * characters
+ */
+ token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
+ if (!tokens) {
+ perror(NULL);
+ exit(1);
+ }
+ tix = 0;
+
+ lineno = 0;
+ while (buffer < end) {
+ /* First of all, break out a line */
+ lineno++;
+ line = buffer;
+ nl = memchr(line, '\n', end - buffer);
+ if (!nl) {
+ buffer = nl = end;
+ } else {
+ buffer = nl + 1;
+ *nl = '\0';
+ }
+
+ /* Remove "--" comments */
+ p = line;
+ next_comment:
+ while ((p = memchr(p, '-', nl - p))) {
+ if (p[1] == '-') {
+ /* Found a comment; see if there's a terminator */
+ q = p + 2;
+ while ((q = memchr(q, '-', nl - q))) {
+ if (q[1] == '-') {
+ /* There is - excise the comment */
+ q += 2;
+ memmove(p, q, nl - q);
+ goto next_comment;
+ }
+ q++;
+ }
+ *p = '\0';
+ nl = p;
+ break;
+ } else {
+ p++;
+ }
+ }
+
+ p = line;
+ while (p < nl) {
+ /* Skip white space */
+ while (p < nl && isspace(*p))
+ *(p++) = 0;
+ if (p >= nl)
+ break;
+
+ tokens[tix].line = lineno;
+ tokens[tix].value = p;
+
+ /* Handle string tokens */
+ if (isalpha(*p)) {
+ const char **dir;
+
+ /* Can be a directive, type name or element
+ * name. Find the end of the name.
+ */
+ q = p + 1;
+ while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
+ q++;
+ tokens[tix].size = q - p;
+ p = q;
+
+ /* If it begins with a lowercase letter then
+ * it's an element name
+ */
+ if (islower(tokens[tix].value[0])) {
+ tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
+ continue;
+ }
+
+ /* Otherwise we need to search the directive
+ * table
+ */
+ dir = bsearch(&tokens[tix], directives,
+ sizeof(directives) / sizeof(directives[1]),
+ sizeof(directives[1]),
+ directive_compare);
+ if (dir) {
+ tokens[tix++].token_type = dir - directives;
+ continue;
+ }
+
+ tokens[tix++].token_type = TOKEN_TYPE_NAME;
+ continue;
+ }
+
+ /* Handle numbers */
+ if (isdigit(*p)) {
+ /* Find the end of the number */
+ q = p + 1;
+ while (q < nl && (isdigit(*q)))
+ q++;
+ tokens[tix].size = q - p;
+ p = q;
+ tokens[tix++].token_type = TOKEN_NUMBER;
+ continue;
+ }
+
+ if (nl - p >= 3) {
+ if (memcmp(p, "::=", 3) == 0) {
+ p += 3;
+ tokens[tix].size = 3;
+ tokens[tix++].token_type = TOKEN_ASSIGNMENT;
+ continue;
+ }
+ }
+
+ if (nl - p >= 2) {
+ if (memcmp(p, "({", 2) == 0) {
+ p += 2;
+ tokens[tix].size = 2;
+ tokens[tix++].token_type = TOKEN_OPEN_ACTION;
+ continue;
+ }
+ if (memcmp(p, "})", 2) == 0) {
+ p += 2;
+ tokens[tix].size = 2;
+ tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
+ continue;
+ }
+ }
+
+ if (nl - p >= 1) {
+ tokens[tix].size = 1;
+ switch (*p) {
+ case '{':
+ p += 1;
+ tokens[tix++].token_type = TOKEN_OPEN_CURLY;
+ continue;
+ case '}':
+ p += 1;
+ tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
+ continue;
+ case '[':
+ p += 1;
+ tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
+ continue;
+ case ']':
+ p += 1;
+ tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
+ continue;
+ case ',':
+ p += 1;
+ tokens[tix++].token_type = TOKEN_COMMA;
+ continue;
+ default:
+ break;
+ }
+ }
+
+ fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
+ filename, lineno, *p);
+ exit(1);
+ }
+ }
+
+ nr_tokens = tix;
+ printf("Extracted %u tokens\n", nr_tokens);
+
+#if 0
+ {
+ int n;
+ for (n = 0; n < nr_tokens; n++)
+ printf("Token %3u: '%*.*s'\n",
+ n,
+ (int)token_list[n].size, (int)token_list[n].size,
+ token_list[n].value);
+ }
+#endif
+}
+
+static void build_type_list(void);
+static void parse(void);
+static void render(FILE *out, FILE *hdr);
+
+/*
+ *
+ */
+int main(int argc, char **argv)
+{
+ struct stat st;
+ ssize_t readlen;
+ FILE *out, *hdr;
+ char *buffer, *p;
+ int fd;
+
+ if (argc != 4) {
+ fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
+ argv[0]);
+ exit(2);
+ }
+
+ filename = argv[1];
+ outputname = argv[2];
+ headername = argv[3];
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ if (fstat(fd, &st) < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ if (!(buffer = malloc(st.st_size + 1))) {
+ perror(NULL);
+ exit(1);
+ }
+
+ if ((readlen = read(fd, buffer, st.st_size)) < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ if (close(fd) < 0) {
+ perror(filename);
+ exit(1);
+ }
+
+ if (readlen != st.st_size) {
+ fprintf(stderr, "%s: Short read\n", filename);
+ exit(1);
+ }
+
+ p = strrchr(argv[1], '/');
+ p = p ? p + 1 : argv[1];
+ grammar_name = strdup(p);
+ if (!p) {
+ perror(NULL);
+ exit(1);
+ }
+ p = strchr(grammar_name, '.');
+ if (p)
+ *p = '\0';
+
+ buffer[readlen] = 0;
+ tokenise(buffer, buffer + readlen);
+ build_type_list();
+ parse();
+
+ out = fopen(outputname, "w");
+ if (!out) {
+ perror(outputname);
+ exit(1);
+ }
+
+ hdr = fopen(headername, "w");
+ if (!out) {
+ perror(headername);
+ exit(1);
+ }
+
+ render(out, hdr);
+
+ if (fclose(out) < 0) {
+ perror(outputname);
+ exit(1);
+ }
+
+ if (fclose(hdr) < 0) {
+ perror(headername);
+ exit(1);
+ }
+
+ return 0;
+}
+
+enum compound {
+ NOT_COMPOUND,
+ SET,
+ SET_OF,
+ SEQUENCE,
+ SEQUENCE_OF,
+ CHOICE,
+ ANY,
+ TYPE_REF,
+ TAG_OVERRIDE
+};
+
+struct element {
+ struct type *type_def;
+ struct token *name;
+ struct token *type;
+ struct action *action;
+ struct element *children;
+ struct element *next;
+ struct element *render_next;
+ struct element *list_next;
+ uint8_t n_elements;
+ enum compound compound : 8;
+ enum asn1_class class : 8;
+ enum asn1_method method : 8;
+ uint8_t tag;
+ unsigned entry_index;
+ unsigned flags;
+#define ELEMENT_IMPLICIT 0x0001
+#define ELEMENT_EXPLICIT 0x0002
+#define ELEMENT_MARKED 0x0004
+#define ELEMENT_RENDERED 0x0008
+#define ELEMENT_SKIPPABLE 0x0010
+#define ELEMENT_CONDITIONAL 0x0020
+};
+
+struct type {
+ struct token *name;
+ struct token *def;
+ struct element *element;
+ unsigned ref_count;
+ unsigned flags;
+#define TYPE_STOP_MARKER 0x0001
+#define TYPE_BEGIN 0x0002
+};
+
+static struct type *type_list;
+static struct type **type_index;
+static unsigned nr_types;
+
+static int type_index_compare(const void *_a, const void *_b)
+{
+ const struct type *const *a = _a, *const *b = _b;
+
+ if ((*a)->name->size != (*b)->name->size)
+ return (*a)->name->size - (*b)->name->size;
+ else
+ return memcmp((*a)->name->value, (*b)->name->value,
+ (*a)->name->size);
+}
+
+static int type_finder(const void *_key, const void *_ti)
+{
+ const struct token *token = _key;
+ const struct type *const *ti = _ti;
+ const struct type *type = *ti;
+
+ if (token->size != type->name->size)
+ return token->size - type->name->size;
+ else
+ return memcmp(token->value, type->name->value,
+ token->size);
+}
+
+/*
+ * Build up a list of types and a sorted index to that list.
+ */
+static void build_type_list(void)
+{
+ struct type *types;
+ unsigned nr, t, n;
+
+ nr = 0;
+ for (n = 0; n < nr_tokens - 1; n++)
+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
+ nr++;
+
+ if (nr == 0) {
+ fprintf(stderr, "%s: No defined types\n", filename);
+ exit(1);
+ }
+
+ nr_types = nr;
+ types = type_list = calloc(nr + 1, sizeof(type_list[0]));
+ if (!type_list) {
+ perror(NULL);
+ exit(1);
+ }
+ type_index = calloc(nr, sizeof(type_index[0]));
+ if (!type_index) {
+ perror(NULL);
+ exit(1);
+ }
+
+ t = 0;
+ types[t].flags |= TYPE_BEGIN;
+ for (n = 0; n < nr_tokens - 1; n++) {
+ if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
+ token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
+ types[t].name = &token_list[n];
+ type_index[t] = &types[t];
+ t++;
+ }
+ }
+ types[t].name = &token_list[n + 1];
+ types[t].flags |= TYPE_STOP_MARKER;
+
+ qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
+
+ printf("Extracted %u types\n", nr_types);
+#if 0
+ for (n = 0; n < nr_types; n++) {
+ struct type *type = type_index[n];
+ printf("- %*.*s\n",
+ (int)type->name->size,
+ (int)type->name->size,
+ type->name->value);
+ }
+#endif
+}
+
+static struct element *parse_type(struct token **_cursor, struct token *stop,
+ struct token *name);
+
+/*
+ * Parse the token stream
+ */
+static void parse(void)
+{
+ struct token *cursor;
+ struct type *type;
+
+ /* Parse one type definition statement at a time */
+ type = type_list;
+ do {
+ cursor = type->name;
+
+ if (cursor[0].token_type != TOKEN_TYPE_NAME ||
+ cursor[1].token_type != TOKEN_ASSIGNMENT)
+ abort();
+ cursor += 2;
+
+ type->element = parse_type(&cursor, type[1].name, NULL);
+ type->element->type_def = type;
+
+ if (cursor != type[1].name) {
+ fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+
+ } while (type++, !(type->flags & TYPE_STOP_MARKER));
+
+ printf("Extracted %u actions\n", nr_actions);
+}
+
+static struct element *element_list;
+
+static struct element *alloc_elem(struct token *type)
+{
+ struct element *e = calloc(1, sizeof(*e));
+ if (!e) {
+ perror(NULL);
+ exit(1);
+ }
+ e->list_next = element_list;
+ element_list = e;
+ return e;
+}
+
+static struct element *parse_compound(struct token **_cursor, struct token *end,
+ int alternates);
+
+/*
+ * Parse one type definition statement
+ */
+static struct element *parse_type(struct token **_cursor, struct token *end,
+ struct token *name)
+{
+ struct element *top, *element;
+ struct action *action, **ppaction;
+ struct token *cursor = *_cursor;
+ struct type **ref;
+ char *p;
+ int labelled = 0, implicit = 0;
+
+ top = element = alloc_elem(cursor);
+ element->class = ASN1_UNIV;
+ element->method = ASN1_PRIM;
+ element->tag = token_to_tag[cursor->token_type];
+ element->name = name;
+
+ /* Extract the tag value if one given */
+ if (cursor->token_type == TOKEN_OPEN_SQUARE) {
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ switch (cursor->token_type) {
+ case DIRECTIVE_UNIVERSAL:
+ element->class = ASN1_UNIV;
+ cursor++;
+ break;
+ case DIRECTIVE_APPLICATION:
+ element->class = ASN1_APPL;
+ cursor++;
+ break;
+ case TOKEN_NUMBER:
+ element->class = ASN1_CONT;
+ break;
+ case DIRECTIVE_PRIVATE:
+ element->class = ASN1_PRIV;
+ cursor++;
+ break;
+ default:
+ fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != TOKEN_NUMBER) {
+ fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+
+ element->tag &= ~0x1f;
+ element->tag |= strtoul(cursor->value, &p, 10);
+ if (p - cursor->value != cursor->size)
+ abort();
+ cursor++;
+
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
+ fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ labelled = 1;
+ }
+
+ /* Handle implicit and explicit markers */
+ if (cursor->token_type == DIRECTIVE_IMPLICIT) {
+ element->flags |= ELEMENT_IMPLICIT;
+ implicit = 1;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
+ element->flags |= ELEMENT_EXPLICIT;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ }
+
+ if (labelled) {
+ if (!implicit)
+ element->method |= ASN1_CONS;
+ element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
+ element->children = alloc_elem(cursor);
+ element = element->children;
+ element->class = ASN1_UNIV;
+ element->method = ASN1_PRIM;
+ element->tag = token_to_tag[cursor->token_type];
+ element->name = name;
+ }
+
+ /* Extract the type we're expecting here */
+ element->type = cursor;
+ switch (cursor->token_type) {
+ case DIRECTIVE_ANY:
+ element->compound = ANY;
+ cursor++;
+ break;
+
+ case DIRECTIVE_NULL:
+ case DIRECTIVE_BOOLEAN:
+ case DIRECTIVE_ENUMERATED:
+ case DIRECTIVE_INTEGER:
+ element->compound = NOT_COMPOUND;
+ cursor++;
+ break;
+
+ case DIRECTIVE_EXTERNAL:
+ element->method = ASN1_CONS;
+
+ case DIRECTIVE_BMPString:
+ case DIRECTIVE_GeneralString:
+ case DIRECTIVE_GraphicString:
+ case DIRECTIVE_IA5String:
+ case DIRECTIVE_ISO646String:
+ case DIRECTIVE_NumericString:
+ case DIRECTIVE_PrintableString:
+ case DIRECTIVE_T61String:
+ case DIRECTIVE_TeletexString:
+ case DIRECTIVE_UniversalString:
+ case DIRECTIVE_UTF8String:
+ case DIRECTIVE_VideotexString:
+ case DIRECTIVE_VisibleString:
+ case DIRECTIVE_ObjectDescriptor:
+ case DIRECTIVE_GeneralizedTime:
+ case DIRECTIVE_UTCTime:
+ element->compound = NOT_COMPOUND;
+ cursor++;
+ break;
+
+ case DIRECTIVE_BIT:
+ case DIRECTIVE_OCTET:
+ element->compound = NOT_COMPOUND;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != DIRECTIVE_STRING)
+ goto parse_error;
+ cursor++;
+ break;
+
+ case DIRECTIVE_OBJECT:
+ element->compound = NOT_COMPOUND;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != DIRECTIVE_IDENTIFIER)
+ goto parse_error;
+ cursor++;
+ break;
+
+ case TOKEN_TYPE_NAME:
+ element->compound = TYPE_REF;
+ ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
+ type_finder);
+ if (!ref) {
+ fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+ cursor->type = *ref;
+ (*ref)->ref_count++;
+ cursor++;
+ break;
+
+ case DIRECTIVE_CHOICE:
+ element->compound = CHOICE;
+ cursor++;
+ element->children = parse_compound(&cursor, end, 1);
+ break;
+
+ case DIRECTIVE_SEQUENCE:
+ element->compound = SEQUENCE;
+ element->method = ASN1_CONS;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type == DIRECTIVE_OF) {
+ element->compound = SEQUENCE_OF;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ element->children = parse_type(&cursor, end, NULL);
+ } else {
+ element->children = parse_compound(&cursor, end, 0);
+ }
+ break;
+
+ case DIRECTIVE_SET:
+ element->compound = SET;
+ element->method = ASN1_CONS;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type == DIRECTIVE_OF) {
+ element->compound = SET_OF;
+ cursor++;
+ if (cursor >= end)
+ goto parse_error;
+ element->children = parse_type(&cursor, end, NULL);
+ } else {
+ element->children = parse_compound(&cursor, end, 1);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+
+ /* Handle elements that are optional */
+ if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
+ cursor->token_type == DIRECTIVE_DEFAULT)
+ ) {
+ cursor++;
+ top->flags |= ELEMENT_SKIPPABLE;
+ }
+
+ if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != TOKEN_ELEMENT_NAME) {
+ fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+
+ action = malloc(sizeof(struct action) + cursor->size + 1);
+ if (!action) {
+ perror(NULL);
+ exit(1);
+ }
+ action->index = 0;
+ memcpy(action->name, cursor->value, cursor->size);
+ action->name[cursor->size] = 0;
+
+ for (ppaction = &action_list;
+ *ppaction;
+ ppaction = &(*ppaction)->next
+ ) {
+ int cmp = strcmp(action->name, (*ppaction)->name);
+ if (cmp == 0) {
+ free(action);
+ action = *ppaction;
+ goto found;
+ }
+ if (cmp < 0) {
+ action->next = *ppaction;
+ *ppaction = action;
+ nr_actions++;
+ goto found;
+ }
+ }
+ action->next = NULL;
+ *ppaction = action;
+ nr_actions++;
+ found:
+
+ element->action = action;
+ cursor->action = action;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != TOKEN_CLOSE_ACTION) {
+ fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+ cursor++;
+ }
+
+ *_cursor = cursor;
+ return top;
+
+parse_error:
+ fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+
+overrun_error:
+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
+ exit(1);
+}
+
+/*
+ * Parse a compound type list
+ */
+static struct element *parse_compound(struct token **_cursor, struct token *end,
+ int alternates)
+{
+ struct element *children, **child_p = &children, *element;
+ struct token *cursor = *_cursor, *name;
+
+ if (cursor->token_type != TOKEN_OPEN_CURLY) {
+ fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+
+ if (cursor->token_type == TOKEN_OPEN_CURLY) {
+ fprintf(stderr, "%s:%d: Empty compound\n",
+ filename, cursor->line);
+ exit(1);
+ }
+
+ for (;;) {
+ name = NULL;
+ if (cursor->token_type == TOKEN_ELEMENT_NAME) {
+ name = cursor;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ }
+
+ element = parse_type(&cursor, end, name);
+ if (alternates)
+ element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
+
+ *child_p = element;
+ child_p = &element->next;
+
+ if (cursor >= end)
+ goto overrun_error;
+ if (cursor->token_type != TOKEN_COMMA)
+ break;
+ cursor++;
+ if (cursor >= end)
+ goto overrun_error;
+ }
+
+ children->flags &= ~ELEMENT_CONDITIONAL;
+
+ if (cursor->token_type != TOKEN_CLOSE_CURLY) {
+ fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
+ filename, cursor->line,
+ (int)cursor->size, (int)cursor->size, cursor->value);
+ exit(1);
+ }
+ cursor++;
+
+ *_cursor = cursor;
+ return children;
+
+overrun_error:
+ fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
+ exit(1);
+}
+
+static void render_element(FILE *out, struct element *e, struct element *tag);
+static void render_out_of_line_list(FILE *out);
+
+static int nr_entries;
+static int render_depth = 1;
+static struct element *render_list, **render_list_p = &render_list;
+
+__attribute__((format(printf, 2, 3)))
+static void render_opcode(FILE *out, const char *fmt, ...)
+{
+ va_list va;
+
+ if (out) {
+ fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
+ va_start(va, fmt);
+ vfprintf(out, fmt, va);
+ va_end(va);
+ }
+ nr_entries++;
+}
+
+__attribute__((format(printf, 2, 3)))
+static void render_more(FILE *out, const char *fmt, ...)
+{
+ va_list va;
+
+ if (out) {
+ va_start(va, fmt);
+ vfprintf(out, fmt, va);
+ va_end(va);
+ }
+}
+
+/*
+ * Render the grammar into a state machine definition.
+ */
+static void render(FILE *out, FILE *hdr)
+{
+ struct element *e;
+ struct action *action;
+ struct type *root;
+ int index;
+
+ fprintf(hdr, "/*\n");
+ fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
+ fprintf(hdr, " *\n");
+ fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
+ fprintf(hdr, " */\n");
+ fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
+ fprintf(hdr, "\n");
+ fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
+ if (ferror(hdr)) {
+ perror(headername);
+ exit(1);
+ }
+
+ fprintf(out, "/*\n");
+ fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
+ fprintf(out, " *\n");
+ fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
+ fprintf(out, " */\n");
+ fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
+ fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
+ fprintf(out, "\n");
+ if (ferror(out)) {
+ perror(outputname);
+ exit(1);
+ }
+
+ /* Tabulate the action functions we might have to call */
+ fprintf(hdr, "\n");
+ index = 0;
+ for (action = action_list; action; action = action->next) {
+ action->index = index++;
+ fprintf(hdr,
+ "extern int %s(void *, size_t, unsigned char,"
+ " const void *, size_t);\n",
+ action->name);
+ }
+ fprintf(hdr, "\n");
+
+ fprintf(out, "enum %s_actions {\n", grammar_name);
+ for (action = action_list; action; action = action->next)
+ fprintf(out, "\tACT_%s = %u,\n",
+ action->name, action->index);
+ fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
+ fprintf(out, "};\n");
+
+ fprintf(out, "\n");
+ fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
+ grammar_name, grammar_name);
+ for (action = action_list; action; action = action->next)
+ fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
+ fprintf(out, "};\n");
+
+ if (ferror(out)) {
+ perror(outputname);
+ exit(1);
+ }
+
+ /* We do two passes - the first one calculates all the offsets */
+ printf("Pass 1\n");
+ nr_entries = 0;
+ root = &type_list[0];
+ render_element(NULL, root->element, NULL);
+ render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
+ render_out_of_line_list(NULL);
+
+ for (e = element_list; e; e = e->list_next)
+ e->flags &= ~ELEMENT_RENDERED;
+
+ /* And then we actually render */
+ printf("Pass 2\n");
+ fprintf(out, "\n");
+ fprintf(out, "static const unsigned char %s_machine[] = {\n",
+ grammar_name);
+
+ nr_entries = 0;
+ root = &type_list[0];
+ render_element(out, root->element, NULL);
+ render_opcode(out, "ASN1_OP_COMPLETE,\n");
+ render_out_of_line_list(out);
+
+ fprintf(out, "};\n");
+
+ fprintf(out, "\n");
+ fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
+ fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
+ fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
+ fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
+ fprintf(out, "};\n");
+}
+
+/*
+ * Render the out-of-line elements
+ */
+static void render_out_of_line_list(FILE *out)
+{
+ struct element *e, *ce;
+ const char *act;
+ int entry;
+
+ while ((e = render_list)) {
+ render_list = e->render_next;
+ if (!render_list)
+ render_list_p = &render_list;
+
+ render_more(out, "\n");
+ e->entry_index = entry = nr_entries;
+ render_depth++;
+ for (ce = e->children; ce; ce = ce->next)
+ render_element(out, ce, NULL);
+ render_depth--;
+
+ act = e->action ? "_ACT" : "";
+ switch (e->compound) {
+ case SEQUENCE:
+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
+ break;
+ case SEQUENCE_OF:
+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
+ render_opcode(out, "_jump_target(%u),\n", entry);
+ break;
+ case SET:
+ render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
+ break;
+ case SET_OF:
+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
+ render_opcode(out, "_jump_target(%u),\n", entry);
+ break;
+ }
+ if (e->action)
+ render_opcode(out, "_action(ACT_%s),\n",
+ e->action->name);
+ render_opcode(out, "ASN1_OP_RETURN,\n");
+ }
+}
+
+/*
+ * Render an element.
+ */
+static void render_element(FILE *out, struct element *e, struct element *tag)
+{
+ struct element *ec;
+ const char *cond, *act;
+ int entry, skippable = 0, outofline = 0;
+
+ if (e->flags & ELEMENT_SKIPPABLE ||
+ (tag && tag->flags & ELEMENT_SKIPPABLE))
+ skippable = 1;
+
+ if ((e->type_def && e->type_def->ref_count > 1) ||
+ skippable)
+ outofline = 1;
+
+ if (e->type_def && out) {
+ render_more(out, "\t// %*.*s\n",
+ (int)e->type_def->name->size, (int)e->type_def->name->size,
+ e->type_def->name->value);
+ }
+
+ /* Render the operation */
+ cond = (e->flags & ELEMENT_CONDITIONAL ||
+ (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
+ act = e->action ? "_ACT" : "";
+ switch (e->compound) {
+ case ANY:
+ render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
+ if (e->name)
+ render_more(out, "\t\t// %*.*s",
+ (int)e->name->size, (int)e->name->size,
+ e->name->value);
+ render_more(out, "\n");
+ goto dont_render_tag;
+
+ case TAG_OVERRIDE:
+ render_element(out, e->children, e);
+ return;
+
+ case SEQUENCE:
+ case SEQUENCE_OF:
+ case SET:
+ case SET_OF:
+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
+ cond,
+ outofline ? "_JUMP" : "",
+ skippable ? "_OR_SKIP" : "");
+ break;
+
+ case CHOICE:
+ goto dont_render_tag;
+
+ case TYPE_REF:
+ if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
+ goto dont_render_tag;
+ default:
+ render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
+ cond, act,
+ skippable ? "_OR_SKIP" : "");
+ break;
+ }
+
+ if (e->name)
+ render_more(out, "\t\t// %*.*s",
+ (int)e->name->size, (int)e->name->size,
+ e->name->value);
+ render_more(out, "\n");
+
+ /* Render the tag */
+ if (!tag)
+ tag = e;
+ if (tag->class == ASN1_UNIV &&
+ tag->tag != 14 &&
+ tag->tag != 15 &&
+ tag->tag != 31)
+ render_opcode(out, "_tag(%s, %s, %s),\n",
+ asn1_classes[tag->class],
+ asn1_methods[tag->method | e->method],
+ asn1_universal_tags[tag->tag]);
+ else
+ render_opcode(out, "_tagn(%s, %s, %2u),\n",
+ asn1_classes[tag->class],
+ asn1_methods[tag->method | e->method],
+ tag->tag);
+ tag = NULL;
+dont_render_tag:
+
+ /* Deal with compound types */
+ switch (e->compound) {
+ case TYPE_REF:
+ render_element(out, e->type->type->element, tag);
+ if (e->action)
+ render_opcode(out, "ASN1_OP_ACT,\n");
+ break;
+
+ case SEQUENCE:
+ if (outofline) {
+ /* Render out-of-line for multiple use or
+ * skipability */
+ render_opcode(out, "_jump_target(%u),", e->entry_index);
+ if (e->type_def && e->type_def->name)
+ render_more(out, "\t\t// --> %*.*s",
+ (int)e->type_def->name->size,
+ (int)e->type_def->name->size,
+ e->type_def->name->value);
+ render_more(out, "\n");
+ if (!(e->flags & ELEMENT_RENDERED)) {
+ e->flags |= ELEMENT_RENDERED;
+ *render_list_p = e;
+ render_list_p = &e->render_next;
+ }
+ return;
+ } else {
+ /* Render inline for single use */
+ render_depth++;
+ for (ec = e->children; ec; ec = ec->next)
+ render_element(out, ec, NULL);
+ render_depth--;
+ render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
+ }
+ break;
+
+ case SEQUENCE_OF:
+ case SET_OF:
+ if (outofline) {
+ /* Render out-of-line for multiple use or
+ * skipability */
+ render_opcode(out, "_jump_target(%u),", e->entry_index);
+ if (e->type_def && e->type_def->name)
+ render_more(out, "\t\t// --> %*.*s",
+ (int)e->type_def->name->size,
+ (int)e->type_def->name->size,
+ e->type_def->name->value);
+ render_more(out, "\n");
+ if (!(e->flags & ELEMENT_RENDERED)) {
+ e->flags |= ELEMENT_RENDERED;
+ *render_list_p = e;
+ render_list_p = &e->render_next;
+ }
+ return;
+ } else {
+ /* Render inline for single use */
+ entry = nr_entries;
+ render_depth++;
+ render_element(out, e->children, NULL);
+ render_depth--;
+ if (e->compound == SEQUENCE_OF)
+ render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
+ else
+ render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
+ render_opcode(out, "_jump_target(%u),\n", entry);
+ }
+ break;
+
+ case SET:
+ /* I can't think of a nice way to do SET support without having
+ * a stack of bitmasks to make sure no element is repeated.
+ * The bitmask has also to be checked that no non-optional
+ * elements are left out whilst not preventing optional
+ * elements from being left out.
+ */
+ fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
+ exit(1);
+
+ case CHOICE:
+ for (ec = e->children; ec; ec = ec->next)
+ render_element(out, ec, NULL);
+ if (!skippable)
+ render_opcode(out, "ASN1_OP_COND_FAIL,\n");
+ if (e->action)
+ render_opcode(out, "ASN1_OP_ACT,\n");
+ break;
+
+ default:
+ break;
+ }
+
+ if (e->action)
+ render_opcode(out, "_action(ACT_%s),\n", e->action->name);
+}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ca05ba217f5..21a9f5de0a2 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -421,7 +421,7 @@ sub top_of_kernel_tree {
}
}
return 1;
- }
+}
sub parse_email {
my ($formatted_email) = @_;
@@ -1386,6 +1386,8 @@ sub process {
my $in_header_lines = 1;
my $in_commit_log = 0; #Scanning lines before patch
+ my $non_utf8_charset = 0;
+
our @report = ();
our $cnt_lines = 0;
our $cnt_error = 0;
@@ -1686,10 +1688,17 @@ sub process {
$in_commit_log = 1;
}
-# Still not yet in a patch, check for any UTF-8
- if ($in_commit_log && $realfile =~ /^$/ &&
+# Check if there is UTF-8 in a commit log when a mail header has explicitly
+# declined it, i.e defined some charset where it is missing.
+ if ($in_header_lines &&
+ $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
+ $1 !~ /utf-8/i) {
+ $non_utf8_charset = 1;
+ }
+
+ if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
$rawline =~ /$NON_ASCII_UTF8/) {
- CHK("UTF8_BEFORE_PATCH",
+ WARN("UTF8_BEFORE_PATCH",
"8-bit UTF-8 used in possible commit log\n" . $herecurr);
}
@@ -1873,6 +1882,20 @@ sub process {
"No space is necessary after a cast\n" . $hereprev);
}
+ if ($realfile =~ m@^(drivers/net/|net/)@ &&
+ $rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
+ $prevrawline =~ /^\+[ \t]*$/) {
+ WARN("NETWORKING_BLOCK_COMMENT_STYLE",
+ "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
+ }
+
+ if ($realfile =~ m@^(drivers/net/|net/)@ &&
+ $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
+ $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
+ WARN("NETWORKING_BLOCK_COMMENT_STYLE",
+ "networking block comments put the trailing */ on a separate line\n" . $herecurr);
+ }
+
# check for spaces at the beginning of a line.
# Exceptions:
# 1) within comments
@@ -2390,8 +2413,10 @@ sub process {
my $orig = $1;
my $level = lc($orig);
$level = "warn" if ($level eq "warning");
+ my $level2 = $level;
+ $level2 = "dbg" if ($level eq "debug");
WARN("PREFER_PR_LEVEL",
- "Prefer pr_$level(... to printk(KERN_$1, ...\n" . $herecurr);
+ "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
}
if ($line =~ /\bpr_warning\s*\(/) {
@@ -2947,7 +2972,7 @@ sub process {
my $exceptions = qr{
$Declare|
module_param_named|
- MODULE_PARAM_DESC|
+ MODULE_PARM_DESC|
DECLARE_PER_CPU|
DEFINE_PER_CPU|
__typeof__\(|
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 823e972149e..1a49d1c7ecf 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -95,6 +95,9 @@ coccinelle () {
$SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \
$SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
$SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1
+ elif [ "$MODE" = "rep+ctxt" ] ; then
+ $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff && \
+ $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
else
$SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
fi
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
index cbfd08c7d8c..15f076fdecb 100644
--- a/scripts/coccinelle/api/ptr_ret.cocci
+++ b/scripts/coccinelle/api/ptr_ret.cocci
@@ -30,6 +30,13 @@ expression ptr;
- if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
+ return PTR_RET(ptr);
+@depends on patch@
+expression ptr;
+@@
+
+- (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
++ PTR_RET(ptr)
+
@r1 depends on !patch@
expression ptr;
position p1;
@@ -44,6 +51,13 @@ position p2;
* if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
+@r3 depends on !patch@
+expression ptr;
+position p3;
+@@
+
+* IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0
+
@script:python depends on org@
p << r1.p1;
@@
@@ -57,6 +71,12 @@ p << r2.p2;
coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
+@script:python depends on org@
+p << r3.p3;
+@@
+
+coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
+
@script:python depends on report@
p << r1.p1;
@@
@@ -68,3 +88,9 @@ p << r2.p2;
@@
coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used")
+
+@script:python depends on report@
+p << r3.p3;
+@@
+
+coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used")
diff --git a/scripts/coccinelle/tests/odd_ptr_err.cocci b/scripts/coccinelle/tests/odd_ptr_err.cocci
new file mode 100644
index 00000000000..e8dd8a6b28a
--- /dev/null
+++ b/scripts/coccinelle/tests/odd_ptr_err.cocci
@@ -0,0 +1,65 @@
+/// PTR_ERR should access the value just tested by IS_ERR
+//# There can be false positives in the patch case, where it is the call
+//# IS_ERR that is wrong.
+///
+// Confidence: High
+// Copyright: (C) 2012 Julia Lawall, INRIA. GPLv2.
+// Copyright: (C) 2012 Gilles Muller, INRIA. GPLv2.
+// URL: http://coccinelle.lip6.fr/
+// Comments:
+// Options: -no_includes -include_headers
+
+virtual patch
+virtual context
+virtual org
+virtual report
+
+@depends on patch@
+expression e,e1;
+@@
+
+(
+if (IS_ERR(e)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e))
+ { ...
+ PTR_ERR(
+- e1
++ e
+ )
+ ... }
+)
+
+@r depends on !patch@
+expression e,e1;
+position p1,p2;
+@@
+
+(
+if (IS_ERR(e)) { ... PTR_ERR(e) ... }
+|
+if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
+|
+*if (IS_ERR@p1(e))
+ { ...
+* PTR_ERR@p2(e1)
+ ... }
+)
+
+@script:python depends on org@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+cocci.print_main("inconsistent IS_ERR and PTR_ERR",p1)
+cocci.print_secs("PTR_ERR",p2)
+
+@script:python depends on report@
+p1 << r.p1;
+p2 << r.p2;
+@@
+
+msg = "inconsistent IS_ERR and PTR_ERR, PTR_ERR on line %s" % (p2[0].line)
+coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index 6ddf9ecac66..bece49b3553 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -3,7 +3,16 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
- checks.c
+DTC_SRCS = \
+ checks.c \
+ data.c \
+ dtc.c \
+ flattree.c \
+ fstree.c \
+ livetree.c \
+ srcpos.c \
+ treesource.c \
+ util.c
+
DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c
index a662a004479..ee96a2519ef 100644
--- a/scripts/dtc/checks.c
+++ b/scripts/dtc/checks.c
@@ -31,12 +31,6 @@
#define TRACE(c, fmt, ...) do { } while (0)
#endif
-enum checklevel {
- IGNORE = 0,
- WARN = 1,
- ERROR = 2,
-};
-
enum checkstatus {
UNCHECKED = 0,
PREREQ,
@@ -57,14 +51,14 @@ struct check {
node_check_fn node_fn;
prop_check_fn prop_fn;
void *data;
- enum checklevel level;
+ bool warn, error;
enum checkstatus status;
int inprogress;
int num_prereqs;
struct check **prereq;
};
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+#define CHECK_ENTRY(nm, tfn, nfn, pfn, d, w, e, ...) \
static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
static struct check nm = { \
.name = #nm, \
@@ -72,20 +66,37 @@ struct check {
.node_fn = (nfn), \
.prop_fn = (pfn), \
.data = (d), \
- .level = (lvl), \
+ .warn = (w), \
+ .error = (e), \
.status = UNCHECKED, \
.num_prereqs = ARRAY_SIZE(nm##_prereqs), \
.prereq = nm##_prereqs, \
};
-
-#define TREE_CHECK(nm, d, lvl, ...) \
- CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
- CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+#define WARNING(nm, tfn, nfn, pfn, d, ...) \
+ CHECK_ENTRY(nm, tfn, nfn, pfn, d, true, false, __VA_ARGS__)
+#define ERROR(nm, tfn, nfn, pfn, d, ...) \
+ CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, true, __VA_ARGS__)
+#define CHECK(nm, tfn, nfn, pfn, d, ...) \
+ CHECK_ENTRY(nm, tfn, nfn, pfn, d, false, false, __VA_ARGS__)
+
+#define TREE_WARNING(nm, d, ...) \
+ WARNING(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_ERROR(nm, d, ...) \
+ ERROR(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define TREE_CHECK(nm, d, ...) \
+ CHECK(nm, check_##nm, NULL, NULL, d, __VA_ARGS__)
+#define NODE_WARNING(nm, d, ...) \
+ WARNING(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define NODE_ERROR(nm, d, ...) \
+ ERROR(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define NODE_CHECK(nm, d, ...) \
+ CHECK(nm, NULL, check_##nm, NULL, d, __VA_ARGS__)
+#define PROP_WARNING(nm, d, ...) \
+ WARNING(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_ERROR(nm, d, ...) \
+ ERROR(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
+#define PROP_CHECK(nm, d, ...) \
+ CHECK(nm, NULL, NULL, check_##nm, d, __VA_ARGS__)
#ifdef __GNUC__
static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
@@ -95,13 +106,13 @@ static inline void check_msg(struct check *c, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
- if ((c->level < WARN) || (c->level <= quiet))
- return; /* Suppress message */
-
- fprintf(stderr, "%s (%s): ",
- (c->level == ERROR) ? "ERROR" : "Warning", c->name);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
+ if ((c->warn && (quiet < 1))
+ || (c->error && (quiet < 2))) {
+ fprintf(stderr, "%s (%s): ",
+ (c->error) ? "ERROR" : "Warning", c->name);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ }
}
#define FAIL(c, ...) \
@@ -167,7 +178,7 @@ static int run_check(struct check *c, struct node *dt)
out:
c->inprogress = 0;
- if ((c->status != PASSED) && (c->level == ERROR))
+ if ((c->status != PASSED) && (c->error))
error = 1;
return error;
}
@@ -176,6 +187,13 @@ out:
* Utility check functions
*/
+/* A check which always fails, for testing purposes only */
+static inline void check_always_fail(struct check *c, struct node *dt)
+{
+ FAIL(c, "always_fail check");
+}
+TREE_CHECK(always_fail, NULL);
+
static void check_is_string(struct check *c, struct node *root,
struct node *node)
{
@@ -190,8 +208,10 @@ static void check_is_string(struct check *c, struct node *root,
FAIL(c, "\"%s\" property in %s is not a string",
propname, node->fullpath);
}
-#define CHECK_IS_STRING(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_STRING(nm, propname) \
+ WARNING(nm, NULL, check_is_string, NULL, (propname))
+#define ERROR_IF_NOT_STRING(nm, propname) \
+ ERROR(nm, NULL, check_is_string, NULL, (propname))
static void check_is_cell(struct check *c, struct node *root,
struct node *node)
@@ -207,8 +227,10 @@ static void check_is_cell(struct check *c, struct node *root,
FAIL(c, "\"%s\" property in %s is not a single cell",
propname, node->fullpath);
}
-#define CHECK_IS_CELL(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+#define WARNING_IF_NOT_CELL(nm, propname) \
+ WARNING(nm, NULL, check_is_cell, NULL, (propname))
+#define ERROR_IF_NOT_CELL(nm, propname) \
+ ERROR(nm, NULL, check_is_cell, NULL, (propname))
/*
* Structural check functions
@@ -227,20 +249,24 @@ static void check_duplicate_node_names(struct check *c, struct node *dt,
FAIL(c, "Duplicate node name %s",
child->fullpath);
}
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
+NODE_ERROR(duplicate_node_names, NULL);
static void check_duplicate_property_names(struct check *c, struct node *dt,
struct node *node)
{
struct property *prop, *prop2;
- for_each_property(node, prop)
- for (prop2 = prop->next; prop2; prop2 = prop2->next)
+ for_each_property(node, prop) {
+ for (prop2 = prop->next; prop2; prop2 = prop2->next) {
+ if (prop2->deleted)
+ continue;
if (streq(prop->name, prop2->name))
FAIL(c, "Duplicate property name %s in %s",
prop->name, node->fullpath);
+ }
+ }
}
-NODE_CHECK(duplicate_property_names, NULL, ERROR);
+NODE_ERROR(duplicate_property_names, NULL);
#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
@@ -256,7 +282,7 @@ static void check_node_name_chars(struct check *c, struct node *dt,
FAIL(c, "Bad character '%c' in node %s",
node->name[n], node->fullpath);
}
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+NODE_ERROR(node_name_chars, PROPNODECHARS "@");
static void check_node_name_format(struct check *c, struct node *dt,
struct node *node)
@@ -265,7 +291,7 @@ static void check_node_name_format(struct check *c, struct node *dt,
FAIL(c, "Node %s has multiple '@' characters in name",
node->fullpath);
}
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+NODE_ERROR(node_name_format, NULL, &node_name_chars);
static void check_property_name_chars(struct check *c, struct node *dt,
struct node *node, struct property *prop)
@@ -276,7 +302,7 @@ static void check_property_name_chars(struct check *c, struct node *dt,
FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
prop->name[n], prop->name, node->fullpath);
}
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+PROP_ERROR(property_name_chars, PROPNODECHARS);
#define DESCLABEL_FMT "%s%s%s%s%s"
#define DESCLABEL_ARGS(node,prop,mark) \
@@ -331,8 +357,8 @@ static void check_duplicate_label_prop(struct check *c, struct node *dt,
for_each_marker_of_type(m, LABEL)
check_duplicate_label(c, dt, m->ref, node, prop, m);
}
-CHECK(duplicate_label, NULL, check_duplicate_label_node,
- check_duplicate_label_prop, NULL, ERROR);
+ERROR(duplicate_label, NULL, check_duplicate_label_node,
+ check_duplicate_label_prop, NULL);
static void check_explicit_phandles(struct check *c, struct node *root,
struct node *node, struct property *prop)
@@ -391,7 +417,7 @@ static void check_explicit_phandles(struct check *c, struct node *root,
node->phandle = phandle;
}
-PROP_CHECK(explicit_phandles, NULL, ERROR);
+PROP_ERROR(explicit_phandles, NULL);
static void check_name_properties(struct check *c, struct node *root,
struct node *node)
@@ -420,8 +446,8 @@ static void check_name_properties(struct check *c, struct node *root,
free(prop);
}
}
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+ERROR_IF_NOT_STRING(name_is_string, "name");
+NODE_ERROR(name_properties, NULL, &name_is_string);
/*
* Reference fixup functions
@@ -448,7 +474,7 @@ static void fixup_phandle_references(struct check *c, struct node *dt,
*((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
}
}
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ERROR(phandle_references, NULL, NULL, fixup_phandle_references, NULL,
&duplicate_node_names, &explicit_phandles);
static void fixup_path_references(struct check *c, struct node *dt,
@@ -473,19 +499,19 @@ static void fixup_path_references(struct check *c, struct node *dt,
strlen(path) + 1);
}
}
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ERROR(path_references, NULL, NULL, fixup_path_references, NULL,
&duplicate_node_names);
/*
* Semantic checks
*/
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+WARNING_IF_NOT_CELL(address_cells_is_cell, "#address-cells");
+WARNING_IF_NOT_CELL(size_cells_is_cell, "#size-cells");
+WARNING_IF_NOT_CELL(interrupt_cells_is_cell, "#interrupt-cells");
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
+WARNING_IF_NOT_STRING(device_type_is_string, "device_type");
+WARNING_IF_NOT_STRING(model_is_string, "model");
+WARNING_IF_NOT_STRING(status_is_string, "status");
static void fixup_addr_size_cells(struct check *c, struct node *dt,
struct node *node)
@@ -503,8 +529,8 @@ static void fixup_addr_size_cells(struct check *c, struct node *dt,
if (prop)
node->size_cells = propval_cell(prop);
}
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
- &address_cells_is_cell, &size_cells_is_cell);
+WARNING(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL,
+ &address_cells_is_cell, &size_cells_is_cell);
#define node_addr_cells(n) \
(((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
@@ -538,7 +564,7 @@ static void check_reg_format(struct check *c, struct node *dt,
"(#address-cells == %d, #size-cells == %d)",
node->fullpath, prop->val.len, addr_cells, size_cells);
}
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(reg_format, NULL, &addr_size_cells);
static void check_ranges_format(struct check *c, struct node *dt,
struct node *node)
@@ -579,7 +605,7 @@ static void check_ranges_format(struct check *c, struct node *dt,
p_addr_cells, c_addr_cells, c_size_cells);
}
}
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+NODE_WARNING(ranges_format, NULL, &addr_size_cells);
/*
* Style checks
@@ -606,7 +632,7 @@ static void check_avoid_default_addr_size(struct check *c, struct node *dt,
FAIL(c, "Relying on default #size-cells value for %s",
node->fullpath);
}
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+NODE_WARNING(avoid_default_addr_size, NULL, &addr_size_cells);
static void check_obsolete_chosen_interrupt_controller(struct check *c,
struct node *dt)
@@ -623,7 +649,7 @@ static void check_obsolete_chosen_interrupt_controller(struct check *c,
FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
"property");
}
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+TREE_WARNING(obsolete_chosen_interrupt_controller, NULL);
static struct check *check_table[] = {
&duplicate_node_names, &duplicate_property_names,
@@ -642,8 +668,71 @@ static struct check *check_table[] = {
&avoid_default_addr_size,
&obsolete_chosen_interrupt_controller,
+
+ &always_fail,
};
+static void enable_warning_error(struct check *c, bool warn, bool error)
+{
+ int i;
+
+ /* Raising level, also raise it for prereqs */
+ if ((warn && !c->warn) || (error && !c->error))
+ for (i = 0; i < c->num_prereqs; i++)
+ enable_warning_error(c->prereq[i], warn, error);
+
+ c->warn = c->warn || warn;
+ c->error = c->error || error;
+}
+
+static void disable_warning_error(struct check *c, bool warn, bool error)
+{
+ int i;
+
+ /* Lowering level, also lower it for things this is the prereq
+ * for */
+ if ((warn && c->warn) || (error && c->error)) {
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *cc = check_table[i];
+ int j;
+
+ for (j = 0; j < cc->num_prereqs; j++)
+ if (cc->prereq[j] == c)
+ disable_warning_error(cc, warn, error);
+ }
+ }
+
+ c->warn = c->warn && !warn;
+ c->error = c->error && !error;
+}
+
+void parse_checks_option(bool warn, bool error, const char *optarg)
+{
+ int i;
+ const char *name = optarg;
+ bool enable = true;
+
+ if ((strncmp(optarg, "no-", 3) == 0)
+ || (strncmp(optarg, "no_", 3) == 0)) {
+ name = optarg + 3;
+ enable = false;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *c = check_table[i];
+
+ if (streq(c->name, name)) {
+ if (enable)
+ enable_warning_error(c, warn, error);
+ else
+ disable_warning_error(c, warn, error);
+ return;
+ }
+ }
+
+ die("Unrecognized check name \"%s\"\n", name);
+}
+
void process_checks(int force, struct boot_info *bi)
{
struct node *dt = bi->dt;
@@ -653,7 +742,7 @@ void process_checks(int force, struct boot_info *bi)
for (i = 0; i < ARRAY_SIZE(check_table); i++) {
struct check *c = check_table[i];
- if (c->level != IGNORE)
+ if (c->warn || c->error)
error = error || run_check(c, dt);
}
diff --git a/scripts/dtc/data.c b/scripts/dtc/data.c
index fe555e819bf..4a40c5b9247 100644
--- a/scripts/dtc/data.c
+++ b/scripts/dtc/data.c
@@ -68,40 +68,6 @@ struct data data_copy_mem(const char *mem, int len)
return d;
}
-static char get_oct_char(const char *s, int *i)
-{
- char x[4];
- char *endx;
- long val;
-
- x[3] = '\0';
- strncpy(x, s + *i, 3);
-
- val = strtol(x, &endx, 8);
-
- assert(endx > x);
-
- (*i) += endx - x;
- return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
- char x[3];
- char *endx;
- long val;
-
- x[2] = '\0';
- strncpy(x, s + *i, 2);
-
- val = strtol(x, &endx, 16);
- if (!(endx > x))
- die("\\x used with no following hex digits\n");
-
- (*i) += endx - x;
- return val;
-}
-
struct data data_copy_escape_string(const char *s, int len)
{
int i = 0;
@@ -114,53 +80,10 @@ struct data data_copy_escape_string(const char *s, int len)
while (i < len) {
char c = s[i++];
- if (c != '\\') {
- q[d.len++] = c;
- continue;
- }
-
- c = s[i++];
- assert(c);
- switch (c) {
- case 'a':
- q[d.len++] = '\a';
- break;
- case 'b':
- q[d.len++] = '\b';
- break;
- case 't':
- q[d.len++] = '\t';
- break;
- case 'n':
- q[d.len++] = '\n';
- break;
- case 'v':
- q[d.len++] = '\v';
- break;
- case 'f':
- q[d.len++] = '\f';
- break;
- case 'r':
- q[d.len++] = '\r';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- i--; /* need to re-read the first digit as
- * part of the octal value */
- q[d.len++] = get_oct_char(s, &i);
- break;
- case 'x':
- q[d.len++] = get_hex_char(s, &i);
- break;
- default:
- q[d.len++] = c;
- }
+ if (c == '\\')
+ c = get_escape_char(s, &i);
+
+ q[d.len++] = c;
}
q[d.len++] = '\0';
@@ -245,11 +168,33 @@ struct data data_merge(struct data d1, struct data d2)
return d;
}
-struct data data_append_cell(struct data d, cell_t word)
+struct data data_append_integer(struct data d, uint64_t value, int bits)
{
- cell_t beword = cpu_to_fdt32(word);
-
- return data_append_data(d, &beword, sizeof(beword));
+ uint8_t value_8;
+ uint16_t value_16;
+ uint32_t value_32;
+ uint64_t value_64;
+
+ switch (bits) {
+ case 8:
+ value_8 = value;
+ return data_append_data(d, &value_8, 1);
+
+ case 16:
+ value_16 = cpu_to_fdt16(value);
+ return data_append_data(d, &value_16, 2);
+
+ case 32:
+ value_32 = cpu_to_fdt32(value);
+ return data_append_data(d, &value_32, 4);
+
+ case 64:
+ value_64 = cpu_to_fdt64(value);
+ return data_append_data(d, &value_64, 8);
+
+ default:
+ die("Invalid literal size (%d)\n", bits);
+ }
}
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
@@ -262,11 +207,14 @@ struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
return data_append_data(d, &bere, sizeof(bere));
}
-struct data data_append_addr(struct data d, uint64_t addr)
+struct data data_append_cell(struct data d, cell_t word)
{
- uint64_t beaddr = cpu_to_fdt64(addr);
+ return data_append_integer(d, word, sizeof(word) * 8);
+}
- return data_append_data(d, &beaddr, sizeof(beaddr));
+struct data data_append_addr(struct data d, uint64_t addr)
+{
+ return data_append_integer(d, addr, sizeof(addr) * 8);
}
struct data data_append_byte(struct data d, uint8_t byte)
diff --git a/scripts/dtc/dtc-lexer.l b/scripts/dtc/dtc-lexer.l
index e866ea5166a..254d5af8895 100644
--- a/scripts/dtc/dtc-lexer.l
+++ b/scripts/dtc/dtc-lexer.l
@@ -29,6 +29,7 @@ PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
PATHCHAR ({PROPNODECHAR}|[/])
LABEL [a-zA-Z_][a-zA-Z0-9_]*
STRING \"([^\\"]|\\.)*\"
+CHAR_LITERAL '([^']|\\')*'
WS [[:space:]]
COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
LINECOMMENT "//".*\n
@@ -70,6 +71,27 @@ static int pop_input_file(void);
push_input_file(name);
}
+<*>^"#"(line)?{WS}+[0-9]+{WS}+{STRING}({WS}+[0-9]+)? {
+ char *line, *tmp, *fn;
+ /* skip text before line # */
+ line = yytext;
+ while (!isdigit(*line))
+ line++;
+ /* skip digits in line # */
+ tmp = line;
+ while (!isspace(*tmp))
+ tmp++;
+ /* "NULL"-terminate line # */
+ *tmp = '\0';
+ /* start of filename */
+ fn = strchr(tmp + 1, '"') + 1;
+ /* strip trailing " from filename */
+ tmp = strchr(fn, '"');
+ *tmp = 0;
+ /* -1 since #line is the number of the next line */
+ srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+ }
+
<*><<EOF>> {
if (!pop_input_file()) {
yyterminate();
@@ -96,6 +118,26 @@ static int pop_input_file(void);
return DT_MEMRESERVE;
}
+<*>"/bits/" {
+ DPRINT("Keyword: /bits/\n");
+ BEGIN_DEFAULT();
+ return DT_BITS;
+ }
+
+<*>"/delete-property/" {
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_PROP;
+ }
+
+<*>"/delete-node/" {
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_NODE;
+ }
+
<*>{LABEL}: {
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -103,12 +145,19 @@ static int pop_input_file(void);
return DT_LABEL;
}
-<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
+<V1>([0-9]+|0[xX][0-9a-fA-F]+)(U|L|UL|LL|ULL)? {
yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
+<*>{CHAR_LITERAL} {
+ yytext[yyleng-1] = '\0';
+ yylval.literal = xstrdup(yytext+1);
+ DPRINT("Character literal: %s\n", yylval.literal);
+ return DT_CHAR_LITERAL;
+ }
+
<*>\&{LABEL} { /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
@@ -134,9 +183,10 @@ static int pop_input_file(void);
return ']';
}
-<PROPNODENAME>{PROPNODECHAR}+ {
+<PROPNODENAME>\\?{PROPNODECHAR}+ {
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = xstrdup(yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+ yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
@@ -150,6 +200,15 @@ static int pop_input_file(void);
<*>{COMMENT}+ /* eat C-style comments */
<*>{LINECOMMENT}+ /* eat C++-style comments */
+<*>"<<" { return DT_LSHIFT; };
+<*>">>" { return DT_RSHIFT; };
+<*>"<=" { return DT_LE; };
+<*>">=" { return DT_GE; };
+<*>"==" { return DT_EQ; };
+<*>"!=" { return DT_NE; };
+<*>"&&" { return DT_AND; };
+<*>"||" { return DT_OR; };
+
<*>. {
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
diff --git a/scripts/dtc/dtc-lexer.lex.c_shipped b/scripts/dtc/dtc-lexer.lex.c_shipped
index 8bbe1281705..a6c5fcdfc03 100644
--- a/scripts/dtc/dtc-lexer.lex.c_shipped
+++ b/scripts/dtc/dtc-lexer.lex.c_shipped
@@ -1,5 +1,6 @@
+#line 2 "dtc-lexer.lex.c"
-#line 3 "scripts/dtc/dtc-lexer.lex.c_shipped"
+#line 4 "dtc-lexer.lex.c"
#define YY_INT_ALIGNED short int
@@ -53,7 +54,6 @@ typedef int flex_int32_t;
typedef unsigned char flex_uint8_t;
typedef unsigned short int flex_uint16_t;
typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
/* Limits of integral types. */
#ifndef INT8_MIN
@@ -84,6 +84,8 @@ typedef unsigned int flex_uint32_t;
#define UINT32_MAX (4294967295U)
#endif
+#endif /* ! C99 */
+
#endif /* ! FLEXINT_H */
#ifdef __cplusplus
@@ -140,7 +142,15 @@ typedef unsigned int flex_uint32_t;
/* Size of default input buffer. */
#ifndef YY_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k.
+ * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case.
+ * Ditto for the __ia64__ case accordingly.
+ */
+#define YY_BUF_SIZE 32768
+#else
#define YY_BUF_SIZE 16384
+#endif /* __ia64__ */
#endif
/* The state buf must be large enough to hold one state per character in the main buffer.
@@ -362,8 +372,8 @@ static void yy_fatal_error (yyconst char msg[] );
*yy_cp = '\0'; \
(yy_c_buf_p) = yy_cp;
-#define YY_NUM_RULES 17
-#define YY_END_OF_BUFFER 18
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -371,19 +381,25 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[94] =
+static yyconst flex_int16_t yy_accept[161] =
{ 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 18, 16, 13, 13, 16, 16, 16, 16, 16, 16,
- 16, 10, 11, 11, 6, 6, 13, 0, 2, 0,
- 7, 0, 0, 0, 0, 0, 0, 0, 5, 0,
- 9, 9, 11, 11, 6, 0, 7, 0, 0, 0,
- 0, 15, 0, 0, 0, 0, 6, 0, 14, 0,
- 0, 0, 0, 0, 8, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 12,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 4, 0
-
+ 31, 29, 18, 18, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 15, 16,
+ 16, 29, 16, 10, 10, 18, 26, 0, 3, 0,
+ 27, 12, 0, 0, 11, 0, 0, 0, 0, 0,
+ 0, 0, 21, 23, 25, 24, 22, 0, 9, 28,
+ 0, 0, 0, 14, 14, 16, 16, 16, 10, 10,
+ 10, 0, 12, 0, 11, 0, 0, 0, 20, 0,
+ 0, 0, 0, 0, 0, 0, 0, 16, 10, 10,
+ 10, 0, 19, 0, 0, 0, 0, 0, 0, 0,
+
+ 0, 0, 16, 13, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 16, 6, 0, 0, 0, 0, 0,
+ 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
+ 4, 17, 0, 0, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
+ 0, 0, 5, 8, 0, 0, 0, 0, 7, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -391,17 +407,17 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 4, 5, 1, 1, 6, 1, 1,
- 1, 7, 5, 5, 8, 5, 9, 10, 11, 12,
- 12, 12, 12, 12, 12, 12, 12, 13, 1, 1,
- 1, 1, 5, 5, 14, 14, 14, 14, 14, 14,
- 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
- 15, 15, 15, 15, 15, 15, 15, 16, 15, 15,
- 1, 17, 18, 1, 15, 1, 14, 19, 20, 21,
-
- 22, 14, 15, 15, 23, 15, 15, 24, 25, 26,
- 15, 15, 15, 27, 28, 29, 30, 31, 15, 16,
- 15, 15, 32, 1, 33, 1, 1, 1, 1, 1,
+ 1, 2, 4, 5, 6, 1, 1, 7, 8, 1,
+ 1, 9, 10, 10, 11, 10, 12, 13, 14, 15,
+ 15, 15, 15, 15, 15, 15, 15, 16, 1, 17,
+ 18, 19, 10, 10, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 22, 21, 21, 21, 21,
+ 21, 21, 21, 21, 23, 21, 21, 24, 21, 21,
+ 1, 25, 26, 1, 21, 1, 20, 27, 28, 29,
+
+ 30, 20, 21, 21, 31, 21, 21, 32, 33, 34,
+ 35, 36, 21, 37, 38, 39, 40, 41, 21, 24,
+ 42, 21, 43, 44, 45, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -418,112 +434,163 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[34] =
+static yyconst flex_int32_t yy_meta[46] =
{ 0,
- 1, 1, 1, 1, 2, 1, 2, 2, 3, 4,
- 4, 4, 5, 6, 7, 7, 1, 1, 6, 6,
- 6, 6, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 8, 1
+ 1, 1, 1, 1, 1, 2, 3, 1, 2, 2,
+ 2, 4, 5, 5, 5, 6, 1, 1, 1, 7,
+ 8, 8, 8, 8, 1, 1, 7, 7, 7, 7,
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+ 8, 8, 3, 1, 1
} ;
-static yyconst flex_int16_t yy_base[106] =
+static yyconst flex_int16_t yy_base[175] =
{ 0,
- 0, 0, 237, 236, 25, 0, 47, 0, 30, 71,
- 244, 247, 82, 84, 84, 211, 95, 229, 218, 0,
- 111, 247, 0, 84, 83, 95, 106, 86, 247, 237,
- 0, 230, 231, 234, 207, 209, 212, 220, 247, 206,
- 247, 218, 0, 106, 116, 0, 0, 0, 223, 89,
- 226, 219, 199, 206, 200, 204, 0, 190, 213, 212,
- 202, 91, 178, 161, 247, 172, 144, 150, 140, 130,
- 140, 124, 128, 120, 138, 137, 123, 122, 247, 247,
- 134, 114, 132, 86, 135, 125, 90, 136, 247, 97,
- 29, 247, 247, 153, 156, 161, 165, 170, 176, 180,
-
- 187, 195, 200, 205, 212
+ 0, 388, 381, 40, 41, 386, 71, 385, 34, 44,
+ 390, 395, 60, 62, 371, 112, 111, 111, 111, 104,
+ 370, 106, 371, 342, 124, 119, 0, 144, 395, 0,
+ 123, 0, 159, 153, 165, 167, 395, 130, 395, 382,
+ 395, 0, 372, 122, 395, 157, 374, 379, 350, 21,
+ 346, 349, 395, 395, 395, 395, 395, 362, 395, 395,
+ 181, 346, 342, 395, 359, 0, 191, 343, 190, 351,
+ 350, 0, 0, 0, 173, 362, 177, 367, 357, 329,
+ 335, 328, 337, 331, 206, 329, 334, 327, 395, 338,
+ 170, 314, 346, 345, 318, 325, 343, 158, 316, 212,
+
+ 322, 319, 320, 395, 340, 336, 308, 305, 314, 304,
+ 295, 138, 208, 220, 395, 292, 305, 265, 264, 254,
+ 201, 222, 285, 275, 273, 270, 236, 235, 225, 115,
+ 395, 395, 252, 216, 216, 217, 214, 230, 209, 220,
+ 213, 239, 211, 217, 216, 209, 229, 395, 240, 225,
+ 206, 169, 395, 395, 116, 106, 99, 54, 395, 395,
+ 254, 260, 268, 272, 276, 282, 289, 293, 301, 309,
+ 313, 319, 327, 335
} ;
-static yyconst flex_int16_t yy_def[106] =
+static yyconst flex_int16_t yy_def[175] =
{ 0,
- 93, 1, 1, 1, 1, 5, 93, 7, 1, 1,
- 93, 93, 93, 93, 94, 95, 93, 96, 17, 97,
- 96, 93, 98, 99, 93, 93, 93, 94, 93, 94,
- 100, 93, 101, 102, 93, 93, 93, 96, 93, 93,
- 93, 96, 98, 99, 93, 103, 100, 104, 101, 101,
- 102, 93, 93, 93, 93, 93, 103, 104, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 105, 93, 105, 93, 105,
- 93, 93, 0, 93, 93, 93, 93, 93, 93, 93,
-
- 93, 93, 93, 93, 93
+ 160, 1, 1, 1, 1, 5, 160, 7, 1, 1,
+ 160, 160, 160, 160, 160, 161, 162, 163, 160, 160,
+ 160, 160, 164, 160, 160, 160, 165, 164, 160, 166,
+ 167, 166, 166, 160, 160, 160, 160, 161, 160, 161,
+ 160, 168, 160, 163, 160, 163, 169, 170, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 164, 160, 160,
+ 160, 160, 160, 160, 164, 166, 167, 166, 160, 160,
+ 160, 171, 168, 172, 163, 169, 169, 170, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 166, 160, 160,
+ 171, 172, 160, 160, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 166, 160, 160, 160, 160, 160, 160, 160,
+ 160, 173, 160, 166, 160, 160, 160, 160, 160, 160,
+ 173, 160, 173, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 174, 160, 160, 160, 174, 160, 174, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 0,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160
} ;
-static yyconst flex_int16_t yy_nxt[281] =
+static yyconst flex_int16_t yy_nxt[441] =
{ 0,
- 12, 13, 14, 15, 12, 16, 12, 12, 17, 12,
- 12, 12, 12, 18, 18, 18, 12, 12, 18, 18,
- 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
- 18, 12, 12, 19, 20, 20, 20, 92, 21, 25,
- 26, 26, 22, 21, 21, 21, 21, 12, 13, 14,
- 15, 23, 16, 23, 23, 19, 23, 23, 23, 12,
- 24, 24, 24, 12, 12, 24, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, 24, 24, 12, 12,
- 25, 26, 26, 27, 27, 27, 27, 29, 43, 29,
- 43, 43, 45, 45, 45, 50, 39, 59, 46, 93,
-
- 30, 33, 30, 34, 45, 45, 45, 27, 27, 68,
- 43, 91, 43, 43, 69, 35, 87, 36, 39, 37,
- 42, 42, 42, 39, 42, 45, 45, 45, 89, 42,
- 42, 42, 42, 85, 85, 86, 85, 85, 86, 89,
- 84, 90, 83, 82, 81, 80, 79, 78, 77, 76,
- 75, 74, 90, 28, 28, 28, 28, 28, 28, 28,
- 28, 31, 31, 31, 38, 38, 38, 38, 41, 73,
- 41, 43, 72, 43, 71, 43, 43, 44, 33, 44,
- 44, 44, 44, 47, 69, 47, 47, 49, 49, 49,
- 49, 49, 49, 49, 49, 51, 51, 51, 51, 51,
-
- 51, 51, 51, 57, 70, 57, 58, 58, 58, 67,
- 58, 58, 88, 88, 88, 88, 88, 88, 88, 88,
- 34, 66, 65, 64, 63, 62, 61, 60, 52, 50,
- 39, 56, 39, 55, 54, 53, 52, 50, 48, 93,
- 40, 39, 32, 93, 19, 19, 11, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93
+ 12, 13, 14, 15, 16, 12, 17, 18, 12, 12,
+ 12, 19, 12, 12, 12, 12, 20, 21, 22, 23,
+ 23, 23, 23, 23, 12, 12, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 12, 24, 12, 25, 34, 35, 35, 25,
+ 81, 26, 26, 27, 27, 27, 34, 35, 35, 82,
+ 28, 36, 36, 36, 36, 159, 29, 28, 28, 28,
+ 28, 12, 13, 14, 15, 16, 30, 17, 18, 30,
+ 30, 30, 26, 30, 30, 30, 12, 20, 21, 22,
+ 31, 31, 31, 31, 31, 32, 12, 31, 31, 31,
+
+ 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+ 31, 31, 31, 12, 24, 12, 39, 41, 45, 47,
+ 53, 54, 48, 56, 57, 61, 61, 47, 66, 45,
+ 48, 66, 66, 66, 39, 46, 40, 49, 59, 50,
+ 158, 51, 122, 52, 157, 49, 46, 50, 136, 63,
+ 137, 52, 156, 43, 40, 62, 65, 65, 65, 59,
+ 61, 61, 123, 65, 75, 69, 69, 69, 36, 36,
+ 65, 65, 65, 65, 70, 71, 72, 69, 69, 69,
+ 45, 46, 61, 61, 109, 77, 70, 71, 93, 110,
+ 68, 70, 71, 85, 85, 85, 66, 46, 155, 66,
+
+ 66, 66, 69, 69, 69, 122, 59, 100, 100, 61,
+ 61, 70, 71, 100, 100, 148, 112, 154, 85, 85,
+ 85, 61, 61, 129, 129, 123, 129, 129, 135, 135,
+ 135, 142, 142, 148, 143, 149, 153, 135, 135, 135,
+ 142, 142, 160, 143, 152, 151, 150, 146, 145, 144,
+ 141, 140, 139, 149, 38, 38, 38, 38, 38, 38,
+ 38, 38, 42, 138, 134, 133, 42, 42, 44, 44,
+ 44, 44, 44, 44, 44, 44, 58, 58, 58, 58,
+ 64, 132, 64, 66, 131, 130, 66, 160, 66, 66,
+ 67, 128, 127, 67, 67, 67, 67, 73, 126, 73,
+
+ 73, 76, 76, 76, 76, 76, 76, 76, 76, 78,
+ 78, 78, 78, 78, 78, 78, 78, 91, 125, 91,
+ 92, 124, 92, 92, 120, 92, 92, 121, 121, 121,
+ 121, 121, 121, 121, 121, 147, 147, 147, 147, 147,
+ 147, 147, 147, 119, 118, 117, 116, 115, 47, 114,
+ 110, 113, 111, 108, 107, 106, 48, 105, 104, 89,
+ 103, 102, 101, 99, 98, 97, 96, 95, 94, 79,
+ 77, 90, 89, 88, 59, 87, 86, 59, 84, 83,
+ 80, 79, 77, 74, 160, 60, 59, 55, 37, 160,
+ 33, 25, 26, 25, 11, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
} ;
-static yyconst flex_int16_t yy_chk[281] =
+static yyconst flex_int16_t yy_chk[441] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 5, 5, 5, 5, 91, 5, 9,
- 9, 9, 5, 5, 5, 5, 5, 7, 7, 7,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 4, 9, 9, 9, 10,
+ 50, 4, 5, 5, 5, 5, 10, 10, 10, 50,
+ 5, 13, 13, 14, 14, 158, 5, 5, 5, 5,
+ 5, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 10, 10, 10, 13, 13, 14, 14, 15, 24, 28,
- 24, 24, 25, 25, 25, 50, 24, 50, 25, 90,
-
- 15, 17, 28, 17, 26, 26, 26, 27, 27, 62,
- 44, 87, 44, 44, 62, 17, 84, 17, 44, 17,
- 21, 21, 21, 21, 21, 45, 45, 45, 86, 21,
- 21, 21, 21, 83, 83, 83, 85, 85, 85, 88,
- 82, 86, 81, 78, 77, 76, 75, 74, 73, 72,
- 71, 70, 88, 94, 94, 94, 94, 94, 94, 94,
- 94, 95, 95, 95, 96, 96, 96, 96, 97, 69,
- 97, 98, 68, 98, 67, 98, 98, 99, 66, 99,
- 99, 99, 99, 100, 64, 100, 100, 101, 101, 101,
- 101, 101, 101, 101, 101, 102, 102, 102, 102, 102,
-
- 102, 102, 102, 103, 63, 103, 104, 104, 104, 61,
- 104, 104, 105, 105, 105, 105, 105, 105, 105, 105,
- 60, 59, 58, 56, 55, 54, 53, 52, 51, 49,
- 42, 40, 38, 37, 36, 35, 34, 33, 32, 30,
- 19, 18, 16, 11, 4, 3, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93,
- 93, 93, 93, 93, 93, 93, 93, 93, 93, 93
+ 7, 7, 7, 7, 7, 7, 16, 17, 18, 19,
+ 20, 20, 19, 22, 22, 25, 25, 26, 31, 44,
+ 26, 31, 31, 31, 38, 18, 16, 19, 31, 19,
+ 157, 19, 112, 19, 156, 26, 44, 26, 130, 26,
+ 130, 26, 155, 17, 38, 25, 28, 28, 28, 28,
+ 33, 33, 112, 28, 46, 34, 34, 34, 36, 36,
+ 28, 28, 28, 28, 34, 34, 34, 35, 35, 35,
+ 75, 46, 61, 61, 98, 77, 35, 35, 77, 98,
+ 33, 91, 91, 61, 61, 61, 67, 75, 152, 67,
+
+ 67, 67, 69, 69, 69, 121, 67, 85, 85, 113,
+ 113, 69, 69, 100, 100, 143, 100, 151, 85, 85,
+ 85, 114, 114, 122, 122, 121, 129, 129, 135, 135,
+ 135, 138, 138, 147, 138, 143, 150, 129, 129, 129,
+ 142, 142, 149, 142, 146, 145, 144, 141, 140, 139,
+ 137, 136, 134, 147, 161, 161, 161, 161, 161, 161,
+ 161, 161, 162, 133, 128, 127, 162, 162, 163, 163,
+ 163, 163, 163, 163, 163, 163, 164, 164, 164, 164,
+ 165, 126, 165, 166, 125, 124, 166, 123, 166, 166,
+ 167, 120, 119, 167, 167, 167, 167, 168, 118, 168,
+
+ 168, 169, 169, 169, 169, 169, 169, 169, 169, 170,
+ 170, 170, 170, 170, 170, 170, 170, 171, 117, 171,
+ 172, 116, 172, 172, 111, 172, 172, 173, 173, 173,
+ 173, 173, 173, 173, 173, 174, 174, 174, 174, 174,
+ 174, 174, 174, 110, 109, 108, 107, 106, 105, 103,
+ 102, 101, 99, 97, 96, 95, 94, 93, 92, 90,
+ 88, 87, 86, 84, 83, 82, 81, 80, 79, 78,
+ 76, 71, 70, 68, 65, 63, 62, 58, 52, 51,
+ 49, 48, 47, 43, 40, 24, 23, 21, 15, 11,
+ 8, 6, 3, 2, 160, 160, 160, 160, 160, 160,
+
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160,
+ 160, 160, 160, 160, 160, 160, 160, 160, 160, 160
} ;
static yy_state_type yy_last_accepting_state;
@@ -540,6 +607,7 @@ int yy_flex_debug = 0;
#define YY_MORE_ADJ 0
#define YY_RESTORE_YY_MORE_OFFSET
char *yytext;
+#line 1 "dtc-lexer.l"
/*
* (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
*
@@ -561,6 +629,10 @@ char *yytext;
*/
#define YY_NO_INPUT 1
+
+
+
+#line 38 "dtc-lexer.l"
#include "dtc.h"
#include "srcpos.h"
#include "dtc-parser.tab.h"
@@ -588,6 +660,7 @@ static int dts_version = 1;
static void push_input_file(const char *filename);
static int pop_input_file(void);
+#line 664 "dtc-lexer.lex.c"
#define INITIAL 0
#define INCLUDE 1
@@ -670,7 +743,12 @@ static int input (void );
/* Amount of stuff to slurp up with each read. */
#ifndef YY_READ_BUF_SIZE
+#ifdef __ia64__
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
+#else
#define YY_READ_BUF_SIZE 8192
+#endif /* __ia64__ */
#endif
/* Copy whatever the last rule matched to the standard output. */
@@ -689,7 +767,7 @@ static int input (void );
if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
{ \
int c = '*'; \
- unsigned n; \
+ size_t n; \
for ( n = 0; n < max_size && \
(c = getc( yyin )) != EOF && c != '\n'; ++n ) \
buf[n] = (char) c; \
@@ -761,6 +839,9 @@ extern int yylex (void);
#endif
#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
YY_USER_ACTION
/** The main scanner function which does all the work.
@@ -771,6 +852,10 @@ YY_DECL
register char *yy_cp, *yy_bp;
register int yy_act;
+#line 67 "dtc-lexer.l"
+
+#line 858 "dtc-lexer.lex.c"
+
if ( !(yy_init) )
{
(yy_init) = 1;
@@ -810,6 +895,7 @@ YY_DECL
yy_bp = yy_cp;
yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
yy_match:
do
{
@@ -822,13 +908,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 94 )
+ if ( yy_current_state >= 161 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_current_state != 93 );
+ while ( yy_current_state != 160 );
yy_cp = (yy_last_accepting_cpos);
yy_current_state = (yy_last_accepting_state);
@@ -851,26 +937,54 @@ do_action: /* This label is used only to access EOF actions. */
case 1:
/* rule 1 can match eol */
YY_RULE_SETUP
+#line 68 "dtc-lexer.l"
{
char *name = strchr(yytext, '\"') + 1;
yytext[yyleng-1] = '\0';
push_input_file(name);
}
YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 74 "dtc-lexer.l"
+{
+ char *line, *tmp, *fn;
+ /* skip text before line # */
+ line = yytext;
+ while (!isdigit(*line))
+ line++;
+ /* skip digits in line # */
+ tmp = line;
+ while (!isspace(*tmp))
+ tmp++;
+ /* "NULL"-terminate line # */
+ *tmp = '\0';
+ /* start of filename */
+ fn = strchr(tmp + 1, '"') + 1;
+ /* strip trailing " from filename */
+ tmp = strchr(fn, '"');
+ *tmp = 0;
+ /* -1 since #line is the number of the next line */
+ srcpos_set_line(xstrdup(fn), atoi(line) - 1);
+ }
+ YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(INCLUDE):
case YY_STATE_EOF(BYTESTRING):
case YY_STATE_EOF(PROPNODENAME):
case YY_STATE_EOF(V1):
+#line 95 "dtc-lexer.l"
{
if (!pop_input_file()) {
yyterminate();
}
}
YY_BREAK
-case 2:
-/* rule 2 can match eol */
+case 3:
+/* rule 3 can match eol */
YY_RULE_SETUP
+#line 101 "dtc-lexer.l"
{
DPRINT("String: %s\n", yytext);
yylval.data = data_copy_escape_string(yytext+1,
@@ -878,8 +992,9 @@ YY_RULE_SETUP
return DT_STRING;
}
YY_BREAK
-case 3:
+case 4:
YY_RULE_SETUP
+#line 108 "dtc-lexer.l"
{
DPRINT("Keyword: /dts-v1/\n");
dts_version = 1;
@@ -887,16 +1002,47 @@ YY_RULE_SETUP
return DT_V1;
}
YY_BREAK
-case 4:
+case 5:
YY_RULE_SETUP
+#line 115 "dtc-lexer.l"
{
DPRINT("Keyword: /memreserve/\n");
BEGIN_DEFAULT();
return DT_MEMRESERVE;
}
YY_BREAK
-case 5:
+case 6:
+YY_RULE_SETUP
+#line 121 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /bits/\n");
+ BEGIN_DEFAULT();
+ return DT_BITS;
+ }
+ YY_BREAK
+case 7:
YY_RULE_SETUP
+#line 127 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /delete-property/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_PROP;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 134 "dtc-lexer.l"
+{
+ DPRINT("Keyword: /delete-node/\n");
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ return DT_DEL_NODE;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 141 "dtc-lexer.l"
{
DPRINT("Label: %s\n", yytext);
yylval.labelref = xstrdup(yytext);
@@ -904,24 +1050,38 @@ YY_RULE_SETUP
return DT_LABEL;
}
YY_BREAK
-case 6:
+case 10:
YY_RULE_SETUP
+#line 148 "dtc-lexer.l"
{
yylval.literal = xstrdup(yytext);
DPRINT("Literal: '%s'\n", yylval.literal);
return DT_LITERAL;
}
YY_BREAK
-case 7:
+case 11:
+/* rule 11 can match eol */
+YY_RULE_SETUP
+#line 154 "dtc-lexer.l"
+{
+ yytext[yyleng-1] = '\0';
+ yylval.literal = xstrdup(yytext+1);
+ DPRINT("Character literal: %s\n", yylval.literal);
+ return DT_CHAR_LITERAL;
+ }
+ YY_BREAK
+case 12:
YY_RULE_SETUP
+#line 161 "dtc-lexer.l"
{ /* label reference */
DPRINT("Ref: %s\n", yytext+1);
yylval.labelref = xstrdup(yytext+1);
return DT_REF;
}
YY_BREAK
-case 8:
+case 13:
YY_RULE_SETUP
+#line 167 "dtc-lexer.l"
{ /* new-style path reference */
yytext[yyleng-1] = '\0';
DPRINT("Ref: %s\n", yytext+2);
@@ -929,55 +1089,104 @@ YY_RULE_SETUP
return DT_REF;
}
YY_BREAK
-case 9:
+case 14:
YY_RULE_SETUP
+#line 174 "dtc-lexer.l"
{
yylval.byte = strtol(yytext, NULL, 16);
DPRINT("Byte: %02x\n", (int)yylval.byte);
return DT_BYTE;
}
YY_BREAK
-case 10:
+case 15:
YY_RULE_SETUP
+#line 180 "dtc-lexer.l"
{
DPRINT("/BYTESTRING\n");
BEGIN_DEFAULT();
return ']';
}
YY_BREAK
-case 11:
+case 16:
YY_RULE_SETUP
+#line 186 "dtc-lexer.l"
{
DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = xstrdup(yytext);
+ yylval.propnodename = xstrdup((yytext[0] == '\\') ?
+ yytext + 1 : yytext);
BEGIN_DEFAULT();
return DT_PROPNODENAME;
}
YY_BREAK
-case 12:
+case 17:
YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
{
DPRINT("Binary Include\n");
return DT_INCBIN;
}
YY_BREAK
-case 13:
-/* rule 13 can match eol */
+case 18:
+/* rule 18 can match eol */
YY_RULE_SETUP
+#line 199 "dtc-lexer.l"
/* eat whitespace */
YY_BREAK
-case 14:
-/* rule 14 can match eol */
+case 19:
+/* rule 19 can match eol */
YY_RULE_SETUP
+#line 200 "dtc-lexer.l"
/* eat C-style comments */
YY_BREAK
-case 15:
-/* rule 15 can match eol */
+case 20:
+/* rule 20 can match eol */
YY_RULE_SETUP
+#line 201 "dtc-lexer.l"
/* eat C++-style comments */
YY_BREAK
-case 16:
+case 21:
YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+{ return DT_LSHIFT; };
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 204 "dtc-lexer.l"
+{ return DT_RSHIFT; };
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{ return DT_LE; };
+ YY_BREAK
+case 24:
+YY_RULE_SETUP
+#line 206 "dtc-lexer.l"
+{ return DT_GE; };
+ YY_BREAK
+case 25:
+YY_RULE_SETUP
+#line 207 "dtc-lexer.l"
+{ return DT_EQ; };
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 208 "dtc-lexer.l"
+{ return DT_NE; };
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 209 "dtc-lexer.l"
+{ return DT_AND; };
+ YY_BREAK
+case 28:
+YY_RULE_SETUP
+#line 210 "dtc-lexer.l"
+{ return DT_OR; };
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 212 "dtc-lexer.l"
{
DPRINT("Char: %c (\\x%02x)\n", yytext[0],
(unsigned)yytext[0]);
@@ -993,10 +1202,12 @@ YY_RULE_SETUP
return yytext[0];
}
YY_BREAK
-case 17:
+case 30:
YY_RULE_SETUP
+#line 227 "dtc-lexer.l"
ECHO;
YY_BREAK
+#line 1211 "dtc-lexer.lex.c"
case YY_END_OF_BUFFER:
{
@@ -1275,6 +1486,7 @@ static int yy_get_next_buffer (void)
register char *yy_cp;
yy_current_state = (yy_start);
+ yy_current_state += YY_AT_BOL();
for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
{
@@ -1287,7 +1499,7 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 94 )
+ if ( yy_current_state >= 161 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1315,11 +1527,11 @@ static int yy_get_next_buffer (void)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 94 )
+ if ( yy_current_state >= 161 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 93);
+ yy_is_jam = (yy_current_state == 160);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -1394,6 +1606,8 @@ static int yy_get_next_buffer (void)
*(yy_c_buf_p) = '\0'; /* preserve yytext */
(yy_hold_char) = *++(yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+
return c;
}
#endif /* ifndef YY_NO_INPUT */
@@ -1712,8 +1926,8 @@ YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
* scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
*
* @return the newly allocated buffer state object.
*/
@@ -1952,6 +2166,10 @@ void yyfree (void * ptr )
#define YYTABLES_NAME "yytables"
+#line 227 "dtc-lexer.l"
+
+
+
static void push_input_file(const char *filename)
{
assert(filename);
@@ -1963,6 +2181,7 @@ static void push_input_file(const char *filename)
yypush_buffer_state(yy_create_buffer(yyin,YY_BUF_SIZE));
}
+
static int pop_input_file(void)
{
if (srcfile_pop() == 0)
diff --git a/scripts/dtc/dtc-parser.tab.c_shipped b/scripts/dtc/dtc-parser.tab.c_shipped
index b05921e1e84..4af55900a15 100644
--- a/scripts/dtc/dtc-parser.tab.c_shipped
+++ b/scripts/dtc/dtc-parser.tab.c_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton implementation for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -45,7 +46,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.4.3"
+#define YYBISON_VERSION "2.4.1"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -66,6 +67,8 @@
/* Copy the first part of user declarations. */
+/* Line 189 of yacc.c */
+#line 21 "dtc-parser.y"
#include <stdio.h>
@@ -82,12 +85,15 @@ extern struct boot_info *the_boot_info;
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
+/* Line 189 of yacc.c */
+#line 93 "dtc-parser.tab.c"
/* Enabling traces. */
#ifndef YYDEBUG
-# define YYDEBUG 1
+# define YYDEBUG 0
#endif
/* Enabling verbose error messages. */
@@ -112,14 +118,26 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
enum yytokentype {
DT_V1 = 258,
DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_BASE = 262,
- DT_BYTE = 263,
- DT_STRING = 264,
- DT_LABEL = 265,
- DT_REF = 266,
- DT_INCBIN = 267
+ DT_LSHIFT = 260,
+ DT_RSHIFT = 261,
+ DT_LE = 262,
+ DT_GE = 263,
+ DT_EQ = 264,
+ DT_NE = 265,
+ DT_AND = 266,
+ DT_OR = 267,
+ DT_BITS = 268,
+ DT_DEL_PROP = 269,
+ DT_DEL_NODE = 270,
+ DT_PROPNODENAME = 271,
+ DT_LITERAL = 272,
+ DT_CHAR_LITERAL = 273,
+ DT_BASE = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
@@ -129,6 +147,8 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
typedef union YYSTYPE
{
+/* Line 214 of yacc.c */
+#line 40 "dtc-parser.y"
char *propnodename;
char *literal;
@@ -137,16 +157,22 @@ typedef union YYSTYPE
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
+/* Line 214 of yacc.c */
+#line 176 "dtc-parser.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -157,6 +183,8 @@ typedef union YYSTYPE
/* Copy the second part of user declarations. */
+/* Line 264 of yacc.c */
+#line 188 "dtc-parser.tab.c"
#ifdef short
# undef short
@@ -206,7 +234,7 @@ typedef short int yytype_int16;
#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
#ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
# define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -371,20 +399,20 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 4
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 56
+#define YYLAST 133
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 25
+#define YYNTOKENS 48
/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 16
+#define YYNNTS 28
/* YYNRULES -- Number of rules. */
-#define YYNRULES 39
+#define YYNRULES 79
/* YYNRULES -- Number of states. */
-#define YYNSTATES 67
+#define YYNSTATES 141
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 267
+#define YYMAXUTOK 279
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -395,16 +423,16 @@ static const yytype_uint8 yytranslate[] =
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 22, 24, 2, 2, 23, 2, 2, 14, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 13,
- 18, 17, 19, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 47, 2, 2, 2, 45, 41, 2,
+ 33, 35, 44, 42, 34, 43, 2, 26, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 38, 25,
+ 36, 29, 30, 37, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 20, 2, 21, 2, 2, 2, 2, 2, 2,
+ 2, 31, 2, 32, 40, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 15, 2, 16, 2, 2, 2, 2,
+ 2, 2, 2, 27, 39, 28, 46, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -418,45 +446,68 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24
};
#if YYDEBUG
/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
YYRHS. */
-static const yytype_uint8 yyprhs[] =
+static const yytype_uint16 yyprhs[] =
{
- 0, 0, 3, 8, 9, 12, 17, 20, 22, 25,
- 29, 33, 39, 40, 43, 48, 51, 54, 57, 62,
- 67, 70, 80, 86, 89, 90, 93, 96, 97, 100,
- 103, 106, 108, 109, 112, 115, 116, 119, 122, 125
+ 0, 0, 3, 8, 9, 12, 17, 20, 23, 27,
+ 31, 36, 42, 43, 46, 51, 54, 58, 61, 64,
+ 68, 73, 76, 86, 92, 95, 96, 99, 102, 106,
+ 108, 111, 114, 117, 119, 121, 125, 127, 129, 135,
+ 137, 141, 143, 147, 149, 153, 155, 159, 161, 165,
+ 167, 171, 175, 177, 181, 185, 189, 193, 197, 201,
+ 203, 207, 211, 213, 217, 221, 225, 227, 229, 232,
+ 235, 238, 239, 242, 245, 246, 249, 252, 255, 259
};
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
static const yytype_int8 yyrhs[] =
{
- 26, 0, -1, 3, 13, 27, 30, -1, -1, 28,
- 27, -1, 4, 29, 29, 13, -1, 10, 28, -1,
- 6, -1, 14, 31, -1, 30, 14, 31, -1, 30,
- 11, 31, -1, 15, 32, 39, 16, 13, -1, -1,
- 32, 33, -1, 5, 17, 34, 13, -1, 5, 13,
- -1, 10, 33, -1, 35, 9, -1, 35, 18, 36,
- 19, -1, 35, 20, 38, 21, -1, 35, 11, -1,
- 35, 12, 22, 9, 23, 29, 23, 29, 24, -1,
- 35, 12, 22, 9, 24, -1, 34, 10, -1, -1,
- 34, 23, -1, 35, 10, -1, -1, 36, 37, -1,
- 36, 11, -1, 36, 10, -1, 6, -1, -1, 38,
- 8, -1, 38, 10, -1, -1, 40, 39, -1, 40,
- 33, -1, 5, 31, -1, 10, 40, -1
+ 49, 0, -1, 3, 25, 50, 52, -1, -1, 51,
+ 50, -1, 4, 59, 59, 25, -1, 22, 51, -1,
+ 26, 53, -1, 52, 26, 53, -1, 52, 23, 53,
+ -1, 52, 15, 23, 25, -1, 27, 54, 74, 28,
+ 25, -1, -1, 54, 55, -1, 16, 29, 56, 25,
+ -1, 16, 25, -1, 14, 16, 25, -1, 22, 55,
+ -1, 57, 21, -1, 57, 58, 30, -1, 57, 31,
+ 73, 32, -1, 57, 23, -1, 57, 24, 33, 21,
+ 34, 59, 34, 59, 35, -1, 57, 24, 33, 21,
+ 35, -1, 56, 22, -1, -1, 56, 34, -1, 57,
+ 22, -1, 13, 17, 36, -1, 36, -1, 58, 59,
+ -1, 58, 23, -1, 58, 22, -1, 17, -1, 18,
+ -1, 33, 60, 35, -1, 61, -1, 62, -1, 62,
+ 37, 60, 38, 61, -1, 63, -1, 62, 12, 63,
+ -1, 64, -1, 63, 11, 64, -1, 65, -1, 64,
+ 39, 65, -1, 66, -1, 65, 40, 66, -1, 67,
+ -1, 66, 41, 67, -1, 68, -1, 67, 9, 68,
+ -1, 67, 10, 68, -1, 69, -1, 68, 36, 69,
+ -1, 68, 30, 69, -1, 68, 7, 69, -1, 68,
+ 8, 69, -1, 69, 5, 70, -1, 69, 6, 70,
+ -1, 70, -1, 70, 42, 71, -1, 70, 43, 71,
+ -1, 71, -1, 71, 44, 72, -1, 71, 26, 72,
+ -1, 71, 45, 72, -1, 72, -1, 59, -1, 43,
+ 72, -1, 46, 72, -1, 47, 72, -1, -1, 73,
+ 20, -1, 73, 22, -1, -1, 75, 74, -1, 75,
+ 55, -1, 16, 53, -1, 15, 16, 25, -1, 22,
+ 75, -1
};
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 86, 86, 95, 98, 105, 109, 117, 124, 128,
- 132, 145, 153, 156, 163, 167, 171, 179, 183, 187,
- 191, 195, 212, 222, 230, 233, 237, 245, 248, 252,
- 257, 264, 272, 275, 279, 287, 290, 294, 302, 306
+ 0, 109, 109, 118, 121, 128, 132, 140, 144, 148,
+ 158, 172, 180, 183, 190, 194, 198, 202, 210, 214,
+ 218, 222, 226, 243, 253, 261, 264, 268, 275, 290,
+ 295, 315, 329, 336, 340, 344, 351, 355, 356, 360,
+ 361, 365, 366, 370, 371, 375, 376, 380, 381, 385,
+ 386, 387, 391, 392, 393, 394, 395, 399, 400, 401,
+ 405, 406, 407, 411, 412, 413, 414, 418, 419, 420,
+ 421, 426, 429, 433, 441, 444, 448, 456, 460, 464
};
#endif
@@ -465,13 +516,19 @@ static const yytype_uint16 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
- "DT_PROPNODENAME", "DT_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING",
- "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='",
- "'<'", "'>'", "'['", "']'", "'('", "','", "')'", "$accept", "sourcefile",
- "memreserves", "memreserve", "addr", "devicetree", "nodedef", "proplist",
- "propdef", "propdata", "propdataprefix", "celllist", "cellval",
- "bytestring", "subnodes", "subnode", 0
+ "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE", "DT_LSHIFT",
+ "DT_RSHIFT", "DT_LE", "DT_GE", "DT_EQ", "DT_NE", "DT_AND", "DT_OR",
+ "DT_BITS", "DT_DEL_PROP", "DT_DEL_NODE", "DT_PROPNODENAME", "DT_LITERAL",
+ "DT_CHAR_LITERAL", "DT_BASE", "DT_BYTE", "DT_STRING", "DT_LABEL",
+ "DT_REF", "DT_INCBIN", "';'", "'/'", "'{'", "'}'", "'='", "'>'", "'['",
+ "']'", "'('", "','", "')'", "'<'", "'?'", "':'", "'|'", "'^'", "'&'",
+ "'+'", "'-'", "'*'", "'%'", "'~'", "'!'", "$accept", "sourcefile",
+ "memreserves", "memreserve", "devicetree", "nodedef", "proplist",
+ "propdef", "propdata", "propdataprefix", "arrayprefix", "integer_prim",
+ "integer_expr", "integer_trinary", "integer_or", "integer_and",
+ "integer_bitor", "integer_bitxor", "integer_bitand", "integer_eq",
+ "integer_rela", "integer_shift", "integer_add", "integer_mul",
+ "integer_unary", "bytestring", "subnodes", "subnode", 0
};
#endif
@@ -481,27 +538,37 @@ static const char *const yytname[] =
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 59, 47, 123, 125, 61, 60, 62,
- 91, 93, 40, 44, 41
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 59, 47, 123, 125, 61,
+ 62, 91, 93, 40, 44, 41, 60, 63, 58, 124,
+ 94, 38, 43, 45, 42, 37, 126, 33
};
# endif
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 25, 26, 27, 27, 28, 28, 29, 30, 30,
- 30, 31, 32, 32, 33, 33, 33, 34, 34, 34,
- 34, 34, 34, 34, 35, 35, 35, 36, 36, 36,
- 36, 37, 38, 38, 38, 39, 39, 39, 40, 40
+ 0, 48, 49, 50, 50, 51, 51, 52, 52, 52,
+ 52, 53, 54, 54, 55, 55, 55, 55, 56, 56,
+ 56, 56, 56, 56, 56, 57, 57, 57, 58, 58,
+ 58, 58, 58, 59, 59, 59, 60, 61, 61, 62,
+ 62, 63, 63, 64, 64, 65, 65, 66, 66, 67,
+ 67, 67, 68, 68, 68, 68, 68, 69, 69, 69,
+ 70, 70, 70, 71, 71, 71, 71, 72, 72, 72,
+ 72, 73, 73, 73, 74, 74, 74, 75, 75, 75
};
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
static const yytype_uint8 yyr2[] =
{
- 0, 2, 4, 0, 2, 4, 2, 1, 2, 3,
- 3, 5, 0, 2, 4, 2, 2, 2, 4, 4,
- 2, 9, 5, 2, 0, 2, 2, 0, 2, 2,
- 2, 1, 0, 2, 2, 0, 2, 2, 2, 2
+ 0, 2, 4, 0, 2, 4, 2, 2, 3, 3,
+ 4, 5, 0, 2, 4, 2, 3, 2, 2, 3,
+ 4, 2, 9, 5, 2, 0, 2, 2, 3, 1,
+ 2, 2, 2, 1, 1, 3, 1, 1, 5, 1,
+ 3, 1, 3, 1, 3, 1, 3, 1, 3, 1,
+ 3, 3, 1, 3, 3, 3, 3, 3, 3, 1,
+ 3, 3, 1, 3, 3, 3, 1, 1, 2, 2,
+ 2, 0, 2, 2, 0, 2, 2, 2, 3, 2
};
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -509,41 +576,59 @@ static const yytype_uint8 yyr2[] =
means the default is an error. */
static const yytype_uint8 yydefact[] =
{
- 0, 0, 0, 3, 1, 0, 0, 0, 3, 7,
- 0, 6, 0, 2, 4, 0, 12, 8, 0, 0,
- 5, 35, 10, 9, 0, 0, 13, 0, 35, 15,
- 24, 38, 16, 39, 0, 37, 36, 0, 0, 11,
- 23, 14, 25, 17, 26, 20, 0, 27, 32, 0,
- 0, 0, 0, 31, 30, 29, 18, 28, 33, 34,
- 19, 0, 22, 0, 0, 0, 21
+ 0, 0, 0, 3, 1, 0, 0, 0, 3, 33,
+ 34, 0, 0, 6, 0, 2, 4, 0, 0, 0,
+ 67, 0, 36, 37, 39, 41, 43, 45, 47, 49,
+ 52, 59, 62, 66, 0, 12, 7, 0, 0, 0,
+ 68, 69, 70, 35, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 5, 74, 0, 9, 8, 40, 0,
+ 42, 44, 46, 48, 50, 51, 55, 56, 54, 53,
+ 57, 58, 60, 61, 64, 63, 65, 0, 0, 0,
+ 0, 13, 0, 74, 10, 0, 0, 0, 15, 25,
+ 77, 17, 79, 0, 76, 75, 38, 16, 78, 0,
+ 0, 11, 24, 14, 26, 0, 18, 27, 21, 0,
+ 71, 29, 0, 0, 0, 0, 32, 31, 19, 30,
+ 28, 0, 72, 73, 20, 0, 23, 0, 0, 0,
+ 22
};
/* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int8 yydefgoto[] =
{
- -1, 2, 7, 8, 10, 13, 17, 21, 26, 37,
- 38, 50, 57, 51, 27, 28
+ -1, 2, 7, 8, 15, 36, 64, 91, 109, 110,
+ 122, 20, 21, 22, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31, 32, 33, 125, 92, 93
};
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
STATE-NUM. */
-#define YYPACT_NINF -12
+#define YYPACT_NINF -78
static const yytype_int8 yypact[] =
{
- 10, -11, 18, -1, -12, 22, -1, 15, -1, -12,
- 22, -12, 20, 1, -12, 17, -12, -12, 20, 20,
- -12, 6, -12, -12, 21, 6, -12, 23, 6, -12,
- -12, -12, -12, -12, 28, -12, -12, -6, 13, -12,
- -12, -12, -12, -12, -12, -12, 24, -12, -12, 33,
- -5, 0, -4, -12, -12, -12, -12, -12, -12, -12,
- -12, 22, -12, 25, 22, 19, -12
+ 22, 11, 51, 10, -78, 23, 10, 2, 10, -78,
+ -78, -9, 23, -78, 30, 38, -78, -9, -9, -9,
+ -78, 35, -78, -6, 52, 29, 48, 49, 33, 3,
+ 71, 36, 0, -78, 64, -78, -78, 68, 30, 30,
+ -78, -78, -78, -78, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
+ -9, -9, -9, -78, 44, 67, -78, -78, 52, 55,
+ 29, 48, 49, 33, 3, 3, 71, 71, 71, 71,
+ 36, 36, 0, 0, -78, -78, -78, 78, 79, 42,
+ 44, -78, 69, 44, -78, -9, 73, 74, -78, -78,
+ -78, -78, -78, 75, -78, -78, -78, -78, -78, -7,
+ -1, -78, -78, -78, -78, 84, -78, -78, -78, 63,
+ -78, -78, 32, 66, 82, -3, -78, -78, -78, -78,
+ -78, 46, -78, -78, -78, 23, -78, 70, 23, 72,
+ -78
};
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -12, -12, 36, 39, -10, -12, 8, -12, 12, -12,
- -12, -12, -12, -12, 27, 31
+ -78, -78, 97, 100, -78, -37, -78, -77, -78, -78,
+ -78, -5, 65, 13, -78, 76, 77, 62, 80, 83,
+ 34, 20, 26, 28, -14, -78, 18, 24
};
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
@@ -553,35 +638,59 @@ static const yytype_int8 yypgoto[] =
#define YYTABLE_NINF -1
static const yytype_uint8 yytable[] =
{
- 15, 53, 3, 5, 40, 54, 55, 41, 58, 6,
- 59, 24, 18, 1, 56, 19, 25, 42, 4, 61,
- 62, 60, 43, 44, 45, 46, 22, 23, 9, 12,
- 20, 47, 31, 48, 29, 16, 16, 32, 30, 34,
- 35, 39, 52, 66, 14, 11, 49, 0, 64, 0,
- 0, 63, 0, 0, 65, 36, 33
+ 12, 66, 67, 40, 41, 42, 44, 34, 9, 10,
+ 52, 53, 115, 101, 5, 112, 104, 132, 113, 133,
+ 116, 117, 118, 119, 11, 1, 60, 114, 14, 134,
+ 120, 45, 6, 54, 17, 121, 3, 18, 19, 55,
+ 9, 10, 50, 51, 61, 62, 84, 85, 86, 9,
+ 10, 4, 100, 37, 126, 127, 11, 35, 87, 88,
+ 89, 38, 128, 46, 39, 11, 90, 98, 47, 35,
+ 43, 99, 76, 77, 78, 79, 56, 57, 58, 59,
+ 135, 136, 80, 81, 74, 75, 82, 83, 48, 63,
+ 49, 65, 94, 95, 96, 97, 124, 103, 107, 108,
+ 111, 123, 130, 131, 138, 16, 13, 140, 106, 71,
+ 69, 105, 0, 0, 102, 0, 0, 129, 0, 0,
+ 68, 0, 0, 70, 0, 0, 0, 0, 72, 0,
+ 137, 0, 73, 139
};
-static const yytype_int8 yycheck[] =
+static const yytype_int16 yycheck[] =
{
- 10, 6, 13, 4, 10, 10, 11, 13, 8, 10,
- 10, 5, 11, 3, 19, 14, 10, 23, 0, 23,
- 24, 21, 9, 10, 11, 12, 18, 19, 6, 14,
- 13, 18, 24, 20, 13, 15, 15, 25, 17, 16,
- 28, 13, 9, 24, 8, 6, 22, -1, 23, -1,
- -1, 61, -1, -1, 64, 28, 25
+ 5, 38, 39, 17, 18, 19, 12, 12, 17, 18,
+ 7, 8, 13, 90, 4, 22, 93, 20, 25, 22,
+ 21, 22, 23, 24, 33, 3, 26, 34, 26, 32,
+ 31, 37, 22, 30, 43, 36, 25, 46, 47, 36,
+ 17, 18, 9, 10, 44, 45, 60, 61, 62, 17,
+ 18, 0, 89, 15, 22, 23, 33, 27, 14, 15,
+ 16, 23, 30, 11, 26, 33, 22, 25, 39, 27,
+ 35, 29, 52, 53, 54, 55, 5, 6, 42, 43,
+ 34, 35, 56, 57, 50, 51, 58, 59, 40, 25,
+ 41, 23, 25, 38, 16, 16, 33, 28, 25, 25,
+ 25, 17, 36, 21, 34, 8, 6, 35, 95, 47,
+ 45, 93, -1, -1, 90, -1, -1, 122, -1, -1,
+ 44, -1, -1, 46, -1, -1, -1, -1, 48, -1,
+ 135, -1, 49, 138
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 3, 26, 13, 0, 4, 10, 27, 28, 6,
- 29, 28, 14, 30, 27, 29, 15, 31, 11, 14,
- 13, 32, 31, 31, 5, 10, 33, 39, 40, 13,
- 17, 31, 33, 40, 16, 33, 39, 34, 35, 13,
- 10, 13, 23, 9, 10, 11, 12, 18, 20, 22,
- 36, 38, 9, 6, 10, 11, 19, 37, 8, 10,
- 21, 23, 24, 29, 23, 29, 24
+ 0, 3, 49, 25, 0, 4, 22, 50, 51, 17,
+ 18, 33, 59, 51, 26, 52, 50, 43, 46, 47,
+ 59, 60, 61, 62, 63, 64, 65, 66, 67, 68,
+ 69, 70, 71, 72, 59, 27, 53, 15, 23, 26,
+ 72, 72, 72, 35, 12, 37, 11, 39, 40, 41,
+ 9, 10, 7, 8, 30, 36, 5, 6, 42, 43,
+ 26, 44, 45, 25, 54, 23, 53, 53, 63, 60,
+ 64, 65, 66, 67, 68, 68, 69, 69, 69, 69,
+ 70, 70, 71, 71, 72, 72, 72, 14, 15, 16,
+ 22, 55, 74, 75, 25, 38, 16, 16, 25, 29,
+ 53, 55, 75, 28, 55, 74, 61, 25, 25, 56,
+ 57, 25, 22, 25, 34, 13, 21, 22, 23, 24,
+ 31, 36, 58, 17, 33, 73, 22, 23, 30, 59,
+ 36, 21, 20, 22, 32, 34, 35, 59, 34, 59,
+ 35
};
#define yyerrok (yyerrstatus = 0)
@@ -596,18 +705,9 @@ static const yytype_uint8 yystos[] =
/* Like YYERROR except do call yyerror. This remains here temporarily
to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
+ Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
#define YYRECOVERING() (!!yyerrstatus)
@@ -664,7 +764,7 @@ while (YYID (0))
we won't break user code: when these are the locations we know. */
#ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
# define YY_LOCATION_PRINT(File, Loc) \
fprintf (File, "%d.%d-%d.%d", \
(Loc).first_line, (Loc).first_column, \
@@ -1403,6 +1503,8 @@ yyreduce:
{
case 2:
+/* Line 1455 of yacc.c */
+#line 110 "dtc-parser.y"
{
the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node),
guess_boot_cpuid((yyvsp[(4) - (4)].node)));
@@ -1411,6 +1513,8 @@ yyreduce:
case 3:
+/* Line 1455 of yacc.c */
+#line 118 "dtc-parser.y"
{
(yyval.re) = NULL;
;}
@@ -1418,6 +1522,8 @@ yyreduce:
case 4:
+/* Line 1455 of yacc.c */
+#line 122 "dtc-parser.y"
{
(yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
;}
@@ -1425,13 +1531,17 @@ yyreduce:
case 5:
+/* Line 1455 of yacc.c */
+#line 129 "dtc-parser.y"
{
- (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].addr), (yyvsp[(3) - (4)].addr));
+ (yyval.re) = build_reserve_entry((yyvsp[(2) - (4)].integer), (yyvsp[(3) - (4)].integer));
;}
break;
case 6:
+/* Line 1455 of yacc.c */
+#line 133 "dtc-parser.y"
{
add_label(&(yyvsp[(2) - (2)].re)->labels, (yyvsp[(1) - (2)].labelref));
(yyval.re) = (yyvsp[(2) - (2)].re);
@@ -1440,40 +1550,57 @@ yyreduce:
case 7:
+/* Line 1455 of yacc.c */
+#line 141 "dtc-parser.y"
{
- (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+ (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
;}
break;
case 8:
+/* Line 1455 of yacc.c */
+#line 145 "dtc-parser.y"
{
- (yyval.node) = name_node((yyvsp[(2) - (2)].node), "");
+ (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
;}
break;
case 9:
+/* Line 1455 of yacc.c */
+#line 149 "dtc-parser.y"
{
- (yyval.node) = merge_nodes((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node));
+ struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
+
+ if (target)
+ merge_nodes(target, (yyvsp[(3) - (3)].node));
+ else
+ print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref));
+ (yyval.node) = (yyvsp[(1) - (3)].node);
;}
break;
case 10:
+/* Line 1455 of yacc.c */
+#line 159 "dtc-parser.y"
{
- struct node *target = get_node_by_ref((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].labelref));
+ struct node *target = get_node_by_ref((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].labelref));
- if (target)
- merge_nodes(target, (yyvsp[(3) - (3)].node));
+ if (!target)
+ print_error("label or path, '%s', not found", (yyvsp[(3) - (4)].labelref));
else
- print_error("label or path, '%s', not found", (yyvsp[(2) - (3)].labelref));
- (yyval.node) = (yyvsp[(1) - (3)].node);
+ delete_node(target);
+
+ (yyval.node) = (yyvsp[(1) - (4)].node);
;}
break;
case 11:
+/* Line 1455 of yacc.c */
+#line 173 "dtc-parser.y"
{
(yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
;}
@@ -1481,6 +1608,8 @@ yyreduce:
case 12:
+/* Line 1455 of yacc.c */
+#line 180 "dtc-parser.y"
{
(yyval.proplist) = NULL;
;}
@@ -1488,6 +1617,8 @@ yyreduce:
case 13:
+/* Line 1455 of yacc.c */
+#line 184 "dtc-parser.y"
{
(yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
;}
@@ -1495,6 +1626,8 @@ yyreduce:
case 14:
+/* Line 1455 of yacc.c */
+#line 191 "dtc-parser.y"
{
(yyval.prop) = build_property((yyvsp[(1) - (4)].propnodename), (yyvsp[(3) - (4)].data));
;}
@@ -1502,6 +1635,8 @@ yyreduce:
case 15:
+/* Line 1455 of yacc.c */
+#line 195 "dtc-parser.y"
{
(yyval.prop) = build_property((yyvsp[(1) - (2)].propnodename), empty_data);
;}
@@ -1509,62 +1644,85 @@ yyreduce:
case 16:
+/* Line 1455 of yacc.c */
+#line 199 "dtc-parser.y"
{
- add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
- (yyval.prop) = (yyvsp[(2) - (2)].prop);
+ (yyval.prop) = build_property_delete((yyvsp[(2) - (3)].propnodename));
;}
break;
case 17:
+/* Line 1455 of yacc.c */
+#line 203 "dtc-parser.y"
{
- (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+ add_label(&(yyvsp[(2) - (2)].prop)->labels, (yyvsp[(1) - (2)].labelref));
+ (yyval.prop) = (yyvsp[(2) - (2)].prop);
;}
break;
case 18:
+/* Line 1455 of yacc.c */
+#line 211 "dtc-parser.y"
{
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
;}
break;
case 19:
+/* Line 1455 of yacc.c */
+#line 215 "dtc-parser.y"
{
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ (yyval.data) = data_merge((yyvsp[(1) - (3)].data), (yyvsp[(2) - (3)].array).data);
;}
break;
case 20:
+/* Line 1455 of yacc.c */
+#line 219 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
;}
break;
case 21:
+/* Line 1455 of yacc.c */
+#line 223 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 22:
+
+/* Line 1455 of yacc.c */
+#line 227 "dtc-parser.y"
{
FILE *f = srcfile_relative_open((yyvsp[(4) - (9)].data).val, NULL);
struct data d;
- if ((yyvsp[(6) - (9)].addr) != 0)
- if (fseek(f, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+ if ((yyvsp[(6) - (9)].integer) != 0)
+ if (fseek(f, (yyvsp[(6) - (9)].integer), SEEK_SET) != 0)
print_error("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)(yyvsp[(6) - (9)].addr),
+ (unsigned long long)(yyvsp[(6) - (9)].integer),
(yyvsp[(4) - (9)].data).val,
strerror(errno));
- d = data_copy_file(f, (yyvsp[(8) - (9)].addr));
+ d = data_copy_file(f, (yyvsp[(8) - (9)].integer));
(yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
fclose(f);
;}
break;
- case 22:
+ case 23:
+/* Line 1455 of yacc.c */
+#line 244 "dtc-parser.y"
{
FILE *f = srcfile_relative_open((yyvsp[(4) - (5)].data).val, NULL);
struct data d = empty_data;
@@ -1576,122 +1734,383 @@ yyreduce:
;}
break;
- case 23:
-
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
case 24:
+/* Line 1455 of yacc.c */
+#line 254 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 25:
+/* Line 1455 of yacc.c */
+#line 261 "dtc-parser.y"
{
- (yyval.data) = (yyvsp[(1) - (2)].data);
+ (yyval.data) = empty_data;
;}
break;
case 26:
+/* Line 1455 of yacc.c */
+#line 265 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ (yyval.data) = (yyvsp[(1) - (2)].data);
;}
break;
case 27:
+/* Line 1455 of yacc.c */
+#line 269 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 28:
+/* Line 1455 of yacc.c */
+#line 276 "dtc-parser.y"
{
- (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = eval_literal((yyvsp[(2) - (3)].literal), 0, 7);
+
+ if (((yyval.array).bits != 8) &&
+ ((yyval.array).bits != 16) &&
+ ((yyval.array).bits != 32) &&
+ ((yyval.array).bits != 64))
+ {
+ print_error("Only 8, 16, 32 and 64-bit elements"
+ " are currently supported");
+ (yyval.array).bits = 32;
+ }
;}
break;
case 29:
+/* Line 1455 of yacc.c */
+#line 291 "dtc-parser.y"
{
- (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
- (yyvsp[(2) - (2)].labelref)), -1);
+ (yyval.array).data = empty_data;
+ (yyval.array).bits = 32;
;}
break;
case 30:
+/* Line 1455 of yacc.c */
+#line 296 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ if ((yyvsp[(1) - (2)].array).bits < 64) {
+ uint64_t mask = (1ULL << (yyvsp[(1) - (2)].array).bits) - 1;
+ /*
+ * Bits above mask must either be all zero
+ * (positive within range of mask) or all one
+ * (negative and sign-extended). The second
+ * condition is true if when we set all bits
+ * within the mask to one (i.e. | in the
+ * mask), all bits are one.
+ */
+ if (((yyvsp[(2) - (2)].integer) > mask) && (((yyvsp[(2) - (2)].integer) | mask) != -1ULL))
+ print_error(
+ "integer value out of range "
+ "%016lx (%d bits)", (yyvsp[(1) - (2)].array).bits);
+ }
+
+ (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, (yyvsp[(2) - (2)].integer), (yyvsp[(1) - (2)].array).bits);
;}
break;
case 31:
+/* Line 1455 of yacc.c */
+#line 316 "dtc-parser.y"
{
- (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+ uint64_t val = ~0ULL >> (64 - (yyvsp[(1) - (2)].array).bits);
+
+ if ((yyvsp[(1) - (2)].array).bits == 32)
+ (yyvsp[(1) - (2)].array).data = data_add_marker((yyvsp[(1) - (2)].array).data,
+ REF_PHANDLE,
+ (yyvsp[(2) - (2)].labelref));
+ else
+ print_error("References are only allowed in "
+ "arrays with 32-bit elements.");
+
+ (yyval.array).data = data_append_integer((yyvsp[(1) - (2)].array).data, val, (yyvsp[(1) - (2)].array).bits);
;}
break;
case 32:
+/* Line 1455 of yacc.c */
+#line 330 "dtc-parser.y"
{
- (yyval.data) = empty_data;
+ (yyval.array).data = data_add_marker((yyvsp[(1) - (2)].array).data, LABEL, (yyvsp[(2) - (2)].labelref));
;}
break;
case 33:
+/* Line 1455 of yacc.c */
+#line 337 "dtc-parser.y"
{
- (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ (yyval.integer) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
;}
break;
case 34:
+/* Line 1455 of yacc.c */
+#line 341 "dtc-parser.y"
{
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ (yyval.integer) = eval_char_literal((yyvsp[(1) - (1)].literal));
;}
break;
case 35:
+/* Line 1455 of yacc.c */
+#line 345 "dtc-parser.y"
+ {
+ (yyval.integer) = (yyvsp[(2) - (3)].integer);
+ ;}
+ break;
+
+ case 38:
+
+/* Line 1455 of yacc.c */
+#line 356 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (5)].integer) ? (yyvsp[(3) - (5)].integer) : (yyvsp[(5) - (5)].integer); ;}
+ break;
+
+ case 40:
+
+/* Line 1455 of yacc.c */
+#line 361 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) || (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 42:
+
+/* Line 1455 of yacc.c */
+#line 366 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) && (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 44:
+
+/* Line 1455 of yacc.c */
+#line 371 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) | (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 46:
+
+/* Line 1455 of yacc.c */
+#line 376 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) ^ (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 48:
+
+/* Line 1455 of yacc.c */
+#line 381 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) & (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 50:
+
+/* Line 1455 of yacc.c */
+#line 386 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) == (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 51:
+
+/* Line 1455 of yacc.c */
+#line 387 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) != (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 53:
+
+/* Line 1455 of yacc.c */
+#line 392 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) < (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 54:
+
+/* Line 1455 of yacc.c */
+#line 393 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) > (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 55:
+
+/* Line 1455 of yacc.c */
+#line 394 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) <= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 56:
+
+/* Line 1455 of yacc.c */
+#line 395 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >= (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 57:
+
+/* Line 1455 of yacc.c */
+#line 399 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) << (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 58:
+
+/* Line 1455 of yacc.c */
+#line 400 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) >> (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 60:
+
+/* Line 1455 of yacc.c */
+#line 405 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) + (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 61:
+
+/* Line 1455 of yacc.c */
+#line 406 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) - (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 63:
+
+/* Line 1455 of yacc.c */
+#line 411 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) * (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 64:
+
+/* Line 1455 of yacc.c */
+#line 412 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) / (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 65:
+
+/* Line 1455 of yacc.c */
+#line 413 "dtc-parser.y"
+ { (yyval.integer) = (yyvsp[(1) - (3)].integer) % (yyvsp[(3) - (3)].integer); ;}
+ break;
+
+ case 68:
+
+/* Line 1455 of yacc.c */
+#line 419 "dtc-parser.y"
+ { (yyval.integer) = -(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 69:
+
+/* Line 1455 of yacc.c */
+#line 420 "dtc-parser.y"
+ { (yyval.integer) = ~(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 70:
+
+/* Line 1455 of yacc.c */
+#line 421 "dtc-parser.y"
+ { (yyval.integer) = !(yyvsp[(2) - (2)].integer); ;}
+ break;
+
+ case 71:
+
+/* Line 1455 of yacc.c */
+#line 426 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+ case 72:
+
+/* Line 1455 of yacc.c */
+#line 430 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ ;}
+ break;
+
+ case 73:
+
+/* Line 1455 of yacc.c */
+#line 434 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 74:
+
+/* Line 1455 of yacc.c */
+#line 441 "dtc-parser.y"
{
(yyval.nodelist) = NULL;
;}
break;
- case 36:
+ case 75:
+/* Line 1455 of yacc.c */
+#line 445 "dtc-parser.y"
{
(yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
;}
break;
- case 37:
+ case 76:
+/* Line 1455 of yacc.c */
+#line 449 "dtc-parser.y"
{
print_error("syntax error: properties must precede subnodes");
YYERROR;
;}
break;
- case 38:
+ case 77:
+/* Line 1455 of yacc.c */
+#line 457 "dtc-parser.y"
{
(yyval.node) = name_node((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].propnodename));
;}
break;
- case 39:
+ case 78:
+
+/* Line 1455 of yacc.c */
+#line 461 "dtc-parser.y"
+ {
+ (yyval.node) = name_node(build_node_delete(), (yyvsp[(2) - (3)].propnodename));
+ ;}
+ break;
+
+ case 79:
+/* Line 1455 of yacc.c */
+#line 465 "dtc-parser.y"
{
add_label(&(yyvsp[(2) - (2)].node)->labels, (yyvsp[(1) - (2)].labelref));
(yyval.node) = (yyvsp[(2) - (2)].node);
@@ -1700,6 +2119,8 @@ yyreduce:
+/* Line 1455 of yacc.c */
+#line 2124 "dtc-parser.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -1910,6 +2331,8 @@ yyreturn:
+/* Line 1675 of yacc.c */
+#line 471 "dtc-parser.y"
void print_error(char const *fmt, ...)
@@ -1934,9 +2357,12 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
errno = 0;
val = strtoull(s, &e, base);
- if (*e)
- print_error("bad characters in literal");
- else if ((errno == ERANGE)
+ if (*e) {
+ size_t uls = strspn(e, "UL");
+ if (e[uls])
+ print_error("bad characters in literal");
+ }
+ if ((errno == ERANGE)
|| ((bits < 64) && (val >= (1ULL << bits))))
print_error("literal out of range");
else if (errno != 0)
@@ -1944,3 +2370,29 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
return val;
}
+static unsigned char eval_char_literal(const char *s)
+{
+ int i = 1;
+ char c = s[0];
+
+ if (c == '\0')
+ {
+ print_error("empty character literal");
+ return 0;
+ }
+
+ /*
+ * If the first character in the character literal is a \ then process
+ * the remaining characters as an escape encoding. If the first
+ * character is neither an escape or a terminator it should be the only
+ * character in the literal and will be returned.
+ */
+ if (c == '\\')
+ c = get_escape_char(s, &i);
+
+ if (s[i] != '\0')
+ print_error("malformed character literal");
+
+ return c;
+}
+
diff --git a/scripts/dtc/dtc-parser.tab.h_shipped b/scripts/dtc/dtc-parser.tab.h_shipped
index 4ee682bb7d3..9d2dce41211 100644
--- a/scripts/dtc/dtc-parser.tab.h_shipped
+++ b/scripts/dtc/dtc-parser.tab.h_shipped
@@ -1,9 +1,10 @@
-/* A Bison parser, made by GNU Bison 2.4.3. */
+
+/* A Bison parser, made by GNU Bison 2.4.1. */
/* Skeleton interface for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
- 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -40,14 +41,26 @@
enum yytokentype {
DT_V1 = 258,
DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_BASE = 262,
- DT_BYTE = 263,
- DT_STRING = 264,
- DT_LABEL = 265,
- DT_REF = 266,
- DT_INCBIN = 267
+ DT_LSHIFT = 260,
+ DT_RSHIFT = 261,
+ DT_LE = 262,
+ DT_GE = 263,
+ DT_EQ = 264,
+ DT_NE = 265,
+ DT_AND = 266,
+ DT_OR = 267,
+ DT_BITS = 268,
+ DT_DEL_PROP = 269,
+ DT_DEL_NODE = 270,
+ DT_PROPNODENAME = 271,
+ DT_LITERAL = 272,
+ DT_CHAR_LITERAL = 273,
+ DT_BASE = 274,
+ DT_BYTE = 275,
+ DT_STRING = 276,
+ DT_LABEL = 277,
+ DT_REF = 278,
+ DT_INCBIN = 279
};
#endif
@@ -57,6 +70,8 @@
typedef union YYSTYPE
{
+/* Line 1676 of yacc.c */
+#line 40 "dtc-parser.y"
char *propnodename;
char *literal;
@@ -65,16 +80,22 @@ typedef union YYSTYPE
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
+/* Line 1676 of yacc.c */
+#line 99 "dtc-parser.tab.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y
index 5e84a67fc1d..f412460f94d 100644
--- a/scripts/dtc/dtc-parser.y
+++ b/scripts/dtc/dtc-parser.y
@@ -34,6 +34,7 @@ extern struct boot_info *the_boot_info;
extern int treesource_error;
static unsigned long long eval_literal(const char *s, int base, int bits);
+static unsigned char eval_char_literal(const char *s);
%}
%union {
@@ -44,19 +45,28 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
uint8_t byte;
struct data data;
- uint64_t addr;
- cell_t cell;
+ struct {
+ struct data data;
+ int bits;
+ } array;
+
struct property *prop;
struct property *proplist;
struct node *node;
struct node *nodelist;
struct reserve_info *re;
+ uint64_t integer;
}
%token DT_V1
%token DT_MEMRESERVE
+%token DT_LSHIFT DT_RSHIFT DT_LE DT_GE DT_EQ DT_NE DT_AND DT_OR
+%token DT_BITS
+%token DT_DEL_PROP
+%token DT_DEL_NODE
%token <propnodename> DT_PROPNODENAME
%token <literal> DT_LITERAL
+%token <literal> DT_CHAR_LITERAL
%token <cbase> DT_BASE
%token <byte> DT_BYTE
%token <data> DT_STRING
@@ -68,9 +78,7 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <data> propdataprefix
%type <re> memreserve
%type <re> memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cell> cellval
+%type <array> arrayprefix
%type <data> bytestring
%type <prop> propdef
%type <proplist> proplist
@@ -80,6 +88,21 @@ static unsigned long long eval_literal(const char *s, int base, int bits);
%type <node> subnode
%type <nodelist> subnodes
+%type <integer> integer_prim
+%type <integer> integer_unary
+%type <integer> integer_mul
+%type <integer> integer_add
+%type <integer> integer_shift
+%type <integer> integer_rela
+%type <integer> integer_eq
+%type <integer> integer_bitand
+%type <integer> integer_bitxor
+%type <integer> integer_bitor
+%type <integer> integer_and
+%type <integer> integer_or
+%type <integer> integer_trinary
+%type <integer> integer_expr
+
%%
sourcefile:
@@ -102,7 +125,7 @@ memreserves:
;
memreserve:
- DT_MEMRESERVE addr addr ';'
+ DT_MEMRESERVE integer_prim integer_prim ';'
{
$$ = build_reserve_entry($2, $3);
}
@@ -113,13 +136,6 @@ memreserve:
}
;
-addr:
- DT_LITERAL
- {
- $$ = eval_literal($1, 0, 64);
- }
- ;
-
devicetree:
'/' nodedef
{
@@ -139,6 +155,17 @@ devicetree:
print_error("label or path, '%s', not found", $2);
$$ = $1;
}
+ | devicetree DT_DEL_NODE DT_REF ';'
+ {
+ struct node *target = get_node_by_ref($1, $3);
+
+ if (!target)
+ print_error("label or path, '%s', not found", $3);
+ else
+ delete_node(target);
+
+ $$ = $1;
+ }
;
nodedef:
@@ -168,6 +195,10 @@ propdef:
{
$$ = build_property($1, empty_data);
}
+ | DT_DEL_PROP DT_PROPNODENAME ';'
+ {
+ $$ = build_property_delete($2);
+ }
| DT_LABEL propdef
{
add_label(&$2->labels, $1);
@@ -180,9 +211,9 @@ propdata:
{
$$ = data_merge($1, $2);
}
- | propdataprefix '<' celllist '>'
+ | propdataprefix arrayprefix '>'
{
- $$ = data_merge($1, $3);
+ $$ = data_merge($1, $2.data);
}
| propdataprefix '[' bytestring ']'
{
@@ -192,7 +223,7 @@ propdata:
{
$$ = data_add_marker($1, REF_PATH, $2);
}
- | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+ | propdataprefix DT_INCBIN '(' DT_STRING ',' integer_prim ',' integer_prim ')'
{
FILE *f = srcfile_relative_open($4.val, NULL);
struct data d;
@@ -240,31 +271,154 @@ propdataprefix:
}
;
-celllist:
- /* empty */
+arrayprefix:
+ DT_BITS DT_LITERAL '<'
+ {
+ $$.data = empty_data;
+ $$.bits = eval_literal($2, 0, 7);
+
+ if (($$.bits != 8) &&
+ ($$.bits != 16) &&
+ ($$.bits != 32) &&
+ ($$.bits != 64))
+ {
+ print_error("Only 8, 16, 32 and 64-bit elements"
+ " are currently supported");
+ $$.bits = 32;
+ }
+ }
+ | '<'
+ {
+ $$.data = empty_data;
+ $$.bits = 32;
+ }
+ | arrayprefix integer_prim
+ {
+ if ($1.bits < 64) {
+ uint64_t mask = (1ULL << $1.bits) - 1;
+ /*
+ * Bits above mask must either be all zero
+ * (positive within range of mask) or all one
+ * (negative and sign-extended). The second
+ * condition is true if when we set all bits
+ * within the mask to one (i.e. | in the
+ * mask), all bits are one.
+ */
+ if (($2 > mask) && (($2 | mask) != -1ULL))
+ print_error(
+ "integer value out of range "
+ "%016lx (%d bits)", $1.bits);
+ }
+
+ $$.data = data_append_integer($1.data, $2, $1.bits);
+ }
+ | arrayprefix DT_REF
+ {
+ uint64_t val = ~0ULL >> (64 - $1.bits);
+
+ if ($1.bits == 32)
+ $1.data = data_add_marker($1.data,
+ REF_PHANDLE,
+ $2);
+ else
+ print_error("References are only allowed in "
+ "arrays with 32-bit elements.");
+
+ $$.data = data_append_integer($1.data, val, $1.bits);
+ }
+ | arrayprefix DT_LABEL
{
- $$ = empty_data;
+ $$.data = data_add_marker($1.data, LABEL, $2);
}
- | celllist cellval
+ ;
+
+integer_prim:
+ DT_LITERAL
{
- $$ = data_append_cell($1, $2);
+ $$ = eval_literal($1, 0, 64);
}
- | celllist DT_REF
+ | DT_CHAR_LITERAL
{
- $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
- $2), -1);
+ $$ = eval_char_literal($1);
}
- | celllist DT_LABEL
+ | '(' integer_expr ')'
{
- $$ = data_add_marker($1, LABEL, $2);
+ $$ = $2;
}
;
-cellval:
- DT_LITERAL
- {
- $$ = eval_literal($1, 0, 32);
- }
+integer_expr:
+ integer_trinary
+ ;
+
+integer_trinary:
+ integer_or
+ | integer_or '?' integer_expr ':' integer_trinary { $$ = $1 ? $3 : $5; }
+ ;
+
+integer_or:
+ integer_and
+ | integer_or DT_OR integer_and { $$ = $1 || $3; }
+ ;
+
+integer_and:
+ integer_bitor
+ | integer_and DT_AND integer_bitor { $$ = $1 && $3; }
+ ;
+
+integer_bitor:
+ integer_bitxor
+ | integer_bitor '|' integer_bitxor { $$ = $1 | $3; }
+ ;
+
+integer_bitxor:
+ integer_bitand
+ | integer_bitxor '^' integer_bitand { $$ = $1 ^ $3; }
+ ;
+
+integer_bitand:
+ integer_eq
+ | integer_bitand '&' integer_eq { $$ = $1 & $3; }
+ ;
+
+integer_eq:
+ integer_rela
+ | integer_eq DT_EQ integer_rela { $$ = $1 == $3; }
+ | integer_eq DT_NE integer_rela { $$ = $1 != $3; }
+ ;
+
+integer_rela:
+ integer_shift
+ | integer_rela '<' integer_shift { $$ = $1 < $3; }
+ | integer_rela '>' integer_shift { $$ = $1 > $3; }
+ | integer_rela DT_LE integer_shift { $$ = $1 <= $3; }
+ | integer_rela DT_GE integer_shift { $$ = $1 >= $3; }
+ ;
+
+integer_shift:
+ integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; }
+ | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; }
+ | integer_add
+ ;
+
+integer_add:
+ integer_add '+' integer_mul { $$ = $1 + $3; }
+ | integer_add '-' integer_mul { $$ = $1 - $3; }
+ | integer_mul
+ ;
+
+integer_mul:
+ integer_mul '*' integer_unary { $$ = $1 * $3; }
+ | integer_mul '/' integer_unary { $$ = $1 / $3; }
+ | integer_mul '%' integer_unary { $$ = $1 % $3; }
+ | integer_unary
+ ;
+
+integer_unary:
+ integer_prim
+ | '-' integer_unary { $$ = -$2; }
+ | '~' integer_unary { $$ = ~$2; }
+ | '!' integer_unary { $$ = !$2; }
;
bytestring:
@@ -303,6 +457,10 @@ subnode:
{
$$ = name_node($2, $1);
}
+ | DT_DEL_NODE DT_PROPNODENAME ';'
+ {
+ $$ = name_node(build_node_delete(), $2);
+ }
| DT_LABEL subnode
{
add_label(&$2->labels, $1);
@@ -334,12 +492,41 @@ static unsigned long long eval_literal(const char *s, int base, int bits)
errno = 0;
val = strtoull(s, &e, base);
- if (*e)
- print_error("bad characters in literal");
- else if ((errno == ERANGE)
+ if (*e) {
+ size_t uls = strspn(e, "UL");
+ if (e[uls])
+ print_error("bad characters in literal");
+ }
+ if ((errno == ERANGE)
|| ((bits < 64) && (val >= (1ULL << bits))))
print_error("literal out of range");
else if (errno != 0)
print_error("bad literal");
return val;
}
+
+static unsigned char eval_char_literal(const char *s)
+{
+ int i = 1;
+ char c = s[0];
+
+ if (c == '\0')
+ {
+ print_error("empty character literal");
+ return 0;
+ }
+
+ /*
+ * If the first character in the character literal is a \ then process
+ * the remaining characters as an escape encoding. If the first
+ * character is neither an escape or a terminator it should be the only
+ * character in the literal and will be returned.
+ */
+ if (c == '\\')
+ c = get_escape_char(s, &i);
+
+ if (s[i] != '\0')
+ print_error("malformed character literal");
+
+ return c;
+}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 2ef5e2e3dd3..a375683c153 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -82,6 +82,8 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\tSet the physical boot cpu\n");
fprintf(stderr, "\t-f\n");
fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+ fprintf(stderr, "\t-i\n");
+ fprintf(stderr, "\t\tAdd a path to search for include files\n");
fprintf(stderr, "\t-s\n");
fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n");
fprintf(stderr, "\t-v\n");
@@ -91,6 +93,9 @@ static void __attribute__ ((noreturn)) usage(void)
fprintf(stderr, "\t\t\tlegacy - \"linux,phandle\" properties only\n");
fprintf(stderr, "\t\t\tepapr - \"phandle\" properties only\n");
fprintf(stderr, "\t\t\tboth - Both \"linux,phandle\" and \"phandle\" properties\n");
+ fprintf(stderr, "\t-W [no-]<checkname>\n");
+ fprintf(stderr, "\t-E [no-]<checkname>\n");
+ fprintf(stderr, "\t\t\tenable or disable warnings and errors\n");
exit(3);
}
@@ -113,7 +118,7 @@ int main(int argc, char *argv[])
minsize = 0;
padsize = 0;
- while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fcqb:vH:s"))
+ while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:sW:E:"))
!= EOF) {
switch (opt) {
case 'I':
@@ -149,6 +154,9 @@ int main(int argc, char *argv[])
case 'b':
cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
break;
+ case 'i':
+ srcfile_add_search_path(optarg);
+ break;
case 'v':
printf("Version: %s\n", DTC_VERSION);
exit(0);
@@ -168,6 +176,14 @@ int main(int argc, char *argv[])
sort = 1;
break;
+ case 'W':
+ parse_checks_option(true, false, optarg);
+ break;
+
+ case 'E':
+ parse_checks_option(false, true, optarg);
+ break;
+
case 'h':
default:
usage();
@@ -188,9 +204,6 @@ int main(int argc, char *argv[])
if (minsize)
fprintf(stderr, "DTC: Use of \"-S\" is deprecated; it will be removed soon, use \"-p\" instead\n");
- fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
- inform, outform, arg);
-
if (depname) {
depfile = fopen(depname, "w");
if (!depfile)
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index f37c97eb3df..3e42a071070 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -25,6 +25,7 @@
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
+#include <stdbool.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
@@ -109,6 +110,7 @@ struct data data_insert_at_marker(struct data d, struct marker *m,
const void *p, int len);
struct data data_merge(struct data d1, struct data d2);
struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_integer(struct data d, uint64_t word, int bits);
struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
struct data data_append_addr(struct data d, uint64_t addr);
struct data data_append_byte(struct data d, uint8_t byte);
@@ -126,11 +128,13 @@ int data_is_one_string(struct data d);
/* Live trees */
struct label {
+ int deleted;
char *label;
struct label *next;
};
struct property {
+ int deleted;
char *name;
struct data val;
@@ -140,6 +144,7 @@ struct property {
};
struct node {
+ int deleted;
char *name;
struct property *proplist;
struct node *children;
@@ -156,28 +161,47 @@ struct node {
struct label *labels;
};
-#define for_each_label(l0, l) \
+#define for_each_label_withdel(l0, l) \
for ((l) = (l0); (l); (l) = (l)->next)
-#define for_each_property(n, p) \
+#define for_each_label(l0, l) \
+ for_each_label_withdel(l0, l) \
+ if (!(l)->deleted)
+
+#define for_each_property_withdel(n, p) \
for ((p) = (n)->proplist; (p); (p) = (p)->next)
-#define for_each_child(n, c) \
+#define for_each_property(n, p) \
+ for_each_property_withdel(n, p) \
+ if (!(p)->deleted)
+
+#define for_each_child_withdel(n, c) \
for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+#define for_each_child(n, c) \
+ for_each_child_withdel(n, c) \
+ if (!(c)->deleted)
+
void add_label(struct label **labels, char *label);
+void delete_labels(struct label **labels);
struct property *build_property(char *name, struct data val);
+struct property *build_property_delete(char *name);
struct property *chain_property(struct property *first, struct property *list);
struct property *reverse_properties(struct property *first);
struct node *build_node(struct property *proplist, struct node *children);
+struct node *build_node_delete(void);
struct node *name_node(struct node *node, char *name);
struct node *chain_node(struct node *first, struct node *list);
struct node *merge_nodes(struct node *old_node, struct node *new_node);
void add_property(struct node *node, struct property *prop);
+void delete_property_by_name(struct node *node, char *name);
+void delete_property(struct property *prop);
void add_child(struct node *parent, struct node *child);
+void delete_node_by_name(struct node *parent, char *name);
+void delete_node(struct node *node);
const char *get_unitname(struct node *node);
struct property *get_property(struct node *node, const char *propname);
@@ -224,6 +248,7 @@ void sort_tree(struct boot_info *bi);
/* Checks */
+void parse_checks_option(bool warn, bool error, const char *optarg);
void process_checks(int force, struct boot_info *bi);
/* Flattened trees */
diff --git a/scripts/dtc/fdtdump.c b/scripts/dtc/fdtdump.c
new file mode 100644
index 00000000000..207a46d6486
--- /dev/null
+++ b/scripts/dtc/fdtdump.c
@@ -0,0 +1,162 @@
+/*
+ * fdtdump.c - Contributed by Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <fdt.h>
+#include <libfdt_env.h>
+
+#include "util.h"
+
+#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
+#define PALIGN(p, a) ((void *)(ALIGN((unsigned long)(p), (a))))
+#define GET_CELL(p) (p += 4, *((const uint32_t *)(p-4)))
+
+static void print_data(const char *data, int len)
+{
+ int i;
+ const char *p = data;
+
+ /* no data, don't print */
+ if (len == 0)
+ return;
+
+ if (util_is_printable_string(data, len)) {
+ printf(" = \"%s\"", (const char *)data);
+ } else if ((len % 4) == 0) {
+ printf(" = <");
+ for (i = 0; i < len; i += 4)
+ printf("0x%08x%s", fdt32_to_cpu(GET_CELL(p)),
+ i < (len - 4) ? " " : "");
+ printf(">");
+ } else {
+ printf(" = [");
+ for (i = 0; i < len; i++)
+ printf("%02x%s", *p++, i < len - 1 ? " " : "");
+ printf("]");
+ }
+}
+
+static void dump_blob(void *blob)
+{
+ struct fdt_header *bph = blob;
+ uint32_t off_mem_rsvmap = fdt32_to_cpu(bph->off_mem_rsvmap);
+ uint32_t off_dt = fdt32_to_cpu(bph->off_dt_struct);
+ uint32_t off_str = fdt32_to_cpu(bph->off_dt_strings);
+ struct fdt_reserve_entry *p_rsvmap =
+ (struct fdt_reserve_entry *)((char *)blob + off_mem_rsvmap);
+ const char *p_struct = (const char *)blob + off_dt;
+ const char *p_strings = (const char *)blob + off_str;
+ uint32_t version = fdt32_to_cpu(bph->version);
+ uint32_t totalsize = fdt32_to_cpu(bph->totalsize);
+ uint32_t tag;
+ const char *p, *s, *t;
+ int depth, sz, shift;
+ int i;
+ uint64_t addr, size;
+
+ depth = 0;
+ shift = 4;
+
+ printf("/dts-v1/;\n");
+ printf("// magic:\t\t0x%x\n", fdt32_to_cpu(bph->magic));
+ printf("// totalsize:\t\t0x%x (%d)\n", totalsize, totalsize);
+ printf("// off_dt_struct:\t0x%x\n", off_dt);
+ printf("// off_dt_strings:\t0x%x\n", off_str);
+ printf("// off_mem_rsvmap:\t0x%x\n", off_mem_rsvmap);
+ printf("// version:\t\t%d\n", version);
+ printf("// last_comp_version:\t%d\n",
+ fdt32_to_cpu(bph->last_comp_version));
+ if (version >= 2)
+ printf("// boot_cpuid_phys:\t0x%x\n",
+ fdt32_to_cpu(bph->boot_cpuid_phys));
+
+ if (version >= 3)
+ printf("// size_dt_strings:\t0x%x\n",
+ fdt32_to_cpu(bph->size_dt_strings));
+ if (version >= 17)
+ printf("// size_dt_struct:\t0x%x\n",
+ fdt32_to_cpu(bph->size_dt_struct));
+ printf("\n");
+
+ for (i = 0; ; i++) {
+ addr = fdt64_to_cpu(p_rsvmap[i].address);
+ size = fdt64_to_cpu(p_rsvmap[i].size);
+ if (addr == 0 && size == 0)
+ break;
+
+ printf("/memreserve/ %llx %llx;\n",
+ (unsigned long long)addr, (unsigned long long)size);
+ }
+
+ p = p_struct;
+ while ((tag = fdt32_to_cpu(GET_CELL(p))) != FDT_END) {
+
+ /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
+
+ if (tag == FDT_BEGIN_NODE) {
+ s = p;
+ p = PALIGN(p + strlen(s) + 1, 4);
+
+ if (*s == '\0')
+ s = "/";
+
+ printf("%*s%s {\n", depth * shift, "", s);
+
+ depth++;
+ continue;
+ }
+
+ if (tag == FDT_END_NODE) {
+ depth--;
+
+ printf("%*s};\n", depth * shift, "");
+ continue;
+ }
+
+ if (tag == FDT_NOP) {
+ printf("%*s// [NOP]\n", depth * shift, "");
+ continue;
+ }
+
+ if (tag != FDT_PROP) {
+ fprintf(stderr, "%*s ** Unknown tag 0x%08x\n", depth * shift, "", tag);
+ break;
+ }
+ sz = fdt32_to_cpu(GET_CELL(p));
+ s = p_strings + fdt32_to_cpu(GET_CELL(p));
+ if (version < 16 && sz >= 8)
+ p = PALIGN(p, 8);
+ t = p;
+
+ p = PALIGN(p + sz, 4);
+
+ printf("%*s%s", depth * shift, "", s);
+ print_data(t, sz);
+ printf(";\n");
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *buf;
+
+ if (argc < 2) {
+ fprintf(stderr, "supply input filename\n");
+ return 5;
+ }
+
+ buf = utilfdt_read(argv[1]);
+ if (buf)
+ dump_blob(buf);
+ else
+ return 10;
+
+ return 0;
+}
diff --git a/scripts/dtc/fdtget.c b/scripts/dtc/fdtget.c
new file mode 100644
index 00000000000..c2fbab2a547
--- /dev/null
+++ b/scripts/dtc/fdtget.c
@@ -0,0 +1,366 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * Portions from U-Boot cmd_fdt.c (C) Copyright 2007
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com
+ * Based on code written by:
+ * Pantelis Antoniou <pantelis.antoniou@gmail.com> and
+ * Matthew McClintock <msm@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+enum display_mode {
+ MODE_SHOW_VALUE, /* show values for node properties */
+ MODE_LIST_PROPS, /* list the properties for a node */
+ MODE_LIST_SUBNODES, /* list the subnodes of a node */
+};
+
+/* Holds information which controls our output and options */
+struct display_info {
+ int type; /* data type (s/i/u/x or 0 for default) */
+ int size; /* data size (1/2/4) */
+ enum display_mode mode; /* display mode that we are using */
+ const char *default_val; /* default value if node/property not found */
+};
+
+static void report_error(const char *where, int err)
+{
+ fprintf(stderr, "Error at '%s': %s\n", where, fdt_strerror(err));
+}
+
+/**
+ * Displays data of a given length according to selected options
+ *
+ * If a specific data type is provided in disp, then this is used. Otherwise
+ * we try to guess the data type / size from the contents.
+ *
+ * @param disp Display information / options
+ * @param data Data to display
+ * @param len Maximum length of buffer
+ * @return 0 if ok, -1 if data does not match format
+ */
+static int show_data(struct display_info *disp, const char *data, int len)
+{
+ int i, size;
+ const uint8_t *p = (const uint8_t *)data;
+ const char *s;
+ int value;
+ int is_string;
+ char fmt[3];
+
+ /* no data, don't print */
+ if (len == 0)
+ return 0;
+
+ is_string = (disp->type) == 's' ||
+ (!disp->type && util_is_printable_string(data, len));
+ if (is_string) {
+ if (data[len - 1] != '\0') {
+ fprintf(stderr, "Unterminated string\n");
+ return -1;
+ }
+ for (s = data; s - data < len; s += strlen(s) + 1) {
+ if (s != data)
+ printf(" ");
+ printf("%s", (const char *)s);
+ }
+ return 0;
+ }
+ size = disp->size;
+ if (size == -1) {
+ size = (len % 4) == 0 ? 4 : 1;
+ } else if (len % size) {
+ fprintf(stderr, "Property length must be a multiple of "
+ "selected data size\n");
+ return -1;
+ }
+ fmt[0] = '%';
+ fmt[1] = disp->type ? disp->type : 'd';
+ fmt[2] = '\0';
+ for (i = 0; i < len; i += size, p += size) {
+ if (i)
+ printf(" ");
+ value = size == 4 ? fdt32_to_cpu(*(const uint32_t *)p) :
+ size == 2 ? (*p << 8) | p[1] : *p;
+ printf(fmt, value);
+ }
+ return 0;
+}
+
+/**
+ * List all properties in a node, one per line.
+ *
+ * @param blob FDT blob
+ * @param node Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_properties(const void *blob, int node)
+{
+ const struct fdt_property *data;
+ const char *name;
+ int prop;
+
+ prop = fdt_first_property_offset(blob, node);
+ do {
+ /* Stop silently when there are no more properties */
+ if (prop < 0)
+ return prop == -FDT_ERR_NOTFOUND ? 0 : prop;
+ data = fdt_get_property_by_offset(blob, prop, NULL);
+ name = fdt_string(blob, fdt32_to_cpu(data->nameoff));
+ if (name)
+ puts(name);
+ prop = fdt_next_property_offset(blob, prop);
+ } while (1);
+}
+
+#define MAX_LEVEL 32 /* how deeply nested we will go */
+
+/**
+ * List all subnodes in a node, one per line
+ *
+ * @param blob FDT blob
+ * @param node Node to display
+ * @return 0 if ok, or FDT_ERR... if not.
+ */
+static int list_subnodes(const void *blob, int node)
+{
+ int nextoffset; /* next node offset from libfdt */
+ uint32_t tag; /* current tag */
+ int level = 0; /* keep track of nesting level */
+ const char *pathp;
+ int depth = 1; /* the assumed depth of this node */
+
+ while (level >= 0) {
+ tag = fdt_next_tag(blob, node, &nextoffset);
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ pathp = fdt_get_name(blob, node, NULL);
+ if (level <= depth) {
+ if (pathp == NULL)
+ pathp = "/* NULL pointer error */";
+ if (*pathp == '\0')
+ pathp = "/"; /* root is nameless */
+ if (level == 1)
+ puts(pathp);
+ }
+ level++;
+ if (level >= MAX_LEVEL) {
+ printf("Nested too deep, aborting.\n");
+ return 1;
+ }
+ break;
+ case FDT_END_NODE:
+ level--;
+ if (level == 0)
+ level = -1; /* exit the loop */
+ break;
+ case FDT_END:
+ return 1;
+ case FDT_PROP:
+ break;
+ default:
+ if (level <= depth)
+ printf("Unknown tag 0x%08X\n", tag);
+ return 1;
+ }
+ node = nextoffset;
+ }
+ return 0;
+}
+
+/**
+ * Show the data for a given node (and perhaps property) according to the
+ * display option provided.
+ *
+ * @param blob FDT blob
+ * @param disp Display information / options
+ * @param node Node to display
+ * @param property Name of property to display, or NULL if none
+ * @return 0 if ok, -ve on error
+ */
+static int show_data_for_item(const void *blob, struct display_info *disp,
+ int node, const char *property)
+{
+ const void *value = NULL;
+ int len, err = 0;
+
+ switch (disp->mode) {
+ case MODE_LIST_PROPS:
+ err = list_properties(blob, node);
+ break;
+
+ case MODE_LIST_SUBNODES:
+ err = list_subnodes(blob, node);
+ break;
+
+ default:
+ assert(property);
+ value = fdt_getprop(blob, node, property, &len);
+ if (value) {
+ if (show_data(disp, value, len))
+ err = -1;
+ else
+ printf("\n");
+ } else if (disp->default_val) {
+ puts(disp->default_val);
+ } else {
+ report_error(property, len);
+ err = -1;
+ }
+ break;
+ }
+
+ return err;
+}
+
+/**
+ * Run the main fdtget operation, given a filename and valid arguments
+ *
+ * @param disp Display information / options
+ * @param filename Filename of blob file
+ * @param arg List of arguments to process
+ * @param arg_count Number of arguments
+ * @param return 0 if ok, -ve on error
+ */
+static int do_fdtget(struct display_info *disp, const char *filename,
+ char **arg, int arg_count, int args_per_step)
+{
+ char *blob;
+ const char *prop;
+ int i, node;
+
+ blob = utilfdt_read(filename);
+ if (!blob)
+ return -1;
+
+ for (i = 0; i + args_per_step <= arg_count; i += args_per_step) {
+ node = fdt_path_offset(blob, arg[i]);
+ if (node < 0) {
+ if (disp->default_val) {
+ puts(disp->default_val);
+ continue;
+ } else {
+ report_error(arg[i], node);
+ return -1;
+ }
+ }
+ prop = args_per_step == 1 ? NULL : arg[i + 1];
+
+ if (show_data_for_item(blob, disp, node, prop))
+ return -1;
+ }
+ return 0;
+}
+
+static const char *usage_msg =
+ "fdtget - read values from device tree\n"
+ "\n"
+ "Each value is printed on a new line.\n\n"
+ "Usage:\n"
+ " fdtget <options> <dt file> [<node> <property>]...\n"
+ " fdtget -p <options> <dt file> [<node> ]...\n"
+ "Options:\n"
+ "\t-t <type>\tType of data\n"
+ "\t-p\t\tList properties for each node\n"
+ "\t-l\t\tList subnodes for each node\n"
+ "\t-d\t\tDefault value to display when the property is "
+ "missing\n"
+ "\t-h\t\tPrint this help\n\n"
+ USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+ if (msg)
+ fprintf(stderr, "Error: %s\n\n", msg);
+
+ fprintf(stderr, "%s", usage_msg);
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ char *filename = NULL;
+ struct display_info disp;
+ int args_per_step = 2;
+
+ /* set defaults */
+ memset(&disp, '\0', sizeof(disp));
+ disp.size = -1;
+ disp.mode = MODE_SHOW_VALUE;
+ for (;;) {
+ int c = getopt(argc, argv, "d:hlpt:");
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ case '?':
+ usage(NULL);
+
+ case 't':
+ if (utilfdt_decode_type(optarg, &disp.type,
+ &disp.size))
+ usage("Invalid type string");
+ break;
+
+ case 'p':
+ disp.mode = MODE_LIST_PROPS;
+ args_per_step = 1;
+ break;
+
+ case 'l':
+ disp.mode = MODE_LIST_SUBNODES;
+ args_per_step = 1;
+ break;
+
+ case 'd':
+ disp.default_val = optarg;
+ break;
+ }
+ }
+
+ if (optind < argc)
+ filename = argv[optind++];
+ if (!filename)
+ usage("Missing filename");
+
+ argv += optind;
+ argc -= optind;
+
+ /* Allow no arguments, and silently succeed */
+ if (!argc)
+ return 0;
+
+ /* Check for node, property arguments */
+ if (args_per_step == 2 && (argc % 2))
+ usage("Must have an even number of arguments");
+
+ if (do_fdtget(&disp, filename, argv, argc, args_per_step))
+ return 1;
+ return 0;
+}
diff --git a/scripts/dtc/fdtput.c b/scripts/dtc/fdtput.c
new file mode 100644
index 00000000000..f2197f51930
--- /dev/null
+++ b/scripts/dtc/fdtput.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <assert.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include "util.h"
+
+/* These are the operations we support */
+enum oper_type {
+ OPER_WRITE_PROP, /* Write a property in a node */
+ OPER_CREATE_NODE, /* Create a new node */
+};
+
+struct display_info {
+ enum oper_type oper; /* operation to perform */
+ int type; /* data type (s/i/u/x or 0 for default) */
+ int size; /* data size (1/2/4) */
+ int verbose; /* verbose output */
+ int auto_path; /* automatically create all path components */
+};
+
+
+/**
+ * Report an error with a particular node.
+ *
+ * @param name Node name to report error on
+ * @param namelen Length of node name, or -1 to use entire string
+ * @param err Error number to report (-FDT_ERR_...)
+ */
+static void report_error(const char *name, int namelen, int err)
+{
+ if (namelen == -1)
+ namelen = strlen(name);
+ fprintf(stderr, "Error at '%1.*s': %s\n", namelen, name,
+ fdt_strerror(err));
+}
+
+/**
+ * Encode a series of arguments in a property value.
+ *
+ * @param disp Display information / options
+ * @param arg List of arguments from command line
+ * @param arg_count Number of arguments (may be 0)
+ * @param valuep Returns buffer containing value
+ * @param *value_len Returns length of value encoded
+ */
+static int encode_value(struct display_info *disp, char **arg, int arg_count,
+ char **valuep, int *value_len)
+{
+ char *value = NULL; /* holding area for value */
+ int value_size = 0; /* size of holding area */
+ char *ptr; /* pointer to current value position */
+ int len; /* length of this cell/string/byte */
+ int ival;
+ int upto; /* the number of bytes we have written to buf */
+ char fmt[3];
+
+ upto = 0;
+
+ if (disp->verbose)
+ fprintf(stderr, "Decoding value:\n");
+
+ fmt[0] = '%';
+ fmt[1] = disp->type ? disp->type : 'd';
+ fmt[2] = '\0';
+ for (; arg_count > 0; arg++, arg_count--, upto += len) {
+ /* assume integer unless told otherwise */
+ if (disp->type == 's')
+ len = strlen(*arg) + 1;
+ else
+ len = disp->size == -1 ? 4 : disp->size;
+
+ /* enlarge our value buffer by a suitable margin if needed */
+ if (upto + len > value_size) {
+ value_size = (upto + len) + 500;
+ value = realloc(value, value_size);
+ if (!value) {
+ fprintf(stderr, "Out of mmory: cannot alloc "
+ "%d bytes\n", value_size);
+ return -1;
+ }
+ }
+
+ ptr = value + upto;
+ if (disp->type == 's') {
+ memcpy(ptr, *arg, len);
+ if (disp->verbose)
+ fprintf(stderr, "\tstring: '%s'\n", ptr);
+ } else {
+ int *iptr = (int *)ptr;
+ sscanf(*arg, fmt, &ival);
+ if (len == 4)
+ *iptr = cpu_to_fdt32(ival);
+ else
+ *ptr = (uint8_t)ival;
+ if (disp->verbose) {
+ fprintf(stderr, "\t%s: %d\n",
+ disp->size == 1 ? "byte" :
+ disp->size == 2 ? "short" : "int",
+ ival);
+ }
+ }
+ }
+ *value_len = upto;
+ *valuep = value;
+ if (disp->verbose)
+ fprintf(stderr, "Value size %d\n", upto);
+ return 0;
+}
+
+static int store_key_value(void *blob, const char *node_name,
+ const char *property, const char *buf, int len)
+{
+ int node;
+ int err;
+
+ node = fdt_path_offset(blob, node_name);
+ if (node < 0) {
+ report_error(node_name, -1, node);
+ return -1;
+ }
+
+ err = fdt_setprop(blob, node, property, buf, len);
+ if (err) {
+ report_error(property, -1, err);
+ return -1;
+ }
+ return 0;
+}
+
+/**
+ * Create paths as needed for all components of a path
+ *
+ * Any components of the path that do not exist are created. Errors are
+ * reported.
+ *
+ * @param blob FDT blob to write into
+ * @param in_path Path to process
+ * @return 0 if ok, -1 on error
+ */
+static int create_paths(void *blob, const char *in_path)
+{
+ const char *path = in_path;
+ const char *sep;
+ int node, offset = 0;
+
+ /* skip leading '/' */
+ while (*path == '/')
+ path++;
+
+ for (sep = path; *sep; path = sep + 1, offset = node) {
+ /* equivalent to strchrnul(), but it requires _GNU_SOURCE */
+ sep = strchr(path, '/');
+ if (!sep)
+ sep = path + strlen(path);
+
+ node = fdt_subnode_offset_namelen(blob, offset, path,
+ sep - path);
+ if (node == -FDT_ERR_NOTFOUND) {
+ node = fdt_add_subnode_namelen(blob, offset, path,
+ sep - path);
+ }
+ if (node < 0) {
+ report_error(path, sep - path, node);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Create a new node in the fdt.
+ *
+ * This will overwrite the node_name string. Any error is reported.
+ *
+ * TODO: Perhaps create fdt_path_offset_namelen() so we don't need to do this.
+ *
+ * @param blob FDT blob to write into
+ * @param node_name Name of node to create
+ * @return new node offset if found, or -1 on failure
+ */
+static int create_node(void *blob, const char *node_name)
+{
+ int node = 0;
+ char *p;
+
+ p = strrchr(node_name, '/');
+ if (!p) {
+ report_error(node_name, -1, -FDT_ERR_BADPATH);
+ return -1;
+ }
+ *p = '\0';
+
+ if (p > node_name) {
+ node = fdt_path_offset(blob, node_name);
+ if (node < 0) {
+ report_error(node_name, -1, node);
+ return -1;
+ }
+ }
+
+ node = fdt_add_subnode(blob, node, p + 1);
+ if (node < 0) {
+ report_error(p + 1, -1, node);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int do_fdtput(struct display_info *disp, const char *filename,
+ char **arg, int arg_count)
+{
+ char *value;
+ char *blob;
+ int len, ret = 0;
+
+ blob = utilfdt_read(filename);
+ if (!blob)
+ return -1;
+
+ switch (disp->oper) {
+ case OPER_WRITE_PROP:
+ /*
+ * Convert the arguments into a single binary value, then
+ * store them into the property.
+ */
+ assert(arg_count >= 2);
+ if (disp->auto_path && create_paths(blob, *arg))
+ return -1;
+ if (encode_value(disp, arg + 2, arg_count - 2, &value, &len) ||
+ store_key_value(blob, *arg, arg[1], value, len))
+ ret = -1;
+ break;
+ case OPER_CREATE_NODE:
+ for (; ret >= 0 && arg_count--; arg++) {
+ if (disp->auto_path)
+ ret = create_paths(blob, *arg);
+ else
+ ret = create_node(blob, *arg);
+ }
+ break;
+ }
+ if (ret >= 0)
+ ret = utilfdt_write(filename, blob);
+
+ free(blob);
+ return ret;
+}
+
+static const char *usage_msg =
+ "fdtput - write a property value to a device tree\n"
+ "\n"
+ "The command line arguments are joined together into a single value.\n"
+ "\n"
+ "Usage:\n"
+ " fdtput <options> <dt file> <node> <property> [<value>...]\n"
+ " fdtput -c <options> <dt file> [<node>...]\n"
+ "Options:\n"
+ "\t-c\t\tCreate nodes if they don't already exist\n"
+ "\t-p\t\tAutomatically create nodes as needed for the node path\n"
+ "\t-t <type>\tType of data\n"
+ "\t-v\t\tVerbose: display each value decoded from command line\n"
+ "\t-h\t\tPrint this help\n\n"
+ USAGE_TYPE_MSG;
+
+static void usage(const char *msg)
+{
+ if (msg)
+ fprintf(stderr, "Error: %s\n\n", msg);
+
+ fprintf(stderr, "%s", usage_msg);
+ exit(2);
+}
+
+int main(int argc, char *argv[])
+{
+ struct display_info disp;
+ char *filename = NULL;
+
+ memset(&disp, '\0', sizeof(disp));
+ disp.size = -1;
+ disp.oper = OPER_WRITE_PROP;
+ for (;;) {
+ int c = getopt(argc, argv, "chpt:v");
+ if (c == -1)
+ break;
+
+ /*
+ * TODO: add options to:
+ * - delete property
+ * - delete node (optionally recursively)
+ * - rename node
+ * - pack fdt before writing
+ * - set amount of free space when writing
+ * - expand fdt if value doesn't fit
+ */
+ switch (c) {
+ case 'c':
+ disp.oper = OPER_CREATE_NODE;
+ break;
+ case 'h':
+ case '?':
+ usage(NULL);
+ case 'p':
+ disp.auto_path = 1;
+ break;
+ case 't':
+ if (utilfdt_decode_type(optarg, &disp.type,
+ &disp.size))
+ usage("Invalid type string");
+ break;
+
+ case 'v':
+ disp.verbose = 1;
+ break;
+ }
+ }
+
+ if (optind < argc)
+ filename = argv[optind++];
+ if (!filename)
+ usage("Missing filename");
+
+ argv += optind;
+ argc -= optind;
+
+ if (disp.oper == OPER_WRITE_PROP) {
+ if (argc < 1)
+ usage("Missing node");
+ if (argc < 2)
+ usage("Missing property");
+ }
+
+ if (do_fdtput(&disp, filename, argv, argc))
+ return 1;
+ return 0;
+}
diff --git a/scripts/dtc/flattree.c b/scripts/dtc/flattree.c
index 28d0b2381df..665dad7bb46 100644
--- a/scripts/dtc/flattree.c
+++ b/scripts/dtc/flattree.c
@@ -263,6 +263,9 @@ static void flatten_tree(struct node *tree, struct emitter *emit,
struct node *child;
int seen_name_prop = 0;
+ if (tree->deleted)
+ return;
+
emit->beginnode(etarget, tree->labels);
if (vi->flags & FTF_FULLPATH)
diff --git a/scripts/dtc/libfdt/Makefile.libfdt b/scripts/dtc/libfdt/Makefile.libfdt
index 6c42acfa21e..91126c000a1 100644
--- a/scripts/dtc/libfdt/Makefile.libfdt
+++ b/scripts/dtc/libfdt/Makefile.libfdt
@@ -3,6 +3,8 @@
# This is not a complete Makefile of itself. Instead, it is designed to
# be easily embeddable into other systems of Makefiles.
#
-LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_soname = libfdt.$(SHAREDLIB_EXT).1
+LIBFDT_INCLUDES = fdt.h libfdt.h libfdt_env.h
+LIBFDT_VERSION = version.lds
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c fdt_empty_tree.c
LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2acaec5923a..e56833ae9b6 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -74,7 +74,7 @@ int fdt_check_header(const void *fdt)
return 0;
}
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len)
{
const char *p;
@@ -90,42 +90,53 @@ const void *fdt_offset_ptr(const void *fdt, int offset, int len)
return p;
}
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset)
{
const uint32_t *tagp, *lenp;
uint32_t tag;
+ int offset = startoffset;
const char *p;
- if (offset % FDT_TAGSIZE)
- return -1;
-
+ *nextoffset = -FDT_ERR_TRUNCATED;
tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
+ if (!tagp)
return FDT_END; /* premature end */
tag = fdt32_to_cpu(*tagp);
offset += FDT_TAGSIZE;
+ *nextoffset = -FDT_ERR_BADSTRUCTURE;
switch (tag) {
case FDT_BEGIN_NODE:
/* skip name */
do {
p = fdt_offset_ptr(fdt, offset++, 1);
} while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
+ if (!p)
+ return FDT_END; /* premature end */
break;
+
case FDT_PROP:
lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ if (!lenp)
+ return FDT_END; /* premature end */
+ /* skip-name offset, length and value */
+ offset += sizeof(struct fdt_property) - FDT_TAGSIZE
+ + fdt32_to_cpu(*lenp);
+ break;
+
+ case FDT_END:
+ case FDT_END_NODE:
+ case FDT_NOP:
break;
+
+ default:
+ return FDT_END;
}
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
+ if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset))
+ return FDT_END; /* premature end */
+ *nextoffset = FDT_TAGALIGN(offset);
return tag;
}
@@ -138,6 +149,15 @@ int _fdt_check_node_offset(const void *fdt, int offset)
return offset;
}
+int _fdt_check_prop_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
int fdt_next_node(const void *fdt, int offset, int *depth)
{
int nextoffset = 0;
@@ -162,15 +182,16 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
break;
case FDT_END_NODE:
- if (depth)
- (*depth)--;
+ if (depth && ((--(*depth)) < 0))
+ return nextoffset;
break;
case FDT_END:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
+ if ((nextoffset >= 0)
+ || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth))
+ return -FDT_ERR_NOTFOUND;
+ else
+ return nextoffset;
}
} while (tag != FDT_BEGIN_NODE);
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/libfdt/fdt_empty_tree.c
new file mode 100644
index 00000000000..f72d13b1d19
--- /dev/null
+++ b/scripts/dtc/libfdt/fdt_empty_tree.c
@@ -0,0 +1,84 @@
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_create_empty_tree(void *buf, int bufsize)
+{
+ int err;
+
+ err = fdt_create(buf, bufsize);
+ if (err)
+ return err;
+
+ err = fdt_finish_reservemap(buf);
+ if (err)
+ return err;
+
+ err = fdt_begin_node(buf, "");
+ if (err)
+ return err;
+
+ err = fdt_end_node(buf);
+ if (err)
+ return err;
+
+ err = fdt_finish(buf);
+ if (err)
+ return err;
+
+ return fdt_open_into(buf, buf, bufsize);
+}
+
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c
index 22e692919ff..02b6d687537 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/libfdt/fdt_ro.c
@@ -80,6 +80,14 @@ const char *fdt_string(const void *fdt, int stroffset)
return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
}
+static int _fdt_string_eq(const void *fdt, int stroffset,
+ const char *s, int len)
+{
+ const char *p = fdt_string(fdt, stroffset);
+
+ return (strlen(p) == len) && (memcmp(p, s, len) == 0);
+}
+
int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
{
FDT_CHECK_HEADER(fdt);
@@ -97,6 +105,30 @@ int fdt_num_mem_rsv(const void *fdt)
return i;
}
+static int _nextprop(const void *fdt, int offset)
+{
+ uint32_t tag;
+ int nextoffset;
+
+ do {
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ if (nextoffset >= 0)
+ return -FDT_ERR_BADSTRUCTURE;
+ else
+ return nextoffset;
+
+ case FDT_PROP:
+ return offset;
+ }
+ offset = nextoffset;
+ } while (tag == FDT_NOP);
+
+ return -FDT_ERR_NOTFOUND;
+}
+
int fdt_subnode_offset_namelen(const void *fdt, int offset,
const char *name, int namelen)
{
@@ -104,20 +136,16 @@ int fdt_subnode_offset_namelen(const void *fdt, int offset,
FDT_CHECK_HEADER(fdt);
- for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
- (offset >= 0) && (depth > 0);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth < 0)
- return -FDT_ERR_NOTFOUND;
- else if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
+ for (depth = 0;
+ (offset >= 0) && (depth >= 0);
+ offset = fdt_next_node(fdt, offset, &depth))
+ if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
return offset;
- }
- if (offset < 0)
- return offset; /* error */
- else
+ if (depth < 0)
return -FDT_ERR_NOTFOUND;
+ return offset; /* error */
}
int fdt_subnode_offset(const void *fdt, int parentoffset,
@@ -134,8 +162,20 @@ int fdt_path_offset(const void *fdt, const char *path)
FDT_CHECK_HEADER(fdt);
- if (*path != '/')
- return -FDT_ERR_BADPATH;
+ /* see if we have an alias */
+ if (*path != '/') {
+ const char *q = strchr(path, '/');
+
+ if (!q)
+ q = end;
+
+ p = fdt_get_alias_namelen(fdt, p, q - p);
+ if (!p)
+ return -FDT_ERR_BADPATH;
+ offset = fdt_path_offset(fdt, p);
+
+ p = q;
+ }
while (*p) {
const char *q;
@@ -178,93 +218,142 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
return NULL;
}
-const struct fdt_property *fdt_get_property(const void *fdt,
- int nodeoffset,
- const char *name, int *lenp)
+int fdt_first_property_offset(const void *fdt, int nodeoffset)
+{
+ int offset;
+
+ if ((offset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+int fdt_next_property_offset(const void *fdt, int offset)
+{
+ if ((offset = _fdt_check_prop_offset(fdt, offset)) < 0)
+ return offset;
+
+ return _nextprop(fdt, offset);
+}
+
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp)
{
- uint32_t tag;
- const struct fdt_property *prop;
- int namestroff;
- int offset, nextoffset;
int err;
+ const struct fdt_property *prop;
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
- goto fail;
+ if ((err = _fdt_check_prop_offset(fdt, offset)) < 0) {
+ if (lenp)
+ *lenp = err;
+ return NULL;
+ }
- nextoffset = err;
- do {
- offset = nextoffset;
+ prop = _fdt_offset_ptr(fdt, offset);
- tag = fdt_next_tag(fdt, offset, &nextoffset);
- switch (tag) {
- case FDT_END:
- err = -FDT_ERR_TRUNCATED;
- goto fail;
+ if (lenp)
+ *lenp = fdt32_to_cpu(prop->len);
- case FDT_BEGIN_NODE:
- case FDT_END_NODE:
- case FDT_NOP:
- break;
+ return prop;
+}
- case FDT_PROP:
- err = -FDT_ERR_BADSTRUCTURE;
- prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
- if (! prop)
- goto fail;
- namestroff = fdt32_to_cpu(prop->nameoff);
- if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
- /* Found it! */
- int len = fdt32_to_cpu(prop->len);
- prop = fdt_offset_ptr(fdt, offset,
- sizeof(*prop)+len);
- if (! prop)
- goto fail;
-
- if (lenp)
- *lenp = len;
-
- return prop;
- }
- break;
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int offset,
+ const char *name,
+ int namelen, int *lenp)
+{
+ for (offset = fdt_first_property_offset(fdt, offset);
+ (offset >= 0);
+ (offset = fdt_next_property_offset(fdt, offset))) {
+ const struct fdt_property *prop;
- default:
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
+ if (!(prop = fdt_get_property_by_offset(fdt, offset, lenp))) {
+ offset = -FDT_ERR_INTERNAL;
+ break;
}
- } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+ if (_fdt_string_eq(fdt, fdt32_to_cpu(prop->nameoff),
+ name, namelen))
+ return prop;
+ }
- err = -FDT_ERR_NOTFOUND;
- fail:
if (lenp)
- *lenp = err;
+ *lenp = offset;
return NULL;
}
-const void *fdt_getprop(const void *fdt, int nodeoffset,
- const char *name, int *lenp)
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_get_property_namelen(fdt, nodeoffset, name,
+ strlen(name), lenp);
+}
+
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp)
{
const struct fdt_property *prop;
- prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+ prop = fdt_get_property_namelen(fdt, nodeoffset, name, namelen, lenp);
if (! prop)
return NULL;
return prop->data;
}
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property_by_offset(fdt, offset, lenp);
+ if (!prop)
+ return NULL;
+ if (namep)
+ *namep = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+ return prop->data;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp);
+}
+
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
{
const uint32_t *php;
int len;
- php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
- if (!php || (len != sizeof(*php)))
- return 0;
+ /* FIXME: This is a bit sub-optimal, since we potentially scan
+ * over all the properties twice. */
+ php = fdt_getprop(fdt, nodeoffset, "phandle", &len);
+ if (!php || (len != sizeof(*php))) {
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+ }
return fdt32_to_cpu(*php);
}
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen)
+{
+ int aliasoffset;
+
+ aliasoffset = fdt_path_offset(fdt, "/aliases");
+ if (aliasoffset < 0)
+ return NULL;
+
+ return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL);
+}
+
+const char *fdt_get_alias(const void *fdt, const char *name)
+{
+ return fdt_get_alias_namelen(fdt, name, strlen(name));
+}
+
int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
{
int pdepth = 0, p = 0;
@@ -279,9 +368,6 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
for (offset = 0, depth = 0;
(offset >= 0) && (offset <= nodeoffset);
offset = fdt_next_node(fdt, offset, &depth)) {
- if (pdepth < depth)
- continue; /* overflowed buffer */
-
while (pdepth > depth) {
do {
p--;
@@ -289,14 +375,16 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
pdepth--;
}
- name = fdt_get_name(fdt, offset, &namelen);
- if (!name)
- return namelen;
- if ((p + namelen + 1) <= buflen) {
- memcpy(buf + p, name, namelen);
- p += namelen;
- buf[p++] = '/';
- pdepth++;
+ if (pdepth >= depth) {
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
}
if (offset == nodeoffset) {
@@ -306,7 +394,7 @@ int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
if (p > 1) /* special case so that root path is "/", not "" */
p--;
buf[p] = '\0';
- return p;
+ return 0;
}
}
@@ -404,14 +492,31 @@ int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
{
+ int offset;
+
if ((phandle == 0) || (phandle == -1))
return -FDT_ERR_BADPHANDLE;
- phandle = cpu_to_fdt32(phandle);
- return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
- &phandle, sizeof(phandle));
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we
+ * potentially scan each property of a node in
+ * fdt_get_phandle(), then if that didn't find what
+ * we want, we scan over them again making our way to the next
+ * node. Still it's the easiest to implement approach;
+ * performance can come later. */
+ for (offset = fdt_next_node(fdt, -1, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ if (fdt_get_phandle(fdt, offset) == phandle)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
}
-static int _stringlist_contains(const char *strlist, int listlen, const char *str)
+static int _fdt_stringlist_contains(const char *strlist, int listlen,
+ const char *str)
{
int len = strlen(str);
const char *p;
@@ -437,7 +542,7 @@ int fdt_node_check_compatible(const void *fdt, int nodeoffset,
prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
if (!prop)
return len;
- if (_stringlist_contains(prop, len, compatible))
+ if (_fdt_stringlist_contains(prop, len, compatible))
return 0;
else
return 1;
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 8e7ec4cb7bc..24437dfc32b 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -289,6 +289,33 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
return 0;
}
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err, oldlen, newlen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (prop) {
+ newlen = len + oldlen;
+ err = _fdt_splice_struct(fdt, prop->data,
+ FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(newlen));
+ if (err)
+ return err;
+ prop->len = cpu_to_fdt32(newlen);
+ memcpy(prop->data + oldlen, val, len);
+ } else {
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+ memcpy(prop->data, val, len);
+ }
+ return 0;
+}
+
int fdt_delprop(void *fdt, int nodeoffset, const char *name)
{
struct fdt_property *prop;
@@ -406,6 +433,8 @@ int fdt_open_into(const void *fdt, void *buf, int bufsize)
struct_size = 0;
while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
;
+ if (struct_size < 0)
+ return struct_size;
}
if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c
index 698329e0cca..55ebebf1eb2 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/libfdt/fdt_sw.c
@@ -70,7 +70,7 @@ static int _fdt_sw_check_header(void *fdt)
return err; \
}
-static void *_fdt_grab_space(void *fdt, int len)
+static void *_fdt_grab_space(void *fdt, size_t len)
{
int offset = fdt_size_dt_struct(fdt);
int spaceleft;
@@ -82,7 +82,7 @@ static void *_fdt_grab_space(void *fdt, int len)
return NULL;
fdt_set_size_dt_struct(fdt, offset + len);
- return fdt_offset_ptr_w(fdt, offset, len);
+ return _fdt_offset_ptr_w(fdt, offset);
}
int fdt_create(void *buf, int bufsize)
@@ -237,18 +237,17 @@ int fdt_finish(void *fdt)
while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
if (tag == FDT_PROP) {
struct fdt_property *prop =
- fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+ _fdt_offset_ptr_w(fdt, offset);
int nameoff;
- if (! prop)
- return -FDT_ERR_BADSTRUCTURE;
-
nameoff = fdt32_to_cpu(prop->nameoff);
nameoff += fdt_size_dt_strings(fdt);
prop->nameoff = cpu_to_fdt32(nameoff);
}
offset = nextoffset;
}
+ if (nextoffset < 0)
+ return nextoffset;
/* Finally, adjust the header */
fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c
index a4652c6e787..6025fa1fe8f 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/libfdt/fdt_wip.c
@@ -94,41 +94,14 @@ int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
return 0;
}
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
+int _fdt_node_end_offset(void *fdt, int offset)
{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
-
- tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
- if (tag != FDT_BEGIN_NODE)
- return -FDT_ERR_BADOFFSET;
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- switch (tag) {
- case FDT_END:
- return offset;
-
- case FDT_BEGIN_NODE:
- level++;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
-
- return nextoffset;
+ int depth = 0;
+
+ while ((offset >= 0) && (depth >= 0))
+ offset = fdt_next_node(fdt, offset, &depth);
+
+ return offset;
}
int fdt_nop_node(void *fdt, int nodeoffset)
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h
index ff6246f000c..73f49759a5e 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt/libfdt.h
@@ -61,7 +61,7 @@
#define FDT_ERR_NOTFOUND 1
/* FDT_ERR_NOTFOUND: The requested node or property does not exist */
#define FDT_ERR_EXISTS 2
- /* FDT_ERR_EXISTS: Attempted to create a node or property which
+ /* FDT_ERR_EXISTS: Attemped to create a node or property which
* already exists */
#define FDT_ERR_NOSPACE 3
/* FDT_ERR_NOSPACE: Operation needed to expand the device
@@ -122,7 +122,7 @@
/* Low-level functions (you probably don't need these) */
/**********************************************************************/
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen);
static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
{
return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
@@ -156,7 +156,7 @@ int fdt_next_node(const void *fdt, int offset, int *depth);
#define __fdt_set_hdr(name) \
static inline void fdt_set_##name(void *fdt, uint32_t val) \
{ \
- struct fdt_header *fdth = fdt; \
+ struct fdt_header *fdth = (struct fdt_header*)fdt; \
fdth->name = cpu_to_fdt32(val); \
}
__fdt_set_hdr(magic);
@@ -343,6 +343,91 @@ int fdt_path_offset(const void *fdt, const char *path);
const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
/**
+ * fdt_first_property_offset - find the offset of a node's first property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ *
+ * fdt_first_property_offset() finds the first property of the node at
+ * the given structure block offset.
+ *
+ * returns:
+ * structure block offset of the property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested node has no properties
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_first_property_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_next_property_offset - step through a node's properties
+ * @fdt: pointer to the device tree blob
+ * @offset: structure block offset of a property
+ *
+ * fdt_next_property_offset() finds the property immediately after the
+ * one at the given structure block offset. This will be a property
+ * of the same node as the given property.
+ *
+ * returns:
+ * structure block offset of the next property (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the given property is the last in its node
+ * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_next_property_offset(const void *fdt, int offset);
+
+/**
+ * fdt_get_property_by_offset - retrieve the property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @offset: offset of the property to retrieve
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property_by_offset() retrieves a pointer to the
+ * fdt_property structure within the device tree blob at the given
+ * offset. If lenp is non-NULL, the length of the property value is
+ * also returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property_by_offset(const void *fdt,
+ int offset,
+ int *lenp);
+
+/**
+ * fdt_get_property_namelen - find a property based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_get_property_namelen(), but only examine the first
+ * namelen characters of name for matching the property name.
+ */
+const struct fdt_property *fdt_get_property_namelen(const void *fdt,
+ int nodeoffset,
+ const char *name,
+ int namelen, int *lenp);
+
+/**
* fdt_get_property - find a given property in a given node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -380,6 +465,54 @@ static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
}
/**
+ * fdt_getprop_by_offset - retrieve the value of a property at a given offset
+ * @fdt: pointer to the device tree blob
+ * @ffset: offset of the property to read
+ * @namep: pointer to a string variable (will be overwritten) or NULL
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop_by_offset() retrieves a pointer to the value of the
+ * property at structure block offset 'offset' (this will be a pointer
+ * to within the device blob itself, not a copy of the value). If
+ * lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp. If namep is non-NULL,
+ * the property's namne will also be returned in the char * pointed to
+ * by namep (this will be a pointer to within the device tree's string
+ * block, not a new copy of the name).
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * if namep is non-NULL *namep contiains a pointer to the property
+ * name.
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop_by_offset(const void *fdt, int offset,
+ const char **namep, int *lenp);
+
+/**
+ * fdt_getprop_namelen - get property value based on substring
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @namelen: number of characters of name to consider
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * Identical to fdt_getprop(), but only examine the first namelen
+ * characters of name for matching the property name.
+ */
+const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
+ const char *name, int namelen, int *lenp);
+
+/**
* fdt_getprop - retrieve the value of a given property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to find
@@ -429,6 +562,32 @@ static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
/**
+ * fdt_get_alias_namelen - get alias based on substring
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_get_alias(), but only examine the first namelen
+ * characters of name for matching the alias name.
+ */
+const char *fdt_get_alias_namelen(const void *fdt,
+ const char *name, int namelen);
+
+/**
+ * fdt_get_alias - retreive the path referenced by a given alias
+ * @fdt: pointer to the device tree blob
+ * @name: name of the alias th look up
+ *
+ * fdt_get_alias() retrieves the value of a given alias. That is, the
+ * value of the property named 'name' in the node /aliases.
+ *
+ * returns:
+ * a pointer to the expansion of the alias named 'name', of it exists
+ * NULL, if the given alias or the /aliases node does not exist
+ */
+const char *fdt_get_alias(const void *fdt, const char *name);
+
+/**
* fdt_get_path - determine the full path of a node
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose path to find
@@ -693,17 +852,17 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
+ * @val: 32-bit integer value to replace the property with
*
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary. This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
+ * fdt_setprop_inplace_u32() replaces the value of a given property
+ * with the 32-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 4.
*
* This function will alter only the bytes in the blob which contain
* the given property value, and will not alter or move any other part
@@ -712,7 +871,7 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
* returns:
* 0, on success
* -FDT_ERR_NOSPACE, if the property's length is not equal to 4
- * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_NOTFOUND, node does not have the named property
* -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
* -FDT_ERR_BADMAGIC,
* -FDT_ERR_BADVERSION,
@@ -720,14 +879,60 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADSTRUCTURE,
* -FDT_ERR_TRUNCATED, standard meanings
*/
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
- const char *name, uint32_t val)
+static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
}
/**
+ * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to replace the property with
+ *
+ * fdt_setprop_inplace_u64() replaces the value of a given property
+ * with the 64-bit integer value in val, converting val to big-endian
+ * if necessary. This function cannot change the size of a property,
+ * and so will only work if the property already exists and has length
+ * 8.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 8
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ *
+ * This is an alternative name for fdt_setprop_inplace_u32()
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val);
+}
+
+/**
* fdt_nop_property - replace a property with nop tags
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
@@ -786,11 +991,20 @@ int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
int fdt_finish_reservemap(void *fdt);
int fdt_begin_node(void *fdt, const char *name);
int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_property(fdt, name, &val, sizeof(val));
}
+static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_property(fdt, name, &val, sizeof(val));
+}
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+ return fdt_property_u32(fdt, name, val);
+}
#define fdt_property_string(fdt, name, str) \
fdt_property(fdt, name, str, strlen(str)+1)
int fdt_end_node(void *fdt);
@@ -800,6 +1014,7 @@ int fdt_finish(void *fdt);
/* Read-write functions */
/**********************************************************************/
+int fdt_create_empty_tree(void *buf, int bufsize);
int fdt_open_into(const void *fdt, void *buf, int bufsize);
int fdt_pack(void *fdt);
@@ -909,14 +1124,14 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
const void *val, int len);
/**
- * fdt_setprop_cell - set a property to a single cell value
+ * fdt_setprop_u32 - set a property to a 32-bit integer
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
* @name: name of the property to change
* @val: 32-bit integer value for the property (native endian)
*
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
+ * fdt_setprop_u32() sets the value of the named property in the given
+ * node to the given 32-bit integer value (converting to big-endian if
* necessary), or creates a new property with that value if it does
* not already exist.
*
@@ -936,14 +1151,60 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name,
* -FDT_ERR_BADLAYOUT,
* -FDT_ERR_TRUNCATED, standard meanings
*/
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
- uint32_t val)
+static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
{
val = cpu_to_fdt32(val);
return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
}
/**
+ * fdt_setprop_u64 - set a property to a 64-bit integer
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_u64() sets the value of the named property in the given
+ * node to the given 64-bit integer value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name,
+ uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ *
+ * This is an alternative name for fdt_setprop_u32()
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
+{
+ return fdt_setprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
* fdt_setprop_string - set a property to a string value
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to change
@@ -975,6 +1236,147 @@ static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
/**
+ * fdt_appendprop - append to or create a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to append to
+ * @val: pointer to data to append to the property value
+ * @len: length of the data to append to the property value
+ *
+ * fdt_appendprop() appends the value to the named property in the
+ * given node, creating the property if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_appendprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_appendprop_u32 - append a 32-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u32() appends the given 32-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u32(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_u64 - append a 64-bit integer value to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 64-bit integer value to append to the property (native endian)
+ *
+ * fdt_appendprop_u64() appends the given 64-bit integer value
+ * (converting to big-endian if necessary) to the value of the named
+ * property in the given node, or creates a new property with that
+ * value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_appendprop_u64(void *fdt, int nodeoffset,
+ const char *name, uint64_t val)
+{
+ val = cpu_to_fdt64(val);
+ return fdt_appendprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_appendprop_cell - append a single cell value to a property
+ *
+ * This is an alternative name for fdt_appendprop_u32()
+ */
+static inline int fdt_appendprop_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ return fdt_appendprop_u32(fdt, nodeoffset, name, val);
+}
+
+/**
+ * fdt_appendprop_string - append a string to a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value to append to the property
+ *
+ * fdt_appendprop_string() appends the given string to the value of
+ * the named property in the given node, or creates a new property
+ * with that value if it does not already exist.
+ *
+ * This function may insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_appendprop_string(fdt, nodeoffset, name, str) \
+ fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
* fdt_delprop - delete a property
* @fdt: pointer to the device tree blob
* @nodeoffset: offset of the node whose property to nop
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt/libfdt_env.h
index 449bf602daf..213d7fb81c4 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt/libfdt_env.h
@@ -5,19 +5,25 @@
#include <stdint.h>
#include <string.h>
-#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
+#define EXTRACT_BYTE(n) ((unsigned long long)((uint8_t *)&x)[n])
+static inline uint16_t fdt16_to_cpu(uint16_t x)
+{
+ return (EXTRACT_BYTE(0) << 8) | EXTRACT_BYTE(1);
+}
+#define cpu_to_fdt16(x) fdt16_to_cpu(x)
+
static inline uint32_t fdt32_to_cpu(uint32_t x)
{
- return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+ return (EXTRACT_BYTE(0) << 24) | (EXTRACT_BYTE(1) << 16) | (EXTRACT_BYTE(2) << 8) | EXTRACT_BYTE(3);
}
#define cpu_to_fdt32(x) fdt32_to_cpu(x)
static inline uint64_t fdt64_to_cpu(uint64_t x)
{
- return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
- | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+ return (EXTRACT_BYTE(0) << 56) | (EXTRACT_BYTE(1) << 48) | (EXTRACT_BYTE(2) << 40) | (EXTRACT_BYTE(3) << 32)
+ | (EXTRACT_BYTE(4) << 24) | (EXTRACT_BYTE(5) << 16) | (EXTRACT_BYTE(6) << 8) | EXTRACT_BYTE(7);
}
#define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
+#undef EXTRACT_BYTE
#endif /* _LIBFDT_ENV_H */
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h
index 46eb93e4af5..381133ba81d 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt/libfdt_internal.h
@@ -62,8 +62,8 @@
return err; \
}
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
int _fdt_check_node_offset(const void *fdt, int offset);
+int _fdt_check_prop_offset(const void *fdt, int offset);
const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
int _fdt_node_end_offset(void *fdt, int nodeoffset);
diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c
index 26d0e1e60c0..b61465fb2f3 100644
--- a/scripts/dtc/livetree.c
+++ b/scripts/dtc/livetree.c
@@ -29,16 +29,27 @@ void add_label(struct label **labels, char *label)
struct label *new;
/* Make sure the label isn't already there */
- for_each_label(*labels, new)
- if (streq(new->label, label))
+ for_each_label_withdel(*labels, new)
+ if (streq(new->label, label)) {
+ new->deleted = 0;
return;
+ }
new = xmalloc(sizeof(*new));
+ memset(new, 0, sizeof(*new));
new->label = label;
new->next = *labels;
*labels = new;
}
+void delete_labels(struct label **labels)
+{
+ struct label *label;
+
+ for_each_label(*labels, label)
+ label->deleted = 1;
+}
+
struct property *build_property(char *name, struct data val)
{
struct property *new = xmalloc(sizeof(*new));
@@ -51,6 +62,18 @@ struct property *build_property(char *name, struct data val)
return new;
}
+struct property *build_property_delete(char *name)
+{
+ struct property *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->name = name;
+ new->deleted = 1;
+
+ return new;
+}
+
struct property *chain_property(struct property *first, struct property *list)
{
assert(first->next == NULL);
@@ -91,6 +114,17 @@ struct node *build_node(struct property *proplist, struct node *children)
return new;
}
+struct node *build_node_delete(void)
+{
+ struct node *new = xmalloc(sizeof(*new));
+
+ memset(new, 0, sizeof(*new));
+
+ new->deleted = 1;
+
+ return new;
+}
+
struct node *name_node(struct node *node, char *name)
{
assert(node->name == NULL);
@@ -106,8 +140,10 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
struct node *new_child, *old_child;
struct label *l;
+ old_node->deleted = 0;
+
/* Add new node labels to old node */
- for_each_label(new_node->labels, l)
+ for_each_label_withdel(new_node->labels, l)
add_label(&old_node->labels, l->label);
/* Move properties from the new node to the old node. If there
@@ -118,14 +154,21 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
new_node->proplist = new_prop->next;
new_prop->next = NULL;
+ if (new_prop->deleted) {
+ delete_property_by_name(old_node, new_prop->name);
+ free(new_prop);
+ continue;
+ }
+
/* Look for a collision, set new value if there is */
- for_each_property(old_node, old_prop) {
+ for_each_property_withdel(old_node, old_prop) {
if (streq(old_prop->name, new_prop->name)) {
/* Add new labels to old property */
- for_each_label(new_prop->labels, l)
+ for_each_label_withdel(new_prop->labels, l)
add_label(&old_prop->labels, l->label);
old_prop->val = new_prop->val;
+ old_prop->deleted = 0;
free(new_prop);
new_prop = NULL;
break;
@@ -146,8 +189,14 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
new_child->parent = NULL;
new_child->next_sibling = NULL;
+ if (new_child->deleted) {
+ delete_node_by_name(old_node, new_child->name);
+ free(new_child);
+ continue;
+ }
+
/* Search for a collision. Merge if there is */
- for_each_child(old_node, old_child) {
+ for_each_child_withdel(old_node, old_child) {
if (streq(old_child->name, new_child->name)) {
merge_nodes(old_child, new_child);
new_child = NULL;
@@ -155,7 +204,7 @@ struct node *merge_nodes(struct node *old_node, struct node *new_node)
}
}
- /* if no collision occurred, add child to the old node. */
+ /* if no collision occured, add child to the old node. */
if (new_child)
add_child(old_node, new_child);
}
@@ -188,6 +237,25 @@ void add_property(struct node *node, struct property *prop)
*p = prop;
}
+void delete_property_by_name(struct node *node, char *name)
+{
+ struct property *prop = node->proplist;
+
+ while (prop) {
+ if (!strcmp(prop->name, name)) {
+ delete_property(prop);
+ return;
+ }
+ prop = prop->next;
+ }
+}
+
+void delete_property(struct property *prop)
+{
+ prop->deleted = 1;
+ delete_labels(&prop->labels);
+}
+
void add_child(struct node *parent, struct node *child)
{
struct node **p;
@@ -202,6 +270,32 @@ void add_child(struct node *parent, struct node *child)
*p = child;
}
+void delete_node_by_name(struct node *parent, char *name)
+{
+ struct node *node = parent->children;
+
+ while (node) {
+ if (!strcmp(node->name, name)) {
+ delete_node(node);
+ return;
+ }
+ node = node->next_sibling;
+ }
+}
+
+void delete_node(struct node *node)
+{
+ struct property *prop;
+ struct node *child;
+
+ node->deleted = 1;
+ for_each_child(node, child)
+ delete_node(child);
+ for_each_property(node, prop)
+ delete_property(prop);
+ delete_labels(&node->labels);
+}
+
struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size)
{
struct reserve_info *new = xmalloc(sizeof(*new));
@@ -353,8 +447,11 @@ struct node *get_node_by_path(struct node *tree, const char *path)
const char *p;
struct node *child;
- if (!path || ! (*path))
+ if (!path || ! (*path)) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
while (path[0] == '/')
path++;
@@ -397,8 +494,11 @@ struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
assert((phandle != 0) && (phandle != -1));
- if (tree->phandle == phandle)
+ if (tree->phandle == phandle) {
+ if (tree->deleted)
+ return NULL;
return tree;
+ }
for_each_child(tree, child) {
node = get_node_by_phandle(child, phandle);
@@ -535,7 +635,7 @@ static void sort_properties(struct node *node)
int n = 0, i = 0;
struct property *prop, **tbl;
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
n++;
if (n == 0)
@@ -543,7 +643,7 @@ static void sort_properties(struct node *node)
tbl = xmalloc(n * sizeof(*tbl));
- for_each_property(node, prop)
+ for_each_property_withdel(node, prop)
tbl[i++] = prop;
qsort(tbl, n, sizeof(*tbl), cmp_prop);
@@ -571,7 +671,7 @@ static void sort_subnodes(struct node *node)
int n = 0, i = 0;
struct node *subnode, **tbl;
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
n++;
if (n == 0)
@@ -579,7 +679,7 @@ static void sort_subnodes(struct node *node)
tbl = xmalloc(n * sizeof(*tbl));
- for_each_child(node, subnode)
+ for_each_child_withdel(node, subnode)
tbl[i++] = subnode;
qsort(tbl, n, sizeof(*tbl), cmp_subnode);
@@ -598,7 +698,7 @@ static void sort_node(struct node *node)
sort_properties(node);
sort_subnodes(node);
- for_each_child(node, c)
+ for_each_child_withdel(node, c)
sort_node(c);
}
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
index 36a38e9f1a2..246ab4bc0d9 100644
--- a/scripts/dtc/srcpos.c
+++ b/scripts/dtc/srcpos.c
@@ -24,6 +24,15 @@
#include "dtc.h"
#include "srcpos.h"
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+ struct search_path *next; /* next node in list, NULL for end */
+ const char *dirname; /* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
static char *dirname(const char *path)
{
@@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */
#define MAX_SRCFILE_DEPTH (100)
static int srcfile_depth; /* = 0 */
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname Directory to look in, or NULL for none
+ * @param fname Filename to look for
+ * @param fp Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+ char *fullname;
+
+ if (!dirname || fname[0] == '/')
+ fullname = xstrdup(fname);
+ else
+ fullname = join_path(dirname, fname);
+
+ *fp = fopen(fullname, "r");
+ if (!*fp) {
+ free(fullname);
+ fullname = NULL;
+ }
+
+ return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname Filename to open
+ * @param fp Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+ const char *cur_dir = NULL;
+ struct search_path *node;
+ char *fullname;
+
+ /* Try current directory first */
+ assert(fp);
+ if (current_srcfile)
+ cur_dir = current_srcfile->dir;
+ fullname = try_open(cur_dir, fname, fp);
+
+ /* Failing that, try each search path in turn */
+ for (node = search_path_head; !*fp && node; node = node->next)
+ fullname = try_open(node->dirname, fname, fp);
+
+ return fullname;
+}
+
FILE *srcfile_relative_open(const char *fname, char **fullnamep)
{
FILE *f;
@@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep)
f = stdin;
fullname = xstrdup("<stdin>");
} else {
- if (!current_srcfile || !current_srcfile->dir
- || (fname[0] == '/'))
- fullname = xstrdup(fname);
- else
- fullname = join_path(current_srcfile->dir, fname);
-
- f = fopen(fullname, "r");
+ fullname = fopen_any_on_path(fname, &f);
if (!f)
die("Couldn't open \"%s\": %s\n", fname,
strerror(errno));
@@ -119,6 +180,23 @@ int srcfile_pop(void)
return current_srcfile ? 1 : 0;
}
+void srcfile_add_search_path(const char *dirname)
+{
+ struct search_path *node;
+
+ /* Create the node */
+ node = xmalloc(sizeof(*node));
+ node->next = NULL;
+ node->dirname = xstrdup(dirname);
+
+ /* Add to the end of our list */
+ if (search_path_tail)
+ *search_path_tail = node;
+ else
+ search_path_head = node;
+ search_path_tail = &node->next;
+}
+
/*
* The empty source position.
*/
@@ -250,3 +328,9 @@ srcpos_warn(struct srcpos *pos, char const *fmt, ...)
va_end(va);
}
+
+void srcpos_set_line(char *f, int l)
+{
+ current_srcfile->name = f;
+ current_srcfile->lineno = l;
+}
diff --git a/scripts/dtc/srcpos.h b/scripts/dtc/srcpos.h
index ce980cafe58..93a27123c2e 100644
--- a/scripts/dtc/srcpos.h
+++ b/scripts/dtc/srcpos.h
@@ -33,10 +33,39 @@ struct srcfile_state {
extern FILE *depfile; /* = NULL */
extern struct srcfile_state *current_srcfile; /* = NULL */
+/**
+ * Open a source file.
+ *
+ * If the source file is a relative pathname, then it is searched for in the
+ * current directory (the directory of the last source file read) and after
+ * that in the search path.
+ *
+ * We work through the search path in order from the first path specified to
+ * the last.
+ *
+ * If the file is not found, then this function does not return, but calls
+ * die().
+ *
+ * @param fname Filename to search
+ * @param fullnamep If non-NULL, it is set to the allocated filename of the
+ * file that was opened. The caller is then responsible
+ * for freeing the pointer.
+ * @return pointer to opened FILE
+ */
FILE *srcfile_relative_open(const char *fname, char **fullnamep);
+
void srcfile_push(const char *fname);
int srcfile_pop(void);
+/**
+ * Add a new directory to the search path for input files
+ *
+ * The new path is added at the end of the list.
+ *
+ * @param dirname Directory to add
+ */
+void srcfile_add_search_path(const char *dirname);
+
struct srcpos {
int first_line;
int first_column;
@@ -84,4 +113,6 @@ extern void srcpos_error(struct srcpos *pos, char const *, ...)
extern void srcpos_warn(struct srcpos *pos, char const *, ...)
__attribute__((format(printf, 2, 3)));
+extern void srcpos_set_line(char *f, int l);
+
#endif /* _SRCPOS_H_ */
diff --git a/scripts/dtc/treesource.c b/scripts/dtc/treesource.c
index c09aafade31..33eeba55fb4 100644
--- a/scripts/dtc/treesource.c
+++ b/scripts/dtc/treesource.c
@@ -23,6 +23,7 @@
extern FILE *yyin;
extern int yyparse(void);
+extern YYLTYPE yylloc;
struct boot_info *the_boot_info;
int treesource_error;
@@ -34,6 +35,7 @@ struct boot_info *dt_from_source(const char *fname)
srcfile_push(fname);
yyin = current_srcfile->f;
+ yylloc.file = current_srcfile;
if (yyparse() != 0)
die("Unable to parse input tree\n");
diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c
index d7ac27d2ae1..2422c34e11d 100644
--- a/scripts/dtc/util.c
+++ b/scripts/dtc/util.c
@@ -1,6 +1,10 @@
/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
+ * util_is_printable_string contributed by
+ * Pantelis Antoniou <pantelis.antoniou AT gmail.com>
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
@@ -17,11 +21,18 @@
* USA
*/
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
+#include <assert.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "libfdt.h"
#include "util.h"
char *xstrdup(const char *s)
@@ -57,3 +68,264 @@ char *join_path(const char *path, const char *name)
memcpy(str+lenp, name, lenn+1);
return str;
}
+
+int util_is_printable_string(const void *data, int len)
+{
+ const char *s = data;
+ const char *ss;
+
+ /* zero length is not */
+ if (len == 0)
+ return 0;
+
+ /* must terminate with zero */
+ if (s[len - 1] != '\0')
+ return 0;
+
+ ss = s;
+ while (*s && isprint(*s))
+ s++;
+
+ /* not zero, or not done yet */
+ if (*s != '\0' || (s + 1 - ss) < len)
+ return 0;
+
+ return 1;
+}
+
+/*
+ * Parse a octal encoded character starting at index i in string s. The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_oct_char(const char *s, int *i)
+{
+ char x[4];
+ char *endx;
+ long val;
+
+ x[3] = '\0';
+ strncpy(x, s + *i, 3);
+
+ val = strtol(x, &endx, 8);
+
+ assert(endx > x);
+
+ (*i) += endx - x;
+ return val;
+}
+
+/*
+ * Parse a hexadecimal encoded character starting at index i in string s. The
+ * resulting character will be returned and the index i will be updated to
+ * point at the character directly after the end of the encoding, this may be
+ * the '\0' terminator of the string.
+ */
+static char get_hex_char(const char *s, int *i)
+{
+ char x[3];
+ char *endx;
+ long val;
+
+ x[2] = '\0';
+ strncpy(x, s + *i, 2);
+
+ val = strtol(x, &endx, 16);
+ if (!(endx > x))
+ die("\\x used with no following hex digits\n");
+
+ (*i) += endx - x;
+ return val;
+}
+
+char get_escape_char(const char *s, int *i)
+{
+ char c = s[*i];
+ int j = *i + 1;
+ char val;
+
+ assert(c);
+ switch (c) {
+ case 'a':
+ val = '\a';
+ break;
+ case 'b':
+ val = '\b';
+ break;
+ case 't':
+ val = '\t';
+ break;
+ case 'n':
+ val = '\n';
+ break;
+ case 'v':
+ val = '\v';
+ break;
+ case 'f':
+ val = '\f';
+ break;
+ case 'r':
+ val = '\r';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ j--; /* need to re-read the first digit as
+ * part of the octal value */
+ val = get_oct_char(s, &j);
+ break;
+ case 'x':
+ val = get_hex_char(s, &j);
+ break;
+ default:
+ val = c;
+ }
+
+ (*i) = j;
+ return val;
+}
+
+int utilfdt_read_err(const char *filename, char **buffp)
+{
+ int fd = 0; /* assume stdin */
+ char *buf = NULL;
+ off_t bufsize = 1024, offset = 0;
+ int ret = 0;
+
+ *buffp = NULL;
+ if (strcmp(filename, "-") != 0) {
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return errno;
+ }
+
+ /* Loop until we have read everything */
+ buf = malloc(bufsize);
+ do {
+ /* Expand the buffer to hold the next chunk */
+ if (offset == bufsize) {
+ bufsize *= 2;
+ buf = realloc(buf, bufsize);
+ if (!buf) {
+ ret = ENOMEM;
+ break;
+ }
+ }
+
+ ret = read(fd, &buf[offset], bufsize - offset);
+ if (ret < 0) {
+ ret = errno;
+ break;
+ }
+ offset += ret;
+ } while (ret != 0);
+
+ /* Clean up, including closing stdin; return errno on error */
+ close(fd);
+ if (ret)
+ free(buf);
+ else
+ *buffp = buf;
+ return ret;
+}
+
+char *utilfdt_read(const char *filename)
+{
+ char *buff;
+ int ret = utilfdt_read_err(filename, &buff);
+
+ if (ret) {
+ fprintf(stderr, "Couldn't open blob from '%s': %s\n", filename,
+ strerror(ret));
+ return NULL;
+ }
+ /* Successful read */
+ return buff;
+}
+
+int utilfdt_write_err(const char *filename, const void *blob)
+{
+ int fd = 1; /* assume stdout */
+ int totalsize;
+ int offset;
+ int ret = 0;
+ const char *ptr = blob;
+
+ if (strcmp(filename, "-") != 0) {
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+ if (fd < 0)
+ return errno;
+ }
+
+ totalsize = fdt_totalsize(blob);
+ offset = 0;
+
+ while (offset < totalsize) {
+ ret = write(fd, ptr + offset, totalsize - offset);
+ if (ret < 0) {
+ ret = -errno;
+ break;
+ }
+ offset += ret;
+ }
+ /* Close the file/stdin; return errno on error */
+ if (fd != 1)
+ close(fd);
+ return ret < 0 ? -ret : 0;
+}
+
+
+int utilfdt_write(const char *filename, const void *blob)
+{
+ int ret = utilfdt_write_err(filename, blob);
+
+ if (ret) {
+ fprintf(stderr, "Couldn't write blob to '%s': %s\n", filename,
+ strerror(ret));
+ }
+ return ret ? -1 : 0;
+}
+
+int utilfdt_decode_type(const char *fmt, int *type, int *size)
+{
+ int qualifier = 0;
+
+ if (!*fmt)
+ return -1;
+
+ /* get the conversion qualifier */
+ *size = -1;
+ if (strchr("hlLb", *fmt)) {
+ qualifier = *fmt++;
+ if (qualifier == *fmt) {
+ switch (*fmt++) {
+/* TODO: case 'l': qualifier = 'L'; break;*/
+ case 'h':
+ qualifier = 'b';
+ break;
+ }
+ }
+ }
+
+ /* we should now have a type */
+ if ((*fmt == '\0') || !strchr("iuxs", *fmt))
+ return -1;
+
+ /* convert qualifier (bhL) to byte size */
+ if (*fmt != 's')
+ *size = qualifier == 'b' ? 1 :
+ qualifier == 'h' ? 2 :
+ qualifier == 'l' ? 4 : -1;
+ *type = *fmt++;
+
+ /* that should be it! */
+ if (*fmt)
+ return -1;
+ return 0;
+}
diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h
index 9cead842c11..c8eb45d9f04 100644
--- a/scripts/dtc/util.h
+++ b/scripts/dtc/util.h
@@ -1,7 +1,10 @@
#ifndef _UTIL_H
#define _UTIL_H
+#include <stdarg.h>
+
/*
+ * Copyright 2011 The Chromium Authors, All Rights Reserved.
* Copyright 2008 Jon Loeliger, Freescale Semiconductor, Inc.
*
* This program is free software; you can redistribute it and/or
@@ -53,4 +56,98 @@ static inline void *xrealloc(void *p, size_t len)
extern char *xstrdup(const char *s);
extern char *join_path(const char *path, const char *name);
+/**
+ * Check a string of a given length to see if it is all printable and
+ * has a valid terminator.
+ *
+ * @param data The string to check
+ * @param len The string length including terminator
+ * @return 1 if a valid printable string, 0 if not */
+int util_is_printable_string(const void *data, int len);
+
+/*
+ * Parse an escaped character starting at index i in string s. The resulting
+ * character will be returned and the index i will be updated to point at the
+ * character directly after the end of the encoding, this may be the '\0'
+ * terminator of the string.
+ */
+char get_escape_char(const char *s, int *i);
+
+/**
+ * Read a device tree file into a buffer. This will report any errors on
+ * stderr.
+ *
+ * @param filename The filename to read, or - for stdin
+ * @return Pointer to allocated buffer containing fdt, or NULL on error
+ */
+char *utilfdt_read(const char *filename);
+
+/**
+ * Read a device tree file into a buffer. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename The filename to read, or - for stdin
+ * @param buffp Returns pointer to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_read_err(const char *filename, char **buffp);
+
+
+/**
+ * Write a device tree buffer to a file. This will report any errors on
+ * stderr.
+ *
+ * @param filename The filename to write, or - for stdout
+ * @param blob Poiner to buffer containing fdt
+ * @return 0 if ok, -1 on error
+ */
+int utilfdt_write(const char *filename, const void *blob);
+
+/**
+ * Write a device tree buffer to a file. Does not report errors, but only
+ * returns them. The value returned can be passed to strerror() to obtain
+ * an error message for the user.
+ *
+ * @param filename The filename to write, or - for stdout
+ * @param blob Poiner to buffer containing fdt
+ * @return 0 if ok, else an errno value representing the error
+ */
+int utilfdt_write_err(const char *filename, const void *blob);
+
+/**
+ * Decode a data type string. The purpose of this string
+ *
+ * The string consists of an optional character followed by the type:
+ * Modifier characters:
+ * hh or b 1 byte
+ * h 2 byte
+ * l 4 byte, default
+ *
+ * Type character:
+ * s string
+ * i signed integer
+ * u unsigned integer
+ * x hex
+ *
+ * TODO: Implement ll modifier (8 bytes)
+ * TODO: Implement o type (octal)
+ *
+ * @param fmt Format string to process
+ * @param type Returns type found(s/d/u/x), or 0 if none
+ * @param size Returns size found(1,2,4,8) or 4 if none
+ * @return 0 if ok, -1 on error (no type given, or other invalid format)
+ */
+int utilfdt_decode_type(const char *fmt, int *type, int *size);
+
+/*
+ * This is a usage message fragment for the -t option. It is the format
+ * supported by utilfdt_decode_type.
+ */
+
+#define USAGE_TYPE_MSG \
+ "<type>\ts=string, i=int, u=unsigned, x=hex\n" \
+ "\tOptional modifier prefix:\n" \
+ "\t\thh or b=byte, h=2 byte, l=4 byte (default)\n";
+
#endif /* _UTIL_H */
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
index debecb5561c..7f2126df91f 100644
--- a/scripts/gcc-version.sh
+++ b/scripts/gcc-version.sh
@@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then
exit 1
fi
-MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1)
-MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1)
+MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
+MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
if [ "x$with_patchlevel" != "x" ] ; then
- PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1)
+ PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
else
printf "%02d%02d\\n" $MAJOR $MINOR
diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh
index 29493dc4528..12dbd0b11ea 100644
--- a/scripts/gcc-x86_32-has-stack-protector.sh
+++ b/scripts/gcc-x86_32-has-stack-protector.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
if [ "$?" -eq "0" ] ; then
echo y
else
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index afaec618b39..973e8c14156 100644
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
+echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
if [ "$?" -eq "0" ] ; then
echo y
else
diff --git a/scripts/headers_install.pl b/scripts/headers_install.pl
index 48462be328b..239d22d4207 100644
--- a/scripts/headers_install.pl
+++ b/scripts/headers_install.pl
@@ -4,8 +4,7 @@
# user space and copy the files to their destination.
#
# Usage: headers_install.pl readdir installdir arch [files...]
-# readdir: dir to open files
-# installdir: dir to install the files
+# installdir: dir to install the files to
# arch: current architecture
# arch is used to force a reinstallation when the arch
# changes because kbuild then detect a command line change.
@@ -18,15 +17,18 @@
use strict;
-my ($readdir, $installdir, $arch, @files) = @ARGV;
+my ($installdir, $arch, @files) = @ARGV;
my $unifdef = "scripts/unifdef -U__KERNEL__ -D__EXPORTED_HEADERS__";
-foreach my $file (@files) {
+foreach my $filename (@files) {
+ my $file = $filename;
+ $file =~ s!^.*/!!;
+
my $tmpfile = "$installdir/$file.tmp";
- open(my $in, '<', "$readdir/$file")
- or die "$readdir/$file: $!\n";
+ open(my $in, '<', $filename)
+ or die "$filename: $!\n";
open(my $out, '>', $tmpfile)
or die "$tmpfile: $!\n";
while (my $line = <$in>) {
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 77d53999ffb..3091794e935 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
$< --$@ $(Kconfig)
-PHONY += listnewconfig oldnoconfig savedefconfig defconfig
+PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
-listnewconfig oldnoconfig: $(obj)/conf
+listnewconfig olddefconfig: $(obj)/conf
$< --$@ $(Kconfig)
+# oldnoconfig is an alias of olddefconfig, because people already are dependent
+# on its behavior(sets new symbols to their default value but not 'n') with the
+# counter-intuitive name.
+oldnoconfig: $(obj)/conf
+ $< --olddefconfig $(Kconfig)
+
savedefconfig: $(obj)/conf
$< --$@=defconfig $(Kconfig)
@@ -114,7 +120,7 @@ help:
@echo ' alldefconfig - New config with all symbols set to default'
@echo ' randconfig - New config with random answer to all options'
@echo ' listnewconfig - List new options'
- @echo ' oldnoconfig - Same as silentoldconfig but sets new symbols to their default value'
+ @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value'
# lxdialog stuff
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh
index fa59cbf9d62..854d9c7c675 100755
--- a/scripts/kconfig/check.sh
+++ b/scripts/kconfig/check.sh
@@ -1,6 +1,6 @@
#!/bin/sh
# Needed for systems without gettext
-$* -xc -o /dev/null - > /dev/null 2>&1 << EOF
+$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
#include <libintl.h>
int main()
{
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 0dc4a2c779b..4da3b4adfad 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -32,7 +32,7 @@ enum input_mode {
defconfig,
savedefconfig,
listnewconfig,
- oldnoconfig,
+ olddefconfig,
} input_mode = oldaskconfig;
static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
case P_MENU:
if ((input_mode == silentoldconfig ||
input_mode == listnewconfig ||
- input_mode == oldnoconfig) &&
+ input_mode == olddefconfig) &&
rootEntry != menu) {
check_conf(menu);
return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
if (sym->name && !sym_is_choice_value(sym)) {
printf("%s%s\n", CONFIG_, sym->name);
}
- } else if (input_mode != oldnoconfig) {
+ } else if (input_mode != olddefconfig) {
if (!conf_cnt++)
printf(_("*\n* Restart config...\n*\n"));
rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
{"alldefconfig", no_argument, NULL, alldefconfig},
{"randconfig", no_argument, NULL, randconfig},
{"listnewconfig", no_argument, NULL, listnewconfig},
- {"oldnoconfig", no_argument, NULL, oldnoconfig},
+ {"olddefconfig", no_argument, NULL, olddefconfig},
+ /*
+ * oldnoconfig is an alias of olddefconfig, because people already
+ * are dependent on its behavior(sets new symbols to their default
+ * value but not 'n') with the counter-intuitive name.
+ */
+ {"oldnoconfig", no_argument, NULL, olddefconfig},
{NULL, 0, NULL, 0}
};
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
printf(" --oldconfig Update a configuration using a provided .config as base\n");
printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
- printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n");
+ printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
+ printf(" --oldnoconfig An alias of olddefconfig\n");
printf(" --defconfig <file> New config with default defined in <file>\n");
printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
printf(" --allnoconfig New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
case allmodconfig:
case alldefconfig:
case listnewconfig:
- case oldnoconfig:
+ case olddefconfig:
break;
case '?':
conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
case oldaskconfig:
case oldconfig:
case listnewconfig:
- case oldnoconfig:
+ case olddefconfig:
conf_read(NULL);
break;
case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
/* fall through */
case oldconfig:
case listnewconfig:
- case oldnoconfig:
+ case olddefconfig:
case silentoldconfig:
/* Update until a loop caused no more changes */
do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
check_conf(&rootmenu);
} while (conf_cnt &&
(input_mode != listnewconfig &&
- input_mode != oldnoconfig));
+ input_mode != olddefconfig));
break;
}
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index d4ecce8bc3a..bd2e0989555 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,6 +12,7 @@ extern "C" {
#include <assert.h>
#include <stdio.h>
+#include <sys/queue.h>
#ifndef __cplusplus
#include <stdbool.h>
#endif
@@ -173,6 +174,16 @@ struct menu {
#define MENU_CHANGED 0x0001
#define MENU_ROOT 0x0002
+struct jump_key {
+ CIRCLEQ_ENTRY(jump_key) entries;
+ size_t offset;
+ struct menu *target;
+ int index;
+};
+CIRCLEQ_HEAD(jk_head, jump_key);
+
+#define JUMP_NB 9
+
extern struct file *file_list;
extern struct file *current_file;
struct file *lookup_file(const char *name);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 47fe9c340f9..1d1c08537f1 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -21,8 +21,10 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
P(menu_get_parent_menu,struct menu *,(struct menu *menu));
P(menu_has_help,bool,(struct menu *menu));
P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr));
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+ *head));
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+ *head));
P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
/* symbol.c */
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index e3b12c01041..c8e8a715475 100644
--- a/scripts/kconfig/lxdialog/check-lxdialog.sh
+++ b/scripts/kconfig/lxdialog/check-lxdialog.sh
@@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15
# Check if we can link to ncurses
check() {
- $cc -xc - -o $tmp 2>/dev/null <<'EOF'
+ $cc -x c - -o $tmp 2>/dev/null <<'EOF'
#include CURSES_LOC
main() {}
EOF
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index b5211fce0d9..ee17a5264d5 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -144,6 +144,7 @@ struct dialog_info {
*/
extern struct dialog_info dlg;
extern char dialog_input_result[];
+extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
/*
* Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
int dialog_yesno(const char *title, const char *prompt, int height, int width);
int dialog_msgbox(const char *title, const char *prompt, int height,
int width, int pause);
-int dialog_textbox(const char *title, const char *file, int height, int width);
+
+
+typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
+ *_data);
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
+ update_text_fn update_text, void *data);
int dialog_menu(const char *title, const char *prompt,
const void *selected, int *s_scroll);
int dialog_checklist(const char *title, const char *prompt, int height,
diff --git a/scripts/kconfig/lxdialog/textbox.c b/scripts/kconfig/lxdialog/textbox.c
index 4e5de60a0c0..a48bb93e090 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -22,23 +22,25 @@
#include "dialog.h"
static void back_lines(int n);
-static void print_page(WINDOW * win, int height, int width);
-static void print_line(WINDOW * win, int row, int width);
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+ update_text, void *data);
+static void print_line(WINDOW *win, int row, int width);
static char *get_line(void);
static void print_position(WINDOW * win);
static int hscroll;
static int begin_reached, end_reached, page_length;
-static const char *buf;
-static const char *page;
+static char *buf;
+static char *page;
/*
* refresh window content
*/
static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
- int cur_y, int cur_x)
+ int cur_y, int cur_x, update_text_fn update_text,
+ void *data)
{
- print_page(box, boxh, boxw);
+ print_page(box, boxh, boxw, update_text, data);
print_position(dialog);
wmove(dialog, cur_y, cur_x); /* Restore cursor position */
wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
/*
* Display text from a file in a dialog box.
+ *
+ * keys is a null-terminated array
+ * update_text() may not add or remove any '\n' or '\0' in tbuf
*/
-int dialog_textbox(const char *title, const char *tbuf,
- int initial_height, int initial_width)
+int dialog_textbox(const char *title, char *tbuf, int initial_height,
+ int initial_width, int *keys, int *_vscroll, int *_hscroll,
+ update_text_fn update_text, void *data)
{
int i, x, y, cur_x, cur_y, key = 0;
int height, width, boxh, boxw;
- int passed_end;
WINDOW *dialog, *box;
+ bool done = false;
begin_reached = 1;
end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
buf = tbuf;
page = buf; /* page is pointer to start of page to be displayed */
+ if (_vscroll && *_vscroll) {
+ begin_reached = 0;
+
+ for (i = 0; i < *_vscroll; i++)
+ get_line();
+ }
+ if (_hscroll)
+ hscroll = *_hscroll;
+
do_resize:
getmaxyx(stdscr, height, width);
if (height < 8 || width < 8)
@@ -120,9 +135,10 @@ do_resize:
/* Print first page of text */
attr_clear(box, boxh, boxw, dlg.dialog.atr);
- refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
+ data);
- while ((key != KEY_ESC) && (key != '\n')) {
+ while (!done) {
key = wgetch(dialog);
switch (key) {
case 'E': /* Exit */
@@ -130,16 +146,17 @@ do_resize:
case 'X':
case 'x':
case 'q':
- delwin(box);
- delwin(dialog);
- return 0;
+ case '\n':
+ done = true;
+ break;
case 'g': /* First page */
case KEY_HOME:
if (!begin_reached) {
begin_reached = 1;
page = buf;
refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ cur_y, cur_x, update_text,
+ data);
}
break;
case 'G': /* Last page */
@@ -149,45 +166,18 @@ do_resize:
/* point to last char in buf */
page = buf + strlen(buf);
back_lines(boxh);
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case 'K': /* Previous line */
case 'k':
case KEY_UP:
- if (!begin_reached) {
- back_lines(page_length + 1);
-
- /* We don't call print_page() here but use
- * scrolling to ensure faster screen update.
- * However, 'end_reached' and 'page_length'
- * should still be updated, and 'page' should
- * point to start of next page. This is done
- * by calling get_line() in the following
- * 'for' loop. */
- scrollok(box, TRUE);
- wscrl(box, -1); /* Scroll box region down one line */
- scrollok(box, FALSE);
- page_length = 0;
- passed_end = 0;
- for (i = 0; i < boxh; i++) {
- if (!i) {
- /* print first line of page */
- print_line(box, 0, boxw);
- wnoutrefresh(box);
- } else
- /* Called to update 'end_reached' and 'page' */
- get_line();
- if (!passed_end)
- page_length++;
- if (end_reached && !passed_end)
- passed_end = 1;
- }
+ if (begin_reached)
+ break;
- print_position(dialog);
- wmove(dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh(dialog);
- }
+ back_lines(page_length + 1);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case 'B': /* Previous page */
case 'b':
@@ -196,23 +186,18 @@ do_resize:
if (begin_reached)
break;
back_lines(page_length + boxh);
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case 'J': /* Next line */
case 'j':
case KEY_DOWN:
- if (!end_reached) {
- begin_reached = 0;
- scrollok(box, TRUE);
- scroll(box); /* Scroll box region up one line */
- scrollok(box, FALSE);
- print_line(box, boxh - 1, boxw);
- wnoutrefresh(box);
- print_position(dialog);
- wmove(dialog, cur_y, cur_x); /* Restore cursor position */
- wrefresh(dialog);
- }
+ if (end_reached)
+ break;
+
+ back_lines(page_length - 1);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case KEY_NPAGE: /* Next page */
case ' ':
@@ -221,8 +206,8 @@ do_resize:
break;
begin_reached = 0;
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case '0': /* Beginning of line */
case 'H': /* Scroll left */
@@ -237,8 +222,8 @@ do_resize:
hscroll--;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case 'L': /* Scroll right */
case 'l':
@@ -248,11 +233,12 @@ do_resize:
hscroll++;
/* Reprint current page to scroll horizontally */
back_lines(page_length);
- refresh_text_box(dialog, box, boxh, boxw,
- cur_y, cur_x);
+ refresh_text_box(dialog, box, boxh, boxw, cur_y,
+ cur_x, update_text, data);
break;
case KEY_ESC:
- key = on_key_esc(dialog);
+ if (on_key_esc(dialog) == KEY_ESC)
+ done = true;
break;
case KEY_RESIZE:
back_lines(height);
@@ -260,11 +246,31 @@ do_resize:
delwin(dialog);
on_key_resize();
goto do_resize;
+ default:
+ for (i = 0; keys[i]; i++) {
+ if (key == keys[i]) {
+ done = true;
+ break;
+ }
+ }
}
}
delwin(box);
delwin(dialog);
- return key; /* ESC pressed */
+ if (_vscroll) {
+ const char *s;
+
+ s = buf;
+ *_vscroll = 0;
+ back_lines(page_length);
+ while (s < page && (s = strchr(s, '\n'))) {
+ (*_vscroll)++;
+ s++;
+ }
+ }
+ if (_hscroll)
+ *_hscroll = hscroll;
+ return key;
}
/*
@@ -301,12 +307,23 @@ static void back_lines(int n)
}
/*
- * Print a new page of text. Called by dialog_textbox().
+ * Print a new page of text.
*/
-static void print_page(WINDOW * win, int height, int width)
+static void print_page(WINDOW *win, int height, int width, update_text_fn
+ update_text, void *data)
{
int i, passed_end = 0;
+ if (update_text) {
+ char *end;
+
+ for (i = 0; i < height; i++)
+ get_line();
+ end = page;
+ back_lines(height);
+ update_text(buf, page - buf, end - buf, data);
+ }
+
page_length = 0;
for (i = 0; i < height; i++) {
print_line(win, i, width);
@@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
}
/*
- * Print a new line of text. Called by dialog_textbox() and print_page().
+ * Print a new line of text.
*/
static void print_line(WINDOW * win, int row, int width)
{
@@ -357,10 +374,8 @@ static char *get_line(void)
end_reached = 0;
while (*page != '\n') {
if (*page == '\0') {
- if (!end_reached) {
- end_reached = 1;
- break;
- }
+ end_reached = 1;
+ break;
} else if (i < MAX_LEN)
line[i++] = *(page++);
else {
@@ -373,7 +388,7 @@ static char *get_line(void)
if (i <= MAX_LEN)
line[i] = '\0';
if (!end_reached)
- page++; /* move pass '\n' */
+ page++; /* move past '\n' */
return line;
}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index f2375ad7ebc..109d53117d2 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -23,6 +23,9 @@
#include "dialog.h"
+/* Needed in signal handler in mconf.c */
+int saved_x, saved_y;
+
struct dialog_info dlg;
static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
int height, width;
initscr(); /* Init curses */
+
+ /* Get current cursor position for signal handler in mconf.c */
+ getyx(stdscr, saved_y, saved_x);
+
getmaxyx(stdscr, height, width);
if (height < 19 || width < 80) {
endwin();
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index f584a281bb4..48f67448af7 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -236,16 +236,19 @@ search_help[] = N_(
"Result:\n"
"-----------------------------------------------------------------\n"
"Symbol: FOO [=m]\n"
+ "Type : tristate\n"
"Prompt: Foo bus is used to drive the bar HW\n"
- "Defined at drivers/pci/Kconfig:47\n"
- "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
- "Location:\n"
- " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
- " -> PCI support (PCI [=y])\n"
- " -> PCI access mode (<choice> [=y])\n"
- "Selects: LIBCRC32\n"
- "Selected by: BAR\n"
+ " Defined at drivers/pci/Kconfig:47\n"
+ " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
+ " Location:\n"
+ " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
+ " -> PCI support (PCI [=y])\n"
+ "(1) -> PCI access mode (<choice> [=y])\n"
+ " Selects: LIBCRC32\n"
+ " Selected by: BAR\n"
"-----------------------------------------------------------------\n"
+ "o The line 'Type:' shows the type of the configuration option for\n"
+ " this symbol (boolean, tristate, string, ...)\n"
"o The line 'Prompt:' shows the text used in the menu structure for\n"
" this symbol\n"
"o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
" this symbol to be visible in the menu (selectable)\n"
"o The 'Location:' lines tell where in the menu structure this symbol\n"
" is located\n"
- " A location followed by a [=y] indicate that this is a selectable\n"
- " menu item - and current value is displayed inside brackets.\n"
+ " A location followed by a [=y] indicates that this is a\n"
+ " selectable menu item - and the current value is displayed inside\n"
+ " brackets.\n"
+ " Press the key in the (#) prefix to jump directly to that\n"
+ " location. You will be returned to the current search results\n"
+ " after exiting this new menu.\n"
"o The 'Selects:' line tell what symbol will be automatically\n"
" selected if this symbol is selected (y or m)\n"
"o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
static int child_count;
static int single_menu_mode;
static int show_all_options;
-static int saved_x, saved_y;
-static void conf(struct menu *menu);
+static void conf(struct menu *menu, struct menu *active_menu);
static void conf_choice(struct menu *menu);
static void conf_string(struct menu *menu);
static void conf_load(void);
static void conf_save(void);
+static int show_textbox_ext(const char *title, char *text, int r, int c,
+ int *keys, int *vscroll, int *hscroll,
+ update_text_fn update_text, void *data);
static void show_textbox(const char *title, const char *text, int r, int c);
static void show_helptext(const char *title, const char *text);
static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
}
+struct search_data {
+ struct jk_head *head;
+ struct menu **targets;
+ int *keys;
+};
+
+static void update_text(char *buf, size_t start, size_t end, void *_data)
+{
+ struct search_data *data = _data;
+ struct jump_key *pos;
+ int k = 0;
+
+ CIRCLEQ_FOREACH(pos, data->head, entries) {
+ if (pos->offset >= start && pos->offset < end) {
+ char header[4];
+
+ if (k < JUMP_NB) {
+ int key = '0' + (pos->index % JUMP_NB) + 1;
+
+ sprintf(header, "(%c)", key);
+ data->keys[k] = key;
+ data->targets[k] = pos->target;
+ k++;
+ } else {
+ sprintf(header, " ");
+ }
+
+ memcpy(buf + pos->offset, header, sizeof(header) - 1);
+ }
+ }
+ data->keys[k] = 0;
+}
+
static void search_conf(void)
{
struct symbol **sym_arr;
struct gstr res;
char *dialog_input;
- int dres;
+ int dres, vscroll = 0, hscroll = 0;
+ bool again;
+
again:
dialog_clear();
dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
dialog_input += strlen(CONFIG_);
sym_arr = sym_re_search(dialog_input);
- res = get_relations_str(sym_arr);
+ do {
+ struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+ struct menu *targets[JUMP_NB];
+ int keys[JUMP_NB + 1], i;
+ struct search_data data = {
+ .head = &head,
+ .targets = targets,
+ .keys = keys,
+ };
+
+ res = get_relations_str(sym_arr, &head);
+ dres = show_textbox_ext(_("Search Results"), (char *)
+ str_get(&res), 0, 0, keys, &vscroll,
+ &hscroll, &update_text, (void *)
+ &data);
+ again = false;
+ for (i = 0; i < JUMP_NB && keys[i]; i++)
+ if (dres == keys[i]) {
+ conf(targets[i]->parent, targets[i]);
+ again = true;
+ }
+ str_free(&res);
+ } while (again);
free(sym_arr);
- show_textbox(_("Search Results"), str_get(&res), 0, 0);
- str_free(&res);
}
static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
indent -= doint;
}
-static void conf(struct menu *menu)
+static void conf(struct menu *menu, struct menu *active_menu)
{
struct menu *submenu;
const char *prompt = menu_get_prompt(menu);
struct symbol *sym;
- struct menu *active_menu = NULL;
int res;
int s_scroll = 0;
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
if (single_menu_mode)
submenu->data = (void *) (long) !submenu->data;
else
- conf(submenu);
+ conf(submenu, NULL);
break;
case 't':
if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
conf_choice(submenu);
else if (submenu->prompt->type == P_MENU)
- conf(submenu);
+ conf(submenu, NULL);
break;
case 's':
conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
if (item_is_tag('t'))
sym_toggle_tristate_value(sym);
else if (item_is_tag('m'))
- conf(submenu);
+ conf(submenu, NULL);
break;
case 7:
search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
}
}
-static void show_textbox(const char *title, const char *text, int r, int c)
+static int show_textbox_ext(const char *title, char *text, int r, int c, int
+ *keys, int *vscroll, int *hscroll, update_text_fn
+ update_text, void *data)
{
dialog_clear();
- dialog_textbox(title, text, r, c);
+ return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
+ update_text, data);
+}
+
+static void show_textbox(const char *title, const char *text, int r, int c)
+{
+ show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
+ NULL, NULL);
}
static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
single_menu_mode = 1;
}
- initscr();
-
- getyx(stdscr, saved_y, saved_x);
if (init_dialog(NULL)) {
fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
set_config_filename(conf_get_configname());
do {
- conf(&rootmenu);
+ conf(&rootmenu, NULL);
res = handle_exit();
} while (res == KEY_ESC);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c2a97e60fa..a3cade659f8 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
return "";
}
-static void get_prompt_str(struct gstr *r, struct property *prop)
+static void get_prompt_str(struct gstr *r, struct property *prop,
+ struct jk_head *head)
{
int i, j;
- struct menu *submenu[8], *menu;
+ struct menu *submenu[8], *menu, *location = NULL;
+ struct jump_key *jump;
str_printf(r, _("Prompt: %s\n"), _(prop->text));
str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name,
@@ -521,13 +523,43 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
str_append(r, "\n");
}
menu = prop->menu->parent;
- for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent)
+ for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
+ bool accessible = menu_is_visible(menu);
+
submenu[i++] = menu;
+ if (location == NULL && accessible)
+ location = menu;
+ }
+ if (head && location) {
+ jump = malloc(sizeof(struct jump_key));
+
+ if (menu_is_visible(prop->menu)) {
+ /*
+ * There is not enough room to put the hint at the
+ * beginning of the "Prompt" line. Put the hint on the
+ * last "Location" line even when it would belong on
+ * the former.
+ */
+ jump->target = prop->menu;
+ } else
+ jump->target = location;
+
+ if (CIRCLEQ_EMPTY(head))
+ jump->index = 0;
+ else
+ jump->index = CIRCLEQ_LAST(head)->index + 1;
+
+ CIRCLEQ_INSERT_TAIL(head, jump, entries);
+ }
+
if (i > 0) {
str_printf(r, _(" Location:\n"));
for (j = 4; --i >= 0; j += 2) {
menu = submenu[i];
- str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu)));
+ if (head && location && menu == location)
+ jump->offset = r->len - 1;
+ str_printf(r, "%*c-> %s", j, ' ',
+ _(menu_get_prompt(menu)));
if (menu->sym) {
str_printf(r, " (%s [=%s])", menu->sym->name ?
menu->sym->name : _("<choice>"),
@@ -538,7 +570,10 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
}
}
-void get_symbol_str(struct gstr *r, struct symbol *sym)
+/*
+ * head is optional and may be NULL
+ */
+void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
{
bool hit;
struct property *prop;
@@ -557,7 +592,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
}
}
for_all_prompts(sym, prop)
- get_prompt_str(r, prop);
+ get_prompt_str(r, prop, head);
hit = false;
for_all_properties(sym, prop, P_SELECT) {
if (!hit) {
@@ -577,14 +612,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
str_append(r, "\n\n");
}
-struct gstr get_relations_str(struct symbol **sym_arr)
+struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
{
struct symbol *sym;
struct gstr res = str_new();
int i;
for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
- get_symbol_str(&res, sym);
+ get_symbol_str(&res, sym, head);
if (!i)
str_append(&res, _("No matches found.\n"));
return res;
@@ -603,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
}
str_printf(help, "%s\n", _(help_text));
if (sym)
- get_symbol_str(help, sym);
+ get_symbol_str(help, sym, NULL);
}
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 1704a8562a5..87d4b15da95 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -721,7 +721,7 @@ again:
dialog_input += strlen(CONFIG_);
sym_arr = sym_re_search(dialog_input);
- res = get_relations_str(sym_arr);
+ res = get_relations_str(sym_arr, NULL);
free(sym_arr);
show_scroll_win(main_window,
_("Search Results"), str_get(&res));
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 2fbbbc1ddea..33689396953 100644
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -100,7 +100,7 @@ my @searchconfigs = (
},
);
-sub find_config {
+sub read_config {
foreach my $conf (@searchconfigs) {
my $file = $conf->{"file"};
@@ -115,17 +115,15 @@ sub find_config {
print STDERR "using config: '$file'\n";
- open(CIN, "$exec $file |") || die "Failed to run $exec $file";
- return;
+ open(my $infile, '-|', "$exec $file") || die "Failed to run $exec $file";
+ my @x = <$infile>;
+ close $infile;
+ return @x;
}
die "No config file found";
}
-find_config;
-
-# Read in the entire config file into config_file
-my @config_file = <CIN>;
-close CIN;
+my @config_file = read_config;
# Parse options
my $localmodconfig = 0;
@@ -135,7 +133,7 @@ GetOptions("localmodconfig" => \$localmodconfig,
"localyesconfig" => \$localyesconfig);
# Get the build source and top level Kconfig file (passed in)
-my $ksource = $ARGV[0];
+my $ksource = ($ARGV[0] ? $ARGV[0] : '.');
my $kconfig = $ARGV[1];
my $lsmod_file = $ENV{'LSMOD'};
@@ -173,8 +171,8 @@ sub read_kconfig {
$source =~ s/\$$env/$ENV{$env}/;
}
- open(KIN, "$source") || die "Can't open $kconfig";
- while (<KIN>) {
+ open(my $kinfile, '<', $source) || die "Can't open $kconfig";
+ while (<$kinfile>) {
chomp;
# Make sure that lines ending with \ continue
@@ -251,10 +249,10 @@ sub read_kconfig {
$state = "NONE";
}
}
- close(KIN);
+ close($kinfile);
# read in any configs that were found.
- foreach $kconfig (@kconfigs) {
+ foreach my $kconfig (@kconfigs) {
if (!defined($read_kconfigs{$kconfig})) {
$read_kconfigs{$kconfig} = 1;
read_kconfig($kconfig);
@@ -295,8 +293,8 @@ foreach my $makefile (@makefiles) {
my $line = "";
my %make_vars;
- open(MIN,$makefile) || die "Can't open $makefile";
- while (<MIN>) {
+ open(my $infile, '<', $makefile) || die "Can't open $makefile";
+ while (<$infile>) {
# if this line ends with a backslash, continue
chomp;
if (/^(.*)\\$/) {
@@ -343,10 +341,11 @@ foreach my $makefile (@makefiles) {
}
}
}
- close(MIN);
+ close($infile);
}
my %modules;
+my $linfile;
if (defined($lsmod_file)) {
if ( ! -f $lsmod_file) {
@@ -356,13 +355,10 @@ if (defined($lsmod_file)) {
die "$lsmod_file not found";
}
}
- if ( -x $lsmod_file) {
- # the file is executable, run it
- open(LIN, "$lsmod_file|");
- } else {
- # Just read the contents
- open(LIN, "$lsmod_file");
- }
+
+ my $otype = ( -x $lsmod_file) ? '-|' : '<';
+ open($linfile, $otype, $lsmod_file);
+
} else {
# see what modules are loaded on this system
@@ -379,16 +375,16 @@ if (defined($lsmod_file)) {
$lsmod = "lsmod";
}
- open(LIN,"$lsmod|") || die "Can not call lsmod with $lsmod";
+ open($linfile, '-|', $lsmod) || die "Can not call lsmod with $lsmod";
}
-while (<LIN>) {
+while (<$linfile>) {
next if (/^Module/); # Skip the first line.
if (/^(\S+)/) {
$modules{$1} = 1;
}
}
-close (LIN);
+close ($linfile);
# add to the configs hash all configs that are needed to enable
# a loaded module. This is a direct obj-${CONFIG_FOO} += bar.o
@@ -605,6 +601,8 @@ foreach my $line (@config_file) {
if (defined($configs{$1})) {
if ($localyesconfig) {
$setconfigs{$1} = 'y';
+ print "$1=y\n";
+ next;
} else {
$setconfigs{$1} = $2;
}
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 8fd107a3fac..46e7aff80d1 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -6,6 +6,7 @@ use strict;
## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
## Copyright (C) 2001 Simon Huggins ##
## Copyright (C) 2005-2012 Randy Dunlap ##
+## Copyright (C) 2012 Dan Luedtke ##
## ##
## #define enhancements by Armin Kuster <akuster@mvista.com> ##
## Copyright (c) 2000 MontaVista Software, Inc. ##
@@ -35,6 +36,8 @@ use strict;
# Small fixes (like spaces vs. \s in regex)
# -- Tim Jansen <tim@tjansen.de>
+# 25/07/2012 - Added support for HTML5
+# -- Dan Luedtke <mail@danrl.de>
#
# This will read a 'c' file and scan for embedded comments in the
@@ -44,12 +47,16 @@ use strict;
# Note: This only supports 'c'.
# usage:
-# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
-# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
+# kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
+# [ -no-doc-sections ]
+# [ -function funcname [ -function funcname ...] ]
+# c file(s)s > outputfile
# or
-# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
+# [ -nofunction funcname [ -function funcname ...] ]
+# c file(s)s > outputfile
#
-# Set output format using one of -docbook -html -text or -man. Default is man.
+# Set output format using one of -docbook -html -html5 -text or -man.
+# Default is man.
# The -list format is for internal use by docproc.
#
# -no-doc-sections
@@ -182,6 +189,14 @@ my $local_lt = "\\\\\\\\lt:";
my $local_gt = "\\\\\\\\gt:";
my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
+# html version 5
+my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
+ $type_func, "<span class=\"func\">\$1</span>",
+ $type_struct_xml, "<span class=\"struct\">\$1</span>",
+ $type_env, "<span class=\"env\">\$1</span>",
+ $type_param, "<span class=\"param\">\$1</span>" );
+my $blankline_html5 = $local_lt . "br /" . $local_gt;
+
# XML, docbook format
my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
$type_constant, "<constant>\$1</constant>",
@@ -230,6 +245,7 @@ my $dohighlight = "";
my $verbose = 0;
my $output_mode = "man";
+my $output_preformatted = 0;
my $no_doc_sections = 0;
my %highlights = %highlights_man;
my $blankline = $blankline_man;
@@ -280,9 +296,10 @@ my $doc_special = "\@\%\$\&";
my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
my $doc_end = '\*/';
my $doc_com = '\s*\*\s*';
+my $doc_com_body = '\s*\* ?';
my $doc_decl = $doc_com . '(\w+)';
my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
-my $doc_content = $doc_com . '(.*)';
+my $doc_content = $doc_com_body . '(.*)';
my $doc_block = $doc_com . 'DOC:\s*(.*)?';
my %constants;
@@ -309,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
$output_mode = "html";
%highlights = %highlights_html;
$blankline = $blankline_html;
+ } elsif ($cmd eq "-html5") {
+ $output_mode = "html5";
+ %highlights = %highlights_html5;
+ $blankline = $blankline_html5;
} elsif ($cmd eq "-man") {
$output_mode = "man";
%highlights = %highlights_man;
@@ -351,10 +372,11 @@ while ($ARGV[0] =~ m/^-(.*)/) {
# continue execution near EOF;
sub usage {
- print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
+ print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
print " [ -no-doc-sections ]\n";
print " [ -function funcname [ -function funcname ...] ]\n";
print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
+ print " [ -v ]\n";
print " c source file(s) > outputfile\n";
print " -v : verbose output, more warnings & other info listed\n";
exit 1;
@@ -448,7 +470,8 @@ sub output_highlight {
# confess "output_highlight got called with no args?\n";
# }
- if ($output_mode eq "html" || $output_mode eq "xml") {
+ if ($output_mode eq "html" || $output_mode eq "html5" ||
+ $output_mode eq "xml") {
$contents = local_unescape($contents);
# convert data read & converted thru xml_escape() into &xyz; format:
$contents =~ s/\\\\\\/\&/g;
@@ -458,9 +481,19 @@ sub output_highlight {
die $@ if $@;
# print STDERR "contents af:$contents\n";
+# strip whitespaces when generating html5
+ if ($output_mode eq "html5") {
+ $contents =~ s/^\s+//;
+ $contents =~ s/\s+$//;
+ }
foreach $line (split "\n", $contents) {
+ if (! $output_preformatted) {
+ $line =~ s/^\s*//;
+ }
if ($line eq ""){
- print $lineprefix, local_unescape($blankline);
+ if (! $output_preformatted) {
+ print $lineprefix, local_unescape($blankline);
+ }
} else {
$line =~ s/\\\\\\/\&/g;
if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
@@ -473,7 +506,7 @@ sub output_highlight {
}
}
-#output sections in html
+# output sections in html
sub output_section_html(%) {
my %args = %{$_[0]};
my $section;
@@ -633,6 +666,239 @@ sub output_blockhead_html(%) {
print "<hr>\n";
}
+# output sections in html5
+sub output_section_html5(%) {
+ my %args = %{$_[0]};
+ my $section;
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ print "<section>\n";
+ print "<h1>$section</h1>\n";
+ print "<p>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</p>\n";
+ print "</section>\n";
+ }
+}
+
+# output enum in html5
+sub output_enum_html5(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ my $html5id;
+
+ $html5id = $args{'enum'};
+ $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+ print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
+ print "<h1>enum " . $args{'enum'} . "</h1>\n";
+ print "<ol class=\"code\">\n";
+ print "<li>";
+ print "<span class=\"keyword\">enum</span> ";
+ print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
+ print "</li>\n";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<li class=\"indent\">";
+ print "<span class=\"param\">" . $parameter . "</span>";
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",";
+ }
+ print "</li>\n";
+ }
+ print "<li>};</li>\n";
+ print "</ol>\n";
+
+ print "<section>\n";
+ print "<h1>Constants</h1>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<dt>" . $parameter . "</dt>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter});
+ print "</dd>\n";
+ }
+ print "</dl>\n";
+ print "</section>\n";
+ output_section_html5(@_);
+ print "</article>\n";
+}
+
+# output typedef in html5
+sub output_typedef_html5(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $count;
+ my $html5id;
+
+ $html5id = $args{'typedef'};
+ $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+ print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
+ print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
+
+ print "<ol class=\"code\">\n";
+ print "<li>";
+ print "<span class=\"keyword\">typedef</span> ";
+ print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
+ print "</li>\n";
+ print "</ol>\n";
+ output_section_html5(@_);
+ print "</article>\n";
+}
+
+# output struct in html5
+sub output_struct_html5(%) {
+ my %args = %{$_[0]};
+ my ($parameter);
+ my $html5id;
+
+ $html5id = $args{'struct'};
+ $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+ print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
+ print "<hgroup>\n";
+ print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
+ print "<h2>". $args{'purpose'} . "</h2>\n";
+ print "</hgroup>\n";
+ print "<ol class=\"code\">\n";
+ print "<li>";
+ print "<span class=\"type\">" . $args{'type'} . "</span> ";
+ print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
+ print "</li>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<li class=\"indent\">";
+ if ($parameter =~ /^#/) {
+ print "<span class=\"param\">" . $parameter ."</span>\n";
+ print "</li>\n";
+ next;
+ }
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print "<span class=\"type\">$1</span> ";
+ print "<span class=\"param\">$parameter</span>";
+ print "<span class=\"type\">)</span> ";
+ print "(<span class=\"args\">$2</span>);";
+ } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
+ # bitfield
+ print "<span class=\"type\">$1</span> ";
+ print "<span class=\"param\">$parameter</span>";
+ print "<span class=\"bits\">$2</span>;";
+ } else {
+ print "<span class=\"type\">$type</span> ";
+ print "<span class=\"param\">$parameter</span>;";
+ }
+ print "</li>\n";
+ }
+ print "<li>};</li>\n";
+ print "</ol>\n";
+
+ print "<section>\n";
+ print "<h1>Members</h1>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ ($parameter =~ /^#/) && next;
+
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ print "<dt>" . $parameter . "</dt>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
+ print "</dd>\n";
+ }
+ print "</dl>\n";
+ print "</section>\n";
+ output_section_html5(@_);
+ print "</article>\n";
+}
+
+# output function in html5
+sub output_function_html5(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $html5id;
+
+ $html5id = $args{'function'};
+ $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+ print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
+ print "<hgroup>\n";
+ print "<h1>" . $args{'function'} . "</h1>";
+ print "<h2>" . $args{'purpose'} . "</h2>\n";
+ print "</hgroup>\n";
+ print "<ol class=\"code\">\n";
+ print "<li>";
+ print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
+ print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
+ print "</li>";
+ $count = 0;
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ print "<li class=\"indent\">";
+ $type = $args{'parametertypes'}{$parameter};
+ if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
+ # pointer-to-function
+ print "<span class=\"type\">$1</span> ";
+ print "<span class=\"param\">$parameter</span>";
+ print "<span class=\"type\">)</span> ";
+ print "(<span class=\"args\">$2</span>)";
+ } else {
+ print "<span class=\"type\">$type</span> ";
+ print "<span class=\"param\">$parameter</span>";
+ }
+ if ($count != $#{$args{'parameterlist'}}) {
+ $count++;
+ print ",";
+ }
+ print "</li>\n";
+ }
+ print "<li>)</li>\n";
+ print "</ol>\n";
+
+ print "<section>\n";
+ print "<h1>Arguments</h1>\n";
+ print "<p>\n";
+ print "<dl>\n";
+ foreach $parameter (@{$args{'parameterlist'}}) {
+ my $parameter_name = $parameter;
+ $parameter_name =~ s/\[.*//;
+
+ ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
+ print "<dt>" . $parameter . "</dt>\n";
+ print "<dd>";
+ output_highlight($args{'parameterdescs'}{$parameter_name});
+ print "</dd>\n";
+ }
+ print "</dl>\n";
+ print "</section>\n";
+ output_section_html5(@_);
+ print "</article>\n";
+}
+
+# output DOC: block header in html5
+sub output_blockhead_html5(%) {
+ my %args = %{$_[0]};
+ my ($parameter, $section);
+ my $count;
+ my $html5id;
+
+ foreach $section (@{$args{'sectionlist'}}) {
+ $html5id = $section;
+ $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
+ print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
+ print "<h1>$section</h1>\n";
+ print "<p>\n";
+ output_highlight($args{'sections'}{$section});
+ print "</p>\n";
+ }
+ print "</article>\n";
+}
+
sub output_section_xml(%) {
my %args = %{$_[0]};
my $section;
@@ -643,10 +909,12 @@ sub output_section_xml(%) {
print "<title>$section</title>\n";
if ($section =~ m/EXAMPLE/i) {
print "<informalexample><programlisting>\n";
+ $output_preformatted = 1;
} else {
print "<para>\n";
}
output_highlight($args{'sections'}{$section});
+ $output_preformatted = 0;
if ($section =~ m/EXAMPLE/i) {
print "</programlisting></informalexample>\n";
} else {
@@ -949,10 +1217,12 @@ sub output_blockhead_xml(%) {
}
if ($section =~ m/EXAMPLE/i) {
print "<example><para>\n";
+ $output_preformatted = 1;
} else {
print "<para>\n";
}
output_highlight($args{'sections'}{$section});
+ $output_preformatted = 0;
if ($section =~ m/EXAMPLE/i) {
print "</para></example>\n";
} else {
@@ -1028,10 +1298,12 @@ sub output_function_gnome {
print "<simplesect>\n <title>$section</title>\n";
if ($section =~ m/EXAMPLE/i) {
print "<example><programlisting>\n";
+ $output_preformatted = 1;
} else {
}
print "<para>\n";
output_highlight($args{'sections'}{$section});
+ $output_preformatted = 0;
print "</para>\n";
if ($section =~ m/EXAMPLE/i) {
print "</programlisting></example>\n";
@@ -2046,6 +2318,9 @@ sub process_file($) {
$section_counter = 0;
while (<IN>) {
+ while (s/\\\s*$//) {
+ $_ .= <IN>;
+ }
if ($state == 0) {
if (/$doc_start/o) {
$state = 1; # next line is always the function name
@@ -2073,7 +2348,7 @@ sub process_file($) {
$descr= $1;
$descr =~ s/^\s*//;
$descr =~ s/\s*$//;
- $descr =~ s/\s+/ /;
+ $descr =~ s/\s+/ /g;
$declaration_purpose = xml_escape($descr);
$in_purpose = 1;
} else {
@@ -2165,6 +2440,7 @@ sub process_file($) {
# Continued declaration purpose
chomp($declaration_purpose);
$declaration_purpose .= " " . xml_escape($1);
+ $declaration_purpose =~ s/\s+/ /g;
} else {
$contents .= $1 . "\n";
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 7ed6864ef65..df4fc23dd83 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -966,6 +966,21 @@ static int do_isapnp_entry(const char *filename,
}
ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry);
+/* Looks like: "ipack:fNvNdN". */
+static int do_ipack_entry(const char *filename,
+ struct ipack_device_id *id, char *alias)
+{
+ id->vendor = TO_NATIVE(id->vendor);
+ id->device = TO_NATIVE(id->device);
+ strcpy(alias, "ipack:");
+ ADD(alias, "f", id->format != IPACK_ANY_FORMAT, id->format);
+ ADD(alias, "v", id->vendor != IPACK_ANY_ID, id->vendor);
+ ADD(alias, "d", id->device != IPACK_ANY_ID, id->device);
+ add_wildcard(alias);
+ return 1;
+}
+ADD_TO_DEVTABLE("ipack", struct ipack_device_id, do_ipack_entry);
+
/*
* Append a match expression for a single masked hex digit.
* outp points to a pointer to the character at which to append.
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 68e9f5ed0a6..0d93856a03f 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -821,12 +821,15 @@ static const char *section_white_list[] =
".debug*",
".zdebug*", /* Compressed debug sections. */
".GCC-command-line", /* mn10300 */
+ ".GCC.command.line", /* record-gcc-switches, non mn10300 */
".mdebug*", /* alpha, score, mips etc. */
".pdr", /* alpha, score, mips etc. */
".stab*",
".note*",
".got*",
".toc*",
+ ".xt.prop", /* xtensa */
+ ".xt.lit", /* xtensa */
NULL
};
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index 8a7b15598ea..62d8234f878 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -28,15 +28,15 @@ case "${1}" in
file_ext=""
;;
targz-pkg)
- compress="gzip -c9"
+ compress="gzip"
file_ext=".gz"
;;
tarbz2-pkg)
- compress="bzip2 -c9"
+ compress="bzip2"
file_ext=".bz2"
;;
tarxz-pkg)
- compress="xz -c9"
+ compress="xz"
file_ext=".xz"
;;
*)
@@ -109,7 +109,7 @@ esac
if tar --owner=root --group=root --help >/dev/null 2>&1; then
opts="--owner=root --group=root"
fi
- tar cf - . $opts | ${compress} > "${tarball}${file_ext}"
+ tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}"
)
echo "Tarball successfully created in ${tarball}${file_ext}"
diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h
index 54e35c1e594..9d1421e63ff 100644
--- a/scripts/recordmcount.h
+++ b/scripts/recordmcount.h
@@ -261,11 +261,13 @@ static unsigned get_mcountsym(Elf_Sym const *const sym0,
&sym0[Elf_r_sym(relp)];
char const *symname = &str0[w(symp->st_name)];
char const *mcount = gpfx == '_' ? "_mcount" : "mcount";
+ char const *fentry = "__fentry__";
if (symname[0] == '.')
++symname; /* ppc64 hack */
if (strcmp(mcount, symname) == 0 ||
- (altmcount && strcmp(altmcount, symname) == 0))
+ (altmcount && strcmp(altmcount, symname) == 0) ||
+ (strcmp(fentry, symname) == 0))
mcountsym = Elf_r_sym(relp);
return mcountsym;
diff --git a/scripts/sign-file b/scripts/sign-file
new file mode 100755
index 00000000000..87ca59d36e7
--- /dev/null
+++ b/scripts/sign-file
@@ -0,0 +1,429 @@
+#!/usr/bin/perl -w
+#
+# Sign a module file using the given key.
+#
+# Format:
+#
+# ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]
+#
+#
+use strict;
+use FileHandle;
+use IPC::Open2;
+
+my $verbose = 0;
+if ($#ARGV >= 0 && $ARGV[0] eq "-v") {
+ $verbose = 1;
+ shift;
+}
+
+die "Format: ./scripts/sign-file [-v] <key> <x509> <module> [<dest>]\n"
+ if ($#ARGV != 2 && $#ARGV != 3);
+
+my $private_key = $ARGV[0];
+my $x509 = $ARGV[1];
+my $module = $ARGV[2];
+my $dest = ($#ARGV == 3) ? $ARGV[3] : $ARGV[2] . "~";
+
+die "Can't read private key\n" unless (-r $private_key);
+die "Can't read X.509 certificate\n" unless (-r $x509);
+die "Can't read module\n" unless (-r $module);
+
+#
+# Read the kernel configuration
+#
+my %config = (
+ CONFIG_MODULE_SIG_SHA512 => 1
+ );
+
+if (-r ".config") {
+ open(FD, "<.config") || die ".config";
+ while (<FD>) {
+ if ($_ =~ /^(CONFIG_.*)=[ym]/) {
+ $config{$1} = 1;
+ }
+ }
+ close(FD);
+}
+
+#
+# Function to read the contents of a file into a variable.
+#
+sub read_file($)
+{
+ my ($file) = @_;
+ my $contents;
+ my $len;
+
+ open(FD, "<$file") || die $file;
+ binmode FD;
+ my @st = stat(FD);
+ die $file if (!@st);
+ $len = read(FD, $contents, $st[7]) || die $file;
+ close(FD) || die $file;
+ die "$file: Wanted length ", $st[7], ", got ", $len, "\n"
+ if ($len != $st[7]);
+ return $contents;
+}
+
+###############################################################################
+#
+# First of all, we have to parse the X.509 certificate to find certain details
+# about it.
+#
+# We read the DER-encoded X509 certificate and parse it to extract the Subject
+# name and Subject Key Identifier. Theis provides the data we need to build
+# the certificate identifier.
+#
+# The signer's name part of the identifier is fabricated from the commonName,
+# the organizationName or the emailAddress components of the X.509 subject
+# name.
+#
+# The subject key ID is used to select which of that signer's certificates
+# we're intending to use to sign the module.
+#
+###############################################################################
+my $x509_certificate = read_file($x509);
+
+my $UNIV = 0 << 6;
+my $APPL = 1 << 6;
+my $CONT = 2 << 6;
+my $PRIV = 3 << 6;
+
+my $CONS = 0x20;
+
+my $BOOLEAN = 0x01;
+my $INTEGER = 0x02;
+my $BIT_STRING = 0x03;
+my $OCTET_STRING = 0x04;
+my $NULL = 0x05;
+my $OBJ_ID = 0x06;
+my $UTF8String = 0x0c;
+my $SEQUENCE = 0x10;
+my $SET = 0x11;
+my $UTCTime = 0x17;
+my $GeneralizedTime = 0x18;
+
+my %OIDs = (
+ pack("CCC", 85, 4, 3) => "commonName",
+ pack("CCC", 85, 4, 6) => "countryName",
+ pack("CCC", 85, 4, 10) => "organizationName",
+ pack("CCC", 85, 4, 11) => "organizationUnitName",
+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
+ pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
+ pack("CCC", 85, 29, 35) => "authorityKeyIdentifier",
+ pack("CCC", 85, 29, 14) => "subjectKeyIdentifier",
+ pack("CCC", 85, 29, 19) => "basicConstraints"
+);
+
+###############################################################################
+#
+# Extract an ASN.1 element from a string and return information about it.
+#
+###############################################################################
+sub asn1_extract($$@)
+{
+ my ($cursor, $expected_tag, $optional) = @_;
+
+ return [ -1 ]
+ if ($cursor->[1] == 0 && $optional);
+
+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
+ if ($cursor->[1] < 2);
+
+ my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
+
+ if ($expected_tag != -1 && $tag != $expected_tag) {
+ return [ -1 ]
+ if ($optional);
+ die $x509, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
+ " not ", $expected_tag, ")\n";
+ }
+
+ $cursor->[0] += 2;
+ $cursor->[1] -= 2;
+
+ die $x509, ": ", $cursor->[0], ": ASN.1 long tag\n"
+ if (($tag & 0x1f) == 0x1f);
+ die $x509, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
+ if ($len == 0x80);
+
+ if ($len > 0x80) {
+ my $l = $len - 0x80;
+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
+ if ($cursor->[1] < $l);
+
+ if ($l == 0x1) {
+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
+ } elsif ($l = 0x2) {
+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
+ } elsif ($l = 0x3) {
+ $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
+ $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
+ } elsif ($l = 0x4) {
+ $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
+ } else {
+ die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
+ }
+
+ $cursor->[0] += $l;
+ $cursor->[1] -= $l;
+ }
+
+ die $x509, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
+ if ($cursor->[1] < $len);
+
+ my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
+ $cursor->[0] += $len;
+ $cursor->[1] -= $len;
+
+ return $ret;
+}
+
+###############################################################################
+#
+# Retrieve the data referred to by a cursor
+#
+###############################################################################
+sub asn1_retrieve($)
+{
+ my ($cursor) = @_;
+ my ($offset, $len, $data) = @$cursor;
+ return substr($$data, $offset, $len);
+}
+
+###############################################################################
+#
+# Roughly parse the X.509 certificate
+#
+###############################################################################
+my $cursor = [ 0, length($x509_certificate), \$x509_certificate ];
+
+my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
+my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
+my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
+my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
+my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
+my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
+my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
+my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
+
+my $subject_key_id = ();
+my $authority_key_id = ();
+
+#
+# Parse the extension list
+#
+if ($extension_list->[0] != -1) {
+ my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
+
+ while ($extensions->[1]->[1] > 0) {
+ my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
+ my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
+ my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
+ my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
+
+ my $raw_oid = asn1_retrieve($x_oid->[1]);
+ next if (!exists($OIDs{$raw_oid}));
+ my $x_type = $OIDs{$raw_oid};
+
+ my $raw_value = asn1_retrieve($x_val->[1]);
+
+ if ($x_type eq "subjectKeyIdentifier") {
+ my $vcursor = [ 0, length($raw_value), \$raw_value ];
+
+ $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
+ }
+ }
+}
+
+###############################################################################
+#
+# Determine what we're going to use as the signer's name. In order of
+# preference, take one of: commonName, organizationName or emailAddress.
+#
+###############################################################################
+my $org = "";
+my $cn = "";
+my $email = "";
+
+while ($subject->[1]->[1] > 0) {
+ my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
+ my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
+ my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
+ my $n_val = asn1_extract($attr->[1], -1);
+
+ my $raw_oid = asn1_retrieve($n_oid->[1]);
+ next if (!exists($OIDs{$raw_oid}));
+ my $n_type = $OIDs{$raw_oid};
+
+ my $raw_value = asn1_retrieve($n_val->[1]);
+
+ if ($n_type eq "organizationName") {
+ $org = $raw_value;
+ } elsif ($n_type eq "commonName") {
+ $cn = $raw_value;
+ } elsif ($n_type eq "emailAddress") {
+ $email = $raw_value;
+ }
+}
+
+my $signers_name = $email;
+
+if ($org && $cn) {
+ # Don't use the organizationName if the commonName repeats it
+ if (length($org) <= length($cn) &&
+ substr($cn, 0, length($org)) eq $org) {
+ $signers_name = $cn;
+ goto got_id_name;
+ }
+
+ # Or a signifcant chunk of it
+ if (length($org) >= 7 &&
+ length($cn) >= 7 &&
+ substr($cn, 0, 7) eq substr($org, 0, 7)) {
+ $signers_name = $cn;
+ goto got_id_name;
+ }
+
+ $signers_name = $org . ": " . $cn;
+} elsif ($org) {
+ $signers_name = $org;
+} elsif ($cn) {
+ $signers_name = $cn;
+}
+
+got_id_name:
+
+die $x509, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
+ if (!$subject_key_id);
+
+my $key_identifier = asn1_retrieve($subject_key_id->[1]);
+
+###############################################################################
+#
+# Create and attach the module signature
+#
+###############################################################################
+
+#
+# Signature parameters
+#
+my $algo = 1; # Public-key crypto algorithm: RSA
+my $hash = 0; # Digest algorithm
+my $id_type = 1; # Identifier type: X.509
+
+#
+# Digest the data
+#
+my ($dgst, $prologue) = ();
+if (exists $config{"CONFIG_MODULE_SIG_SHA1"}) {
+ $prologue = pack("C*",
+ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+ 0x2B, 0x0E, 0x03, 0x02, 0x1A,
+ 0x05, 0x00, 0x04, 0x14);
+ $dgst = "-sha1";
+ $hash = 2;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA224"}) {
+ $prologue = pack("C*",
+ 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+ 0x05, 0x00, 0x04, 0x1C);
+ $dgst = "-sha224";
+ $hash = 7;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA256"}) {
+ $prologue = pack("C*",
+ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+ 0x05, 0x00, 0x04, 0x20);
+ $dgst = "-sha256";
+ $hash = 4;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA384"}) {
+ $prologue = pack("C*",
+ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+ 0x05, 0x00, 0x04, 0x30);
+ $dgst = "-sha384";
+ $hash = 5;
+} elsif (exists $config{"CONFIG_MODULE_SIG_SHA512"}) {
+ $prologue = pack("C*",
+ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+ 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+ 0x05, 0x00, 0x04, 0x40);
+ $dgst = "-sha512";
+ $hash = 6;
+} else {
+ die "Can't determine hash algorithm";
+}
+
+#
+# Generate the digest and read from openssl's stdout
+#
+my $digest;
+$digest = readpipe("openssl dgst $dgst -binary $module") || die "openssl dgst";
+
+#
+# Generate the binary signature, which will be just the integer that comprises
+# the signature with no metadata attached.
+#
+my $pid;
+$pid = open2(*read_from, *write_to,
+ "openssl rsautl -sign -inkey $private_key -keyform PEM") ||
+ die "openssl rsautl";
+binmode write_to;
+print write_to $prologue . $digest || die "pipe to openssl rsautl";
+close(write_to) || die "pipe to openssl rsautl";
+
+binmode read_from;
+my $signature;
+read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
+close(read_from) || die "pipe from openssl rsautl";
+$signature = pack("n", length($signature)) . $signature,
+
+waitpid($pid, 0) || die;
+die "openssl rsautl died: $?" if ($? >> 8);
+
+#
+# Build the signed binary
+#
+my $unsigned_module = read_file($module);
+
+my $magic_number = "~Module signature appended~\n";
+
+my $info = pack("CCCCCxxxN",
+ $algo, $hash, $id_type,
+ length($signers_name),
+ length($key_identifier),
+ length($signature));
+
+if ($verbose) {
+ print "Size of unsigned module: ", length($unsigned_module), "\n";
+ print "Size of signer's name : ", length($signers_name), "\n";
+ print "Size of key identifier : ", length($key_identifier), "\n";
+ print "Size of signature : ", length($signature), "\n";
+ print "Size of informaton : ", length($info), "\n";
+ print "Size of magic number : ", length($magic_number), "\n";
+ print "Signer's name : '", $signers_name, "'\n";
+ print "Digest : $dgst\n";
+}
+
+open(FD, ">$dest") || die $dest;
+binmode FD;
+print FD
+ $unsigned_module,
+ $signers_name,
+ $key_identifier,
+ $signature,
+ $info,
+ $magic_number
+ ;
+close FD || die $dest;
+
+if ($#ARGV != 3) {
+ rename($dest, $module) || die $module;
+}
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index 6acf8344910..f19ddc47304 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -161,7 +161,7 @@ typedef void (*table_sort_t)(char *, int);
#define SORTEXTABLE_64
#include "sortextable.h"
-static int compare_x86_table(const void *a, const void *b)
+static int compare_relative_table(const void *a, const void *b)
{
int32_t av = (int32_t)r(a);
int32_t bv = (int32_t)r(b);
@@ -173,7 +173,7 @@ static int compare_x86_table(const void *a, const void *b)
return 0;
}
-static void sort_x86_table(char *extab_image, int image_size)
+static void sort_relative_table(char *extab_image, int image_size)
{
int i;
@@ -188,7 +188,7 @@ static void sort_x86_table(char *extab_image, int image_size)
i += 4;
}
- qsort(extab_image, image_size / 8, 8, compare_x86_table);
+ qsort(extab_image, image_size / 8, 8, compare_relative_table);
/* Now denormalize. */
i = 0;
@@ -245,9 +245,9 @@ do_file(char const *const fname)
break;
case EM_386:
case EM_X86_64:
- custom_sort = sort_x86_table;
- break;
case EM_S390:
+ custom_sort = sort_relative_table;
+ break;
case EM_MIPS:
break;
} /* end switch */
diff --git a/scripts/tags.sh b/scripts/tags.sh
index cff8faad73d..79fdafb0d26 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -154,7 +154,9 @@ exuberant()
--regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
--regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
--regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
- --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+ --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \
+ --regex-c='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
+ --regex-c='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
all_kconfigs | xargs $1 -a \
--langdef=kconfig --language-force=kconfig \
@@ -197,7 +199,9 @@ emacs()
--regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
--regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
--regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
- --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
+ --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \
+ --regex='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
+ --regex='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
all_kconfigs | xargs $1 -a \
--regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'