aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-15 01:41:27 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-10-15 01:41:27 -0400
commitc362495586e8a3a6487a318fcd82eaf15ffe2142 (patch)
tree86f7b195d36ba198f24f86be327f21a8d24ec248 /scripts
parentb70936d9ffbf0f45f4fa13a03122f015f13ecdb0 (diff)
parentddffeb8c4d0331609ef2581d84de4d763607bd37 (diff)
Merge 3.7-rc1 into tty-linus
This syncs up the tty-linus branch to the latest in Linus's tree to get all of the UAPI stuff needed for the next set of patches to merge. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
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.build11
-rw-r--r--scripts/Makefile.fwinst4
-rw-r--r--scripts/Makefile.modinst2
-rw-r--r--scripts/Makefile.modpost79
-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/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/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
-rwxr-xr-xscripts/kernel-doc296
-rw-r--r--scripts/mod/modpost.c3
-rw-r--r--scripts/package/buildtar8
-rw-r--r--scripts/sign-file115
-rwxr-xr-xscripts/tags.sh8
-rwxr-xr-xscripts/x509keyid268
33 files changed, 2749 insertions, 171 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 65f362d931b5..fb070fa1038f 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -10,3 +10,4 @@ ihex2fw
10recordmcount 10recordmcount
11docproc 11docproc
12sortextable 12sortextable
13asn1_compiler
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 6a3ee981931d..978416dd31ca 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -98,24 +98,24 @@ try-run = $(shell set -e; \
98# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) 98# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
99 99
100as-option = $(call try-run,\ 100as-option = $(call try-run,\
101 $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) 101 $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2))
102 102
103# as-instr 103# as-instr
104# Usage: cflags-y += $(call as-instr,instr,option1,option2) 104# Usage: cflags-y += $(call as-instr,instr,option1,option2)
105 105
106as-instr = $(call try-run,\ 106as-instr = $(call try-run,\
107 printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) 107 printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3))
108 108
109# cc-option 109# cc-option
110# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) 110# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
111 111
112cc-option = $(call try-run,\ 112cc-option = $(call try-run,\
113 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) 113 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
114 114
115# cc-option-yn 115# cc-option-yn
116# Usage: flag := $(call cc-option-yn,-march=winchip-c6) 116# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
117cc-option-yn = $(call try-run,\ 117cc-option-yn = $(call try-run,\
118 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) 118 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
119 119
120# cc-option-align 120# cc-option-align
121# Prefix align with either -falign or -malign 121# Prefix align with either -falign or -malign
@@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\
125# cc-disable-warning 125# cc-disable-warning
126# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) 126# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
127cc-disable-warning = $(call try-run,\ 127cc-disable-warning = $(call try-run,\
128 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) 128 $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
129 129
130# cc-version 130# cc-version
131# Usage gcc-ver := $(call cc-version) 131# Usage gcc-ver := $(call cc-version)
@@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
143# cc-ldoption 143# cc-ldoption
144# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) 144# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
145cc-ldoption = $(call try-run,\ 145cc-ldoption = $(call try-run,\
146 $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) 146 $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2))
147 147
148# ld-option 148# ld-option
149# Usage: LDFLAGS += $(call ld-option, -X) 149# Usage: LDFLAGS += $(call ld-option, -X)
@@ -209,7 +209,7 @@ endif
209# >$< substitution to preserve $ when reloading .cmd file 209# >$< substitution to preserve $ when reloading .cmd file
210# note: when using inline perl scripts [perl -e '...$$t=1;...'] 210# note: when using inline perl scripts [perl -e '...$$t=1;...']
211# in $(cmd_xxx) double $$ your perl vars 211# in $(cmd_xxx) double $$ your perl vars
212make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) 212make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))))
213 213
214# Find any prerequisites that is newer than target or that does not exist. 214# Find any prerequisites that is newer than target or that does not exist.
215# PHONY targets skipped in both cases. 215# PHONY targets skipped in both cases.
diff --git a/scripts/Makefile b/scripts/Makefile
index a55b0067758a..01e7adb838d9 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -16,8 +16,10 @@ hostprogs-$(CONFIG_VT) += conmakehash
16hostprogs-$(CONFIG_IKCONFIG) += bin2c 16hostprogs-$(CONFIG_IKCONFIG) += bin2c
17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
19hostprogs-$(CONFIG_ASN1) += asn1_compiler
19 20
20HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include 21HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
22HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
21 23
22always := $(hostprogs-y) $(hostprogs-m) 24always := $(hostprogs-y) $(hostprogs-m)
23 25
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index ff1720d28d0c..0e801c3cdaf8 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -354,6 +354,17 @@ quiet_cmd_cpp_lds_S = LDS $@
354$(obj)/%.lds: $(src)/%.lds.S FORCE 354$(obj)/%.lds: $(src)/%.lds.S FORCE
355 $(call if_changed_dep,cpp_lds_S) 355 $(call if_changed_dep,cpp_lds_S)
356 356
357# ASN.1 grammar
358# ---------------------------------------------------------------------------
359quiet_cmd_asn1_compiler = ASN.1 $@
360 cmd_asn1_compiler = $(objtree)/scripts/asn1_compiler $< \
361 $(subst .h,.c,$@) $(subst .c,.h,$@)
362
363.PRECIOUS: $(objtree)/$(obj)/%-asn1.c $(objtree)/$(obj)/%-asn1.h
364
365$(obj)/%-asn1.c $(obj)/%-asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler
366 $(call cmd,asn1_compiler)
367
357# Build the compiled-in targets 368# Build the compiled-in targets
358# --------------------------------------------------------------------------- 369# ---------------------------------------------------------------------------
359 370
diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst
index 4d908d16c035..c3f69ae275d1 100644
--- a/scripts/Makefile.fwinst
+++ b/scripts/Makefile.fwinst
@@ -27,7 +27,7 @@ endif
27installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw)) 27installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
28 28
29installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all)) 29installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
30installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./ 30installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
31 31
32# Workaround for make < 3.81, where .SECONDEXPANSION doesn't work. 32# Workaround for make < 3.81, where .SECONDEXPANSION doesn't work.
33PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs 33PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs
@@ -42,7 +42,7 @@ quiet_cmd_install = INSTALL $(subst $(srctree)/,,$@)
42$(installed-fw-dirs): 42$(installed-fw-dirs):
43 $(call cmd,mkdir) 43 $(call cmd,mkdir)
44 44
45$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $(INSTALL_FW_PATH)/$$(dir %) 45$(installed-fw): $(INSTALL_FW_PATH)/%: $(obj)/% | $$(dir $(INSTALL_FW_PATH)/%)
46 $(call cmd,install) 46 $(call cmd,install)
47 47
48PHONY += __fw_install __fw_modinst FORCE 48PHONY += __fw_install __fw_modinst FORCE
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index efa5d940e632..3d13d3a3edfe 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -9,7 +9,7 @@ include scripts/Kbuild.include
9 9
10# 10#
11 11
12__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) 12__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
13modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o))) 13modules := $(patsubst %.o,%.ko,$(wildcard $(__modules:.ko=.o)))
14 14
15PHONY += $(modules) 15PHONY += $(modules)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 08dce14f2dc8..002089141df4 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -14,7 +14,8 @@
14# 3) create one <module>.mod.c file pr. module 14# 3) create one <module>.mod.c file pr. module
15# 4) create one Module.symvers file with CRC for all exported symbols 15# 4) create one Module.symvers file with CRC for all exported symbols
16# 5) compile all <module>.mod.c files 16# 5) compile all <module>.mod.c files
17# 6) final link of the module to a <module.ko> file 17# 6) final link of the module to a <module.ko> (or <module.unsigned>) file
18# 7) signs the modules to a <module.ko> file
18 19
19# Step 3 is used to place certain information in the module's ELF 20# Step 3 is used to place certain information in the module's ELF
20# section, including information such as: 21# section, including information such as:
@@ -32,6 +33,8 @@
32# Step 4 is solely used to allow module versioning in external modules, 33# Step 4 is solely used to allow module versioning in external modules,
33# where the CRC of each module is retrieved from the Module.symvers file. 34# where the CRC of each module is retrieved from the Module.symvers file.
34 35
36# Step 7 is dependent on CONFIG_MODULE_SIG being enabled.
37
35# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined 38# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined
36# symbols in the final module linking stage 39# symbols in the final module linking stage
37# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules. 40# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
@@ -60,7 +63,7 @@ kernelsymfile := $(objtree)/Module.symvers
60modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers 63modulesymfile := $(firstword $(KBUILD_EXTMOD))/Module.symvers
61 64
62# Step 1), find all modules listed in $(MODVERDIR)/ 65# Step 1), find all modules listed in $(MODVERDIR)/
63__modules := $(sort $(shell grep -h '\.ko' /dev/null $(wildcard $(MODVERDIR)/*.mod))) 66__modules := $(sort $(shell grep -h '\.ko$$' /dev/null $(wildcard $(MODVERDIR)/*.mod)))
64modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o))) 67modules := $(patsubst %.o,%.ko, $(wildcard $(__modules:.ko=.o)))
65 68
66# Stop after building .o files if NOFINAL is set. Makes compile tests quicker 69# Stop after building .o files if NOFINAL is set. Makes compile tests quicker
@@ -116,6 +119,7 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE
116targets += $(modules:.ko=.mod.o) 119targets += $(modules:.ko=.mod.o)
117 120
118# Step 6), final link of the modules 121# Step 6), final link of the modules
122ifneq ($(CONFIG_MODULE_SIG),y)
119quiet_cmd_ld_ko_o = LD [M] $@ 123quiet_cmd_ld_ko_o = LD [M] $@
120 cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ 124 cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \
121 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ 125 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
@@ -125,7 +129,78 @@ $(modules): %.ko :%.o %.mod.o FORCE
125 $(call if_changed,ld_ko_o) 129 $(call if_changed,ld_ko_o)
126 130
127targets += $(modules) 131targets += $(modules)
132else
133quiet_cmd_ld_ko_unsigned_o = LD [M] $@
134 cmd_ld_ko_unsigned_o = \
135 $(LD) -r $(LDFLAGS) \
136 $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
137 -o $@ $(filter-out FORCE,$^) \
138 $(if $(AFTER_LINK),; $(AFTER_LINK))
139
140$(modules:.ko=.ko.unsigned): %.ko.unsigned :%.o %.mod.o FORCE
141 $(call if_changed,ld_ko_unsigned_o)
142
143targets += $(modules:.ko=.ko.unsigned)
144
145# Step 7), sign the modules
146MODSECKEY = ./signing_key.priv
147MODPUBKEY = ./signing_key.x509
148
149ifeq ($(wildcard $(MODSECKEY))+$(wildcard $(MODPUBKEY)),$(MODSECKEY)+$(MODPUBKEY))
150ifeq ($(KBUILD_SRC),)
151 # no O= is being used
152 SCRIPTS_DIR := scripts
153else
154 SCRIPTS_DIR := $(KBUILD_SRC)/scripts
155endif
156SIGN_MODULES := 1
157else
158SIGN_MODULES := 0
159endif
160
161# only sign if it's an in-tree module
162ifneq ($(KBUILD_EXTMOD),)
163SIGN_MODULES := 0
164endif
128 165
166# We strip the module as best we can - note that using both strip and eu-strip
167# results in a smaller module than using either alone.
168EU_STRIP = $(shell which eu-strip || echo true)
169
170quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@
171 cmd_sign_ko_stripped_ko_unsigned = \
172 cp $< $@ && \
173 strip -x -g $@ && \
174 $(EU_STRIP) $@
175
176ifeq ($(SIGN_MODULES),1)
177
178quiet_cmd_genkeyid = GENKEYID $@
179 cmd_genkeyid = \
180 perl $(SCRIPTS_DIR)/x509keyid $< $<.signer $<.keyid
181
182%.signer %.keyid: %
183 $(call if_changed,genkeyid)
184
185KEYRING_DEP := $(MODSECKEY) $(MODPUBKEY) $(MODPUBKEY).signer $(MODPUBKEY).keyid
186quiet_cmd_sign_ko_ko_stripped = SIGN [M] $@
187 cmd_sign_ko_ko_stripped = \
188 sh $(SCRIPTS_DIR)/sign-file $(MODSECKEY) $(MODPUBKEY) $< $@
189else
190KEYRING_DEP :=
191quiet_cmd_sign_ko_ko_unsigned = NO SIGN [M] $@
192 cmd_sign_ko_ko_unsigned = \
193 cp $< $@
194endif
195
196$(modules): %.ko :%.ko.stripped $(KEYRING_DEP) FORCE
197 $(call if_changed,sign_ko_ko_stripped)
198
199$(patsubst %.ko,%.ko.stripped,$(modules)): %.ko.stripped :%.ko.unsigned FORCE
200 $(call if_changed,sign_ko_stripped_ko_unsigned)
201
202targets += $(modules)
203endif
129 204
130# Add FORCE to the prequisites of a target to force it to be always rebuilt. 205# Add FORCE to the prequisites of a target to force it to be always rebuilt.
131# --------------------------------------------------------------------------- 206# ---------------------------------------------------------------------------
diff --git a/scripts/asn1_compiler.c b/scripts/asn1_compiler.c
new file mode 100644
index 000000000000..db0e5cd34c70
--- /dev/null
+++ b/scripts/asn1_compiler.c
@@ -0,0 +1,1545 @@
1/* Simplified ASN.1 notation parser
2 *
3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public Licence
8 * as published by the Free Software Foundation; either version
9 * 2 of the Licence, or (at your option) any later version.
10 */
11
12#include <stdarg.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <stdint.h>
16#include <string.h>
17#include <ctype.h>
18#include <unistd.h>
19#include <fcntl.h>
20#include <sys/stat.h>
21#include <linux/asn1_ber_bytecode.h>
22
23enum token_type {
24 DIRECTIVE_ABSENT,
25 DIRECTIVE_ALL,
26 DIRECTIVE_ANY,
27 DIRECTIVE_APPLICATION,
28 DIRECTIVE_AUTOMATIC,
29 DIRECTIVE_BEGIN,
30 DIRECTIVE_BIT,
31 DIRECTIVE_BMPString,
32 DIRECTIVE_BOOLEAN,
33 DIRECTIVE_BY,
34 DIRECTIVE_CHARACTER,
35 DIRECTIVE_CHOICE,
36 DIRECTIVE_CLASS,
37 DIRECTIVE_COMPONENT,
38 DIRECTIVE_COMPONENTS,
39 DIRECTIVE_CONSTRAINED,
40 DIRECTIVE_CONTAINING,
41 DIRECTIVE_DEFAULT,
42 DIRECTIVE_DEFINED,
43 DIRECTIVE_DEFINITIONS,
44 DIRECTIVE_EMBEDDED,
45 DIRECTIVE_ENCODED,
46 DIRECTIVE_ENCODING_CONTROL,
47 DIRECTIVE_END,
48 DIRECTIVE_ENUMERATED,
49 DIRECTIVE_EXCEPT,
50 DIRECTIVE_EXPLICIT,
51 DIRECTIVE_EXPORTS,
52 DIRECTIVE_EXTENSIBILITY,
53 DIRECTIVE_EXTERNAL,
54 DIRECTIVE_FALSE,
55 DIRECTIVE_FROM,
56 DIRECTIVE_GeneralString,
57 DIRECTIVE_GeneralizedTime,
58 DIRECTIVE_GraphicString,
59 DIRECTIVE_IA5String,
60 DIRECTIVE_IDENTIFIER,
61 DIRECTIVE_IMPLICIT,
62 DIRECTIVE_IMPLIED,
63 DIRECTIVE_IMPORTS,
64 DIRECTIVE_INCLUDES,
65 DIRECTIVE_INSTANCE,
66 DIRECTIVE_INSTRUCTIONS,
67 DIRECTIVE_INTEGER,
68 DIRECTIVE_INTERSECTION,
69 DIRECTIVE_ISO646String,
70 DIRECTIVE_MAX,
71 DIRECTIVE_MIN,
72 DIRECTIVE_MINUS_INFINITY,
73 DIRECTIVE_NULL,
74 DIRECTIVE_NumericString,
75 DIRECTIVE_OBJECT,
76 DIRECTIVE_OCTET,
77 DIRECTIVE_OF,
78 DIRECTIVE_OPTIONAL,
79 DIRECTIVE_ObjectDescriptor,
80 DIRECTIVE_PATTERN,
81 DIRECTIVE_PDV,
82 DIRECTIVE_PLUS_INFINITY,
83 DIRECTIVE_PRESENT,
84 DIRECTIVE_PRIVATE,
85 DIRECTIVE_PrintableString,
86 DIRECTIVE_REAL,
87 DIRECTIVE_RELATIVE_OID,
88 DIRECTIVE_SEQUENCE,
89 DIRECTIVE_SET,
90 DIRECTIVE_SIZE,
91 DIRECTIVE_STRING,
92 DIRECTIVE_SYNTAX,
93 DIRECTIVE_T61String,
94 DIRECTIVE_TAGS,
95 DIRECTIVE_TRUE,
96 DIRECTIVE_TeletexString,
97 DIRECTIVE_UNION,
98 DIRECTIVE_UNIQUE,
99 DIRECTIVE_UNIVERSAL,
100 DIRECTIVE_UTCTime,
101 DIRECTIVE_UTF8String,
102 DIRECTIVE_UniversalString,
103 DIRECTIVE_VideotexString,
104 DIRECTIVE_VisibleString,
105 DIRECTIVE_WITH,
106 NR__DIRECTIVES,
107 TOKEN_ASSIGNMENT = NR__DIRECTIVES,
108 TOKEN_OPEN_CURLY,
109 TOKEN_CLOSE_CURLY,
110 TOKEN_OPEN_SQUARE,
111 TOKEN_CLOSE_SQUARE,
112 TOKEN_OPEN_ACTION,
113 TOKEN_CLOSE_ACTION,
114 TOKEN_COMMA,
115 TOKEN_NUMBER,
116 TOKEN_TYPE_NAME,
117 TOKEN_ELEMENT_NAME,
118 NR__TOKENS
119};
120
121static const unsigned char token_to_tag[NR__TOKENS] = {
122 /* EOC goes first */
123 [DIRECTIVE_BOOLEAN] = ASN1_BOOL,
124 [DIRECTIVE_INTEGER] = ASN1_INT,
125 [DIRECTIVE_BIT] = ASN1_BTS,
126 [DIRECTIVE_OCTET] = ASN1_OTS,
127 [DIRECTIVE_NULL] = ASN1_NULL,
128 [DIRECTIVE_OBJECT] = ASN1_OID,
129 [DIRECTIVE_ObjectDescriptor] = ASN1_ODE,
130 [DIRECTIVE_EXTERNAL] = ASN1_EXT,
131 [DIRECTIVE_REAL] = ASN1_REAL,
132 [DIRECTIVE_ENUMERATED] = ASN1_ENUM,
133 [DIRECTIVE_EMBEDDED] = 0,
134 [DIRECTIVE_UTF8String] = ASN1_UTF8STR,
135 [DIRECTIVE_RELATIVE_OID] = ASN1_RELOID,
136 /* 14 */
137 /* 15 */
138 [DIRECTIVE_SEQUENCE] = ASN1_SEQ,
139 [DIRECTIVE_SET] = ASN1_SET,
140 [DIRECTIVE_NumericString] = ASN1_NUMSTR,
141 [DIRECTIVE_PrintableString] = ASN1_PRNSTR,
142 [DIRECTIVE_T61String] = ASN1_TEXSTR,
143 [DIRECTIVE_TeletexString] = ASN1_TEXSTR,
144 [DIRECTIVE_VideotexString] = ASN1_VIDSTR,
145 [DIRECTIVE_IA5String] = ASN1_IA5STR,
146 [DIRECTIVE_UTCTime] = ASN1_UNITIM,
147 [DIRECTIVE_GeneralizedTime] = ASN1_GENTIM,
148 [DIRECTIVE_GraphicString] = ASN1_GRASTR,
149 [DIRECTIVE_VisibleString] = ASN1_VISSTR,
150 [DIRECTIVE_GeneralString] = ASN1_GENSTR,
151 [DIRECTIVE_UniversalString] = ASN1_UNITIM,
152 [DIRECTIVE_CHARACTER] = ASN1_CHRSTR,
153 [DIRECTIVE_BMPString] = ASN1_BMPSTR,
154};
155
156static const char asn1_classes[4][5] = {
157 [ASN1_UNIV] = "UNIV",
158 [ASN1_APPL] = "APPL",
159 [ASN1_CONT] = "CONT",
160 [ASN1_PRIV] = "PRIV"
161};
162
163static const char asn1_methods[2][5] = {
164 [ASN1_UNIV] = "PRIM",
165 [ASN1_APPL] = "CONS"
166};
167
168static const char *const asn1_universal_tags[32] = {
169 "EOC",
170 "BOOL",
171 "INT",
172 "BTS",
173 "OTS",
174 "NULL",
175 "OID",
176 "ODE",
177 "EXT",
178 "REAL",
179 "ENUM",
180 "EPDV",
181 "UTF8STR",
182 "RELOID",
183 NULL, /* 14 */
184 NULL, /* 15 */
185 "SEQ",
186 "SET",
187 "NUMSTR",
188 "PRNSTR",
189 "TEXSTR",
190 "VIDSTR",
191 "IA5STR",
192 "UNITIM",
193 "GENTIM",
194 "GRASTR",
195 "VISSTR",
196 "GENSTR",
197 "UNISTR",
198 "CHRSTR",
199 "BMPSTR",
200 NULL /* 31 */
201};
202
203static const char *filename;
204static const char *grammar_name;
205static const char *outputname;
206static const char *headername;
207
208static const char *const directives[NR__DIRECTIVES] = {
209#define _(X) [DIRECTIVE_##X] = #X
210 _(ABSENT),
211 _(ALL),
212 _(ANY),
213 _(APPLICATION),
214 _(AUTOMATIC),
215 _(BEGIN),
216 _(BIT),
217 _(BMPString),
218 _(BOOLEAN),
219 _(BY),
220 _(CHARACTER),
221 _(CHOICE),
222 _(CLASS),
223 _(COMPONENT),
224 _(COMPONENTS),
225 _(CONSTRAINED),
226 _(CONTAINING),
227 _(DEFAULT),
228 _(DEFINED),
229 _(DEFINITIONS),
230 _(EMBEDDED),
231 _(ENCODED),
232 [DIRECTIVE_ENCODING_CONTROL] = "ENCODING-CONTROL",
233 _(END),
234 _(ENUMERATED),
235 _(EXCEPT),
236 _(EXPLICIT),
237 _(EXPORTS),
238 _(EXTENSIBILITY),
239 _(EXTERNAL),
240 _(FALSE),
241 _(FROM),
242 _(GeneralString),
243 _(GeneralizedTime),
244 _(GraphicString),
245 _(IA5String),
246 _(IDENTIFIER),
247 _(IMPLICIT),
248 _(IMPLIED),
249 _(IMPORTS),
250 _(INCLUDES),
251 _(INSTANCE),
252 _(INSTRUCTIONS),
253 _(INTEGER),
254 _(INTERSECTION),
255 _(ISO646String),
256 _(MAX),
257 _(MIN),
258 [DIRECTIVE_MINUS_INFINITY] = "MINUS-INFINITY",
259 [DIRECTIVE_NULL] = "NULL",
260 _(NumericString),
261 _(OBJECT),
262 _(OCTET),
263 _(OF),
264 _(OPTIONAL),
265 _(ObjectDescriptor),
266 _(PATTERN),
267 _(PDV),
268 [DIRECTIVE_PLUS_INFINITY] = "PLUS-INFINITY",
269 _(PRESENT),
270 _(PRIVATE),
271 _(PrintableString),
272 _(REAL),
273 [DIRECTIVE_RELATIVE_OID] = "RELATIVE-OID",
274 _(SEQUENCE),
275 _(SET),
276 _(SIZE),
277 _(STRING),
278 _(SYNTAX),
279 _(T61String),
280 _(TAGS),
281 _(TRUE),
282 _(TeletexString),
283 _(UNION),
284 _(UNIQUE),
285 _(UNIVERSAL),
286 _(UTCTime),
287 _(UTF8String),
288 _(UniversalString),
289 _(VideotexString),
290 _(VisibleString),
291 _(WITH)
292};
293
294struct action {
295 struct action *next;
296 unsigned char index;
297 char name[];
298};
299
300static struct action *action_list;
301static unsigned nr_actions;
302
303struct token {
304 unsigned short line;
305 enum token_type token_type : 8;
306 unsigned char size;
307 struct action *action;
308 const char *value;
309 struct type *type;
310};
311
312static struct token *token_list;
313static unsigned nr_tokens;
314
315static int directive_compare(const void *_key, const void *_pdir)
316{
317 const struct token *token = _key;
318 const char *const *pdir = _pdir, *dir = *pdir;
319 size_t dlen, clen;
320 int val;
321
322 dlen = strlen(dir);
323 clen = (dlen < token->size) ? dlen : token->size;
324
325 //printf("cmp(%*.*s,%s) = ",
326 // (int)token->size, (int)token->size, token->value,
327 // dir);
328
329 val = memcmp(token->value, dir, clen);
330 if (val != 0) {
331 //printf("%d [cmp]\n", val);
332 return val;
333 }
334
335 if (dlen == token->size) {
336 //printf("0\n");
337 return 0;
338 }
339 //printf("%d\n", (int)dlen - (int)token->size);
340 return dlen - token->size; /* shorter -> negative */
341}
342
343/*
344 * Tokenise an ASN.1 grammar
345 */
346static void tokenise(char *buffer, char *end)
347{
348 struct token *tokens;
349 char *line, *nl, *p, *q;
350 unsigned tix, lineno;
351
352 /* Assume we're going to have half as many tokens as we have
353 * characters
354 */
355 token_list = tokens = calloc((end - buffer) / 2, sizeof(struct token));
356 if (!tokens) {
357 perror(NULL);
358 exit(1);
359 }
360 tix = 0;
361
362 lineno = 0;
363 while (buffer < end) {
364 /* First of all, break out a line */
365 lineno++;
366 line = buffer;
367 nl = memchr(line, '\n', end - buffer);
368 if (!nl) {
369 buffer = nl = end;
370 } else {
371 buffer = nl + 1;
372 *nl = '\0';
373 }
374
375 /* Remove "--" comments */
376 p = line;
377 next_comment:
378 while ((p = memchr(p, '-', nl - p))) {
379 if (p[1] == '-') {
380 /* Found a comment; see if there's a terminator */
381 q = p + 2;
382 while ((q = memchr(q, '-', nl - q))) {
383 if (q[1] == '-') {
384 /* There is - excise the comment */
385 q += 2;
386 memmove(p, q, nl - q);
387 goto next_comment;
388 }
389 q++;
390 }
391 *p = '\0';
392 nl = p;
393 break;
394 } else {
395 p++;
396 }
397 }
398
399 p = line;
400 while (p < nl) {
401 /* Skip white space */
402 while (p < nl && isspace(*p))
403 *(p++) = 0;
404 if (p >= nl)
405 break;
406
407 tokens[tix].line = lineno;
408 tokens[tix].value = p;
409
410 /* Handle string tokens */
411 if (isalpha(*p)) {
412 const char **dir;
413
414 /* Can be a directive, type name or element
415 * name. Find the end of the name.
416 */
417 q = p + 1;
418 while (q < nl && (isalnum(*q) || *q == '-' || *q == '_'))
419 q++;
420 tokens[tix].size = q - p;
421 p = q;
422
423 /* If it begins with a lowercase letter then
424 * it's an element name
425 */
426 if (islower(tokens[tix].value[0])) {
427 tokens[tix++].token_type = TOKEN_ELEMENT_NAME;
428 continue;
429 }
430
431 /* Otherwise we need to search the directive
432 * table
433 */
434 dir = bsearch(&tokens[tix], directives,
435 sizeof(directives) / sizeof(directives[1]),
436 sizeof(directives[1]),
437 directive_compare);
438 if (dir) {
439 tokens[tix++].token_type = dir - directives;
440 continue;
441 }
442
443 tokens[tix++].token_type = TOKEN_TYPE_NAME;
444 continue;
445 }
446
447 /* Handle numbers */
448 if (isdigit(*p)) {
449 /* Find the end of the number */
450 q = p + 1;
451 while (q < nl && (isdigit(*q)))
452 q++;
453 tokens[tix].size = q - p;
454 p = q;
455 tokens[tix++].token_type = TOKEN_NUMBER;
456 continue;
457 }
458
459 if (nl - p >= 3) {
460 if (memcmp(p, "::=", 3) == 0) {
461 p += 3;
462 tokens[tix].size = 3;
463 tokens[tix++].token_type = TOKEN_ASSIGNMENT;
464 continue;
465 }
466 }
467
468 if (nl - p >= 2) {
469 if (memcmp(p, "({", 2) == 0) {
470 p += 2;
471 tokens[tix].size = 2;
472 tokens[tix++].token_type = TOKEN_OPEN_ACTION;
473 continue;
474 }
475 if (memcmp(p, "})", 2) == 0) {
476 p += 2;
477 tokens[tix].size = 2;
478 tokens[tix++].token_type = TOKEN_CLOSE_ACTION;
479 continue;
480 }
481 }
482
483 if (nl - p >= 1) {
484 tokens[tix].size = 1;
485 switch (*p) {
486 case '{':
487 p += 1;
488 tokens[tix++].token_type = TOKEN_OPEN_CURLY;
489 continue;
490 case '}':
491 p += 1;
492 tokens[tix++].token_type = TOKEN_CLOSE_CURLY;
493 continue;
494 case '[':
495 p += 1;
496 tokens[tix++].token_type = TOKEN_OPEN_SQUARE;
497 continue;
498 case ']':
499 p += 1;
500 tokens[tix++].token_type = TOKEN_CLOSE_SQUARE;
501 continue;
502 case ',':
503 p += 1;
504 tokens[tix++].token_type = TOKEN_COMMA;
505 continue;
506 default:
507 break;
508 }
509 }
510
511 fprintf(stderr, "%s:%u: Unknown character in grammar: '%c'\n",
512 filename, lineno, *p);
513 exit(1);
514 }
515 }
516
517 nr_tokens = tix;
518 printf("Extracted %u tokens\n", nr_tokens);
519
520#if 0
521 {
522 int n;
523 for (n = 0; n < nr_tokens; n++)
524 printf("Token %3u: '%*.*s'\n",
525 n,
526 (int)token_list[n].size, (int)token_list[n].size,
527 token_list[n].value);
528 }
529#endif
530}
531
532static void build_type_list(void);
533static void parse(void);
534static void render(FILE *out, FILE *hdr);
535
536/*
537 *
538 */
539int main(int argc, char **argv)
540{
541 struct stat st;
542 ssize_t readlen;
543 FILE *out, *hdr;
544 char *buffer, *p;
545 int fd;
546
547 if (argc != 4) {
548 fprintf(stderr, "Format: %s <grammar-file> <c-file> <hdr-file>\n",
549 argv[0]);
550 exit(2);
551 }
552
553 filename = argv[1];
554 outputname = argv[2];
555 headername = argv[3];
556
557 fd = open(filename, O_RDONLY);
558 if (fd < 0) {
559 perror(filename);
560 exit(1);
561 }
562
563 if (fstat(fd, &st) < 0) {
564 perror(filename);
565 exit(1);
566 }
567
568 if (!(buffer = malloc(st.st_size + 1))) {
569 perror(NULL);
570 exit(1);
571 }
572
573 if ((readlen = read(fd, buffer, st.st_size)) < 0) {
574 perror(filename);
575 exit(1);
576 }
577
578 if (close(fd) < 0) {
579 perror(filename);
580 exit(1);
581 }
582
583 if (readlen != st.st_size) {
584 fprintf(stderr, "%s: Short read\n", filename);
585 exit(1);
586 }
587
588 p = strrchr(argv[1], '/');
589 p = p ? p + 1 : argv[1];
590 grammar_name = strdup(p);
591 if (!p) {
592 perror(NULL);
593 exit(1);
594 }
595 p = strchr(grammar_name, '.');
596 if (p)
597 *p = '\0';
598
599 buffer[readlen] = 0;
600 tokenise(buffer, buffer + readlen);
601 build_type_list();
602 parse();
603
604 out = fopen(outputname, "w");
605 if (!out) {
606 perror(outputname);
607 exit(1);
608 }
609
610 hdr = fopen(headername, "w");
611 if (!out) {
612 perror(headername);
613 exit(1);
614 }
615
616 render(out, hdr);
617
618 if (fclose(out) < 0) {
619 perror(outputname);
620 exit(1);
621 }
622
623 if (fclose(hdr) < 0) {
624 perror(headername);
625 exit(1);
626 }
627
628 return 0;
629}
630
631enum compound {
632 NOT_COMPOUND,
633 SET,
634 SET_OF,
635 SEQUENCE,
636 SEQUENCE_OF,
637 CHOICE,
638 ANY,
639 TYPE_REF,
640 TAG_OVERRIDE
641};
642
643struct element {
644 struct type *type_def;
645 struct token *name;
646 struct token *type;
647 struct action *action;
648 struct element *children;
649 struct element *next;
650 struct element *render_next;
651 struct element *list_next;
652 uint8_t n_elements;
653 enum compound compound : 8;
654 enum asn1_class class : 8;
655 enum asn1_method method : 8;
656 uint8_t tag;
657 unsigned entry_index;
658 unsigned flags;
659#define ELEMENT_IMPLICIT 0x0001
660#define ELEMENT_EXPLICIT 0x0002
661#define ELEMENT_MARKED 0x0004
662#define ELEMENT_RENDERED 0x0008
663#define ELEMENT_SKIPPABLE 0x0010
664#define ELEMENT_CONDITIONAL 0x0020
665};
666
667struct type {
668 struct token *name;
669 struct token *def;
670 struct element *element;
671 unsigned ref_count;
672 unsigned flags;
673#define TYPE_STOP_MARKER 0x0001
674#define TYPE_BEGIN 0x0002
675};
676
677static struct type *type_list;
678static struct type **type_index;
679static unsigned nr_types;
680
681static int type_index_compare(const void *_a, const void *_b)
682{
683 const struct type *const *a = _a, *const *b = _b;
684
685 if ((*a)->name->size != (*b)->name->size)
686 return (*a)->name->size - (*b)->name->size;
687 else
688 return memcmp((*a)->name->value, (*b)->name->value,
689 (*a)->name->size);
690}
691
692static int type_finder(const void *_key, const void *_ti)
693{
694 const struct token *token = _key;
695 const struct type *const *ti = _ti;
696 const struct type *type = *ti;
697
698 if (token->size != type->name->size)
699 return token->size - type->name->size;
700 else
701 return memcmp(token->value, type->name->value,
702 token->size);
703}
704
705/*
706 * Build up a list of types and a sorted index to that list.
707 */
708static void build_type_list(void)
709{
710 struct type *types;
711 unsigned nr, t, n;
712
713 nr = 0;
714 for (n = 0; n < nr_tokens - 1; n++)
715 if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
716 token_list[n + 1].token_type == TOKEN_ASSIGNMENT)
717 nr++;
718
719 if (nr == 0) {
720 fprintf(stderr, "%s: No defined types\n", filename);
721 exit(1);
722 }
723
724 nr_types = nr;
725 types = type_list = calloc(nr + 1, sizeof(type_list[0]));
726 if (!type_list) {
727 perror(NULL);
728 exit(1);
729 }
730 type_index = calloc(nr, sizeof(type_index[0]));
731 if (!type_index) {
732 perror(NULL);
733 exit(1);
734 }
735
736 t = 0;
737 types[t].flags |= TYPE_BEGIN;
738 for (n = 0; n < nr_tokens - 1; n++) {
739 if (token_list[n + 0].token_type == TOKEN_TYPE_NAME &&
740 token_list[n + 1].token_type == TOKEN_ASSIGNMENT) {
741 types[t].name = &token_list[n];
742 type_index[t] = &types[t];
743 t++;
744 }
745 }
746 types[t].name = &token_list[n + 1];
747 types[t].flags |= TYPE_STOP_MARKER;
748
749 qsort(type_index, nr, sizeof(type_index[0]), type_index_compare);
750
751 printf("Extracted %u types\n", nr_types);
752#if 0
753 for (n = 0; n < nr_types; n++) {
754 struct type *type = type_index[n];
755 printf("- %*.*s\n",
756 (int)type->name->size,
757 (int)type->name->size,
758 type->name->value);
759 }
760#endif
761}
762
763static struct element *parse_type(struct token **_cursor, struct token *stop,
764 struct token *name);
765
766/*
767 * Parse the token stream
768 */
769static void parse(void)
770{
771 struct token *cursor;
772 struct type *type;
773
774 /* Parse one type definition statement at a time */
775 type = type_list;
776 do {
777 cursor = type->name;
778
779 if (cursor[0].token_type != TOKEN_TYPE_NAME ||
780 cursor[1].token_type != TOKEN_ASSIGNMENT)
781 abort();
782 cursor += 2;
783
784 type->element = parse_type(&cursor, type[1].name, NULL);
785 type->element->type_def = type;
786
787 if (cursor != type[1].name) {
788 fprintf(stderr, "%s:%d: Parse error at token '%*.*s'\n",
789 filename, cursor->line,
790 (int)cursor->size, (int)cursor->size, cursor->value);
791 exit(1);
792 }
793
794 } while (type++, !(type->flags & TYPE_STOP_MARKER));
795
796 printf("Extracted %u actions\n", nr_actions);
797}
798
799static struct element *element_list;
800
801static struct element *alloc_elem(struct token *type)
802{
803 struct element *e = calloc(1, sizeof(*e));
804 if (!e) {
805 perror(NULL);
806 exit(1);
807 }
808 e->list_next = element_list;
809 element_list = e;
810 return e;
811}
812
813static struct element *parse_compound(struct token **_cursor, struct token *end,
814 int alternates);
815
816/*
817 * Parse one type definition statement
818 */
819static struct element *parse_type(struct token **_cursor, struct token *end,
820 struct token *name)
821{
822 struct element *top, *element;
823 struct action *action, **ppaction;
824 struct token *cursor = *_cursor;
825 struct type **ref;
826 char *p;
827 int labelled = 0, implicit = 0;
828
829 top = element = alloc_elem(cursor);
830 element->class = ASN1_UNIV;
831 element->method = ASN1_PRIM;
832 element->tag = token_to_tag[cursor->token_type];
833 element->name = name;
834
835 /* Extract the tag value if one given */
836 if (cursor->token_type == TOKEN_OPEN_SQUARE) {
837 cursor++;
838 if (cursor >= end)
839 goto overrun_error;
840 switch (cursor->token_type) {
841 case DIRECTIVE_UNIVERSAL:
842 element->class = ASN1_UNIV;
843 cursor++;
844 break;
845 case DIRECTIVE_APPLICATION:
846 element->class = ASN1_APPL;
847 cursor++;
848 break;
849 case TOKEN_NUMBER:
850 element->class = ASN1_CONT;
851 break;
852 case DIRECTIVE_PRIVATE:
853 element->class = ASN1_PRIV;
854 cursor++;
855 break;
856 default:
857 fprintf(stderr, "%s:%d: Unrecognised tag class token '%*.*s'\n",
858 filename, cursor->line,
859 (int)cursor->size, (int)cursor->size, cursor->value);
860 exit(1);
861 }
862
863 if (cursor >= end)
864 goto overrun_error;
865 if (cursor->token_type != TOKEN_NUMBER) {
866 fprintf(stderr, "%s:%d: Missing tag number '%*.*s'\n",
867 filename, cursor->line,
868 (int)cursor->size, (int)cursor->size, cursor->value);
869 exit(1);
870 }
871
872 element->tag &= ~0x1f;
873 element->tag |= strtoul(cursor->value, &p, 10);
874 if (p - cursor->value != cursor->size)
875 abort();
876 cursor++;
877
878 if (cursor >= end)
879 goto overrun_error;
880 if (cursor->token_type != TOKEN_CLOSE_SQUARE) {
881 fprintf(stderr, "%s:%d: Missing closing square bracket '%*.*s'\n",
882 filename, cursor->line,
883 (int)cursor->size, (int)cursor->size, cursor->value);
884 exit(1);
885 }
886 cursor++;
887 if (cursor >= end)
888 goto overrun_error;
889 labelled = 1;
890 }
891
892 /* Handle implicit and explicit markers */
893 if (cursor->token_type == DIRECTIVE_IMPLICIT) {
894 element->flags |= ELEMENT_IMPLICIT;
895 implicit = 1;
896 cursor++;
897 if (cursor >= end)
898 goto overrun_error;
899 } else if (cursor->token_type == DIRECTIVE_EXPLICIT) {
900 element->flags |= ELEMENT_EXPLICIT;
901 cursor++;
902 if (cursor >= end)
903 goto overrun_error;
904 }
905
906 if (labelled) {
907 if (!implicit)
908 element->method |= ASN1_CONS;
909 element->compound = implicit ? TAG_OVERRIDE : SEQUENCE;
910 element->children = alloc_elem(cursor);
911 element = element->children;
912 element->class = ASN1_UNIV;
913 element->method = ASN1_PRIM;
914 element->tag = token_to_tag[cursor->token_type];
915 element->name = name;
916 }
917
918 /* Extract the type we're expecting here */
919 element->type = cursor;
920 switch (cursor->token_type) {
921 case DIRECTIVE_ANY:
922 element->compound = ANY;
923 cursor++;
924 break;
925
926 case DIRECTIVE_NULL:
927 case DIRECTIVE_BOOLEAN:
928 case DIRECTIVE_ENUMERATED:
929 case DIRECTIVE_INTEGER:
930 element->compound = NOT_COMPOUND;
931 cursor++;
932 break;
933
934 case DIRECTIVE_EXTERNAL:
935 element->method = ASN1_CONS;
936
937 case DIRECTIVE_BMPString:
938 case DIRECTIVE_GeneralString:
939 case DIRECTIVE_GraphicString:
940 case DIRECTIVE_IA5String:
941 case DIRECTIVE_ISO646String:
942 case DIRECTIVE_NumericString:
943 case DIRECTIVE_PrintableString:
944 case DIRECTIVE_T61String:
945 case DIRECTIVE_TeletexString:
946 case DIRECTIVE_UniversalString:
947 case DIRECTIVE_UTF8String:
948 case DIRECTIVE_VideotexString:
949 case DIRECTIVE_VisibleString:
950 case DIRECTIVE_ObjectDescriptor:
951 case DIRECTIVE_GeneralizedTime:
952 case DIRECTIVE_UTCTime:
953 element->compound = NOT_COMPOUND;
954 cursor++;
955 break;
956
957 case DIRECTIVE_BIT:
958 case DIRECTIVE_OCTET:
959 element->compound = NOT_COMPOUND;
960 cursor++;
961 if (cursor >= end)
962 goto overrun_error;
963 if (cursor->token_type != DIRECTIVE_STRING)
964 goto parse_error;
965 cursor++;
966 break;
967
968 case DIRECTIVE_OBJECT:
969 element->compound = NOT_COMPOUND;
970 cursor++;
971 if (cursor >= end)
972 goto overrun_error;
973 if (cursor->token_type != DIRECTIVE_IDENTIFIER)
974 goto parse_error;
975 cursor++;
976 break;
977
978 case TOKEN_TYPE_NAME:
979 element->compound = TYPE_REF;
980 ref = bsearch(cursor, type_index, nr_types, sizeof(type_index[0]),
981 type_finder);
982 if (!ref) {
983 fprintf(stderr, "%s:%d: Type '%*.*s' undefined\n",
984 filename, cursor->line,
985 (int)cursor->size, (int)cursor->size, cursor->value);
986 exit(1);
987 }
988 cursor->type = *ref;
989 (*ref)->ref_count++;
990 cursor++;
991 break;
992
993 case DIRECTIVE_CHOICE:
994 element->compound = CHOICE;
995 cursor++;
996 element->children = parse_compound(&cursor, end, 1);
997 break;
998
999 case DIRECTIVE_SEQUENCE:
1000 element->compound = SEQUENCE;
1001 element->method = ASN1_CONS;
1002 cursor++;
1003 if (cursor >= end)
1004 goto overrun_error;
1005 if (cursor->token_type == DIRECTIVE_OF) {
1006 element->compound = SEQUENCE_OF;
1007 cursor++;
1008 if (cursor >= end)
1009 goto overrun_error;
1010 element->children = parse_type(&cursor, end, NULL);
1011 } else {
1012 element->children = parse_compound(&cursor, end, 0);
1013 }
1014 break;
1015
1016 case DIRECTIVE_SET:
1017 element->compound = SET;
1018 element->method = ASN1_CONS;
1019 cursor++;
1020 if (cursor >= end)
1021 goto overrun_error;
1022 if (cursor->token_type == DIRECTIVE_OF) {
1023 element->compound = SET_OF;
1024 cursor++;
1025 if (cursor >= end)
1026 goto parse_error;
1027 element->children = parse_type(&cursor, end, NULL);
1028 } else {
1029 element->children = parse_compound(&cursor, end, 1);
1030 }
1031 break;
1032
1033 default:
1034 fprintf(stderr, "%s:%d: Token '%*.*s' does not introduce a type\n",
1035 filename, cursor->line,
1036 (int)cursor->size, (int)cursor->size, cursor->value);
1037 exit(1);
1038 }
1039
1040 /* Handle elements that are optional */
1041 if (cursor < end && (cursor->token_type == DIRECTIVE_OPTIONAL ||
1042 cursor->token_type == DIRECTIVE_DEFAULT)
1043 ) {
1044 cursor++;
1045 top->flags |= ELEMENT_SKIPPABLE;
1046 }
1047
1048 if (cursor < end && cursor->token_type == TOKEN_OPEN_ACTION) {
1049 cursor++;
1050 if (cursor >= end)
1051 goto overrun_error;
1052 if (cursor->token_type != TOKEN_ELEMENT_NAME) {
1053 fprintf(stderr, "%s:%d: Token '%*.*s' is not an action function name\n",
1054 filename, cursor->line,
1055 (int)cursor->size, (int)cursor->size, cursor->value);
1056 exit(1);
1057 }
1058
1059 action = malloc(sizeof(struct action) + cursor->size + 1);
1060 if (!action) {
1061 perror(NULL);
1062 exit(1);
1063 }
1064 action->index = 0;
1065 memcpy(action->name, cursor->value, cursor->size);
1066 action->name[cursor->size] = 0;
1067
1068 for (ppaction = &action_list;
1069 *ppaction;
1070 ppaction = &(*ppaction)->next
1071 ) {
1072 int cmp = strcmp(action->name, (*ppaction)->name);
1073 if (cmp == 0) {
1074 free(action);
1075 action = *ppaction;
1076 goto found;
1077 }
1078 if (cmp < 0) {
1079 action->next = *ppaction;
1080 *ppaction = action;
1081 nr_actions++;
1082 goto found;
1083 }
1084 }
1085 action->next = NULL;
1086 *ppaction = action;
1087 nr_actions++;
1088 found:
1089
1090 element->action = action;
1091 cursor->action = action;
1092 cursor++;
1093 if (cursor >= end)
1094 goto overrun_error;
1095 if (cursor->token_type != TOKEN_CLOSE_ACTION) {
1096 fprintf(stderr, "%s:%d: Missing close action, got '%*.*s'\n",
1097 filename, cursor->line,
1098 (int)cursor->size, (int)cursor->size, cursor->value);
1099 exit(1);
1100 }
1101 cursor++;
1102 }
1103
1104 *_cursor = cursor;
1105 return top;
1106
1107parse_error:
1108 fprintf(stderr, "%s:%d: Unexpected token '%*.*s'\n",
1109 filename, cursor->line,
1110 (int)cursor->size, (int)cursor->size, cursor->value);
1111 exit(1);
1112
1113overrun_error:
1114 fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
1115 exit(1);
1116}
1117
1118/*
1119 * Parse a compound type list
1120 */
1121static struct element *parse_compound(struct token **_cursor, struct token *end,
1122 int alternates)
1123{
1124 struct element *children, **child_p = &children, *element;
1125 struct token *cursor = *_cursor, *name;
1126
1127 if (cursor->token_type != TOKEN_OPEN_CURLY) {
1128 fprintf(stderr, "%s:%d: Expected compound to start with brace not '%*.*s'\n",
1129 filename, cursor->line,
1130 (int)cursor->size, (int)cursor->size, cursor->value);
1131 exit(1);
1132 }
1133 cursor++;
1134 if (cursor >= end)
1135 goto overrun_error;
1136
1137 if (cursor->token_type == TOKEN_OPEN_CURLY) {
1138 fprintf(stderr, "%s:%d: Empty compound\n",
1139 filename, cursor->line);
1140 exit(1);
1141 }
1142
1143 for (;;) {
1144 name = NULL;
1145 if (cursor->token_type == TOKEN_ELEMENT_NAME) {
1146 name = cursor;
1147 cursor++;
1148 if (cursor >= end)
1149 goto overrun_error;
1150 }
1151
1152 element = parse_type(&cursor, end, name);
1153 if (alternates)
1154 element->flags |= ELEMENT_SKIPPABLE | ELEMENT_CONDITIONAL;
1155
1156 *child_p = element;
1157 child_p = &element->next;
1158
1159 if (cursor >= end)
1160 goto overrun_error;
1161 if (cursor->token_type != TOKEN_COMMA)
1162 break;
1163 cursor++;
1164 if (cursor >= end)
1165 goto overrun_error;
1166 }
1167
1168 children->flags &= ~ELEMENT_CONDITIONAL;
1169
1170 if (cursor->token_type != TOKEN_CLOSE_CURLY) {
1171 fprintf(stderr, "%s:%d: Expected compound closure, got '%*.*s'\n",
1172 filename, cursor->line,
1173 (int)cursor->size, (int)cursor->size, cursor->value);
1174 exit(1);
1175 }
1176 cursor++;
1177
1178 *_cursor = cursor;
1179 return children;
1180
1181overrun_error:
1182 fprintf(stderr, "%s: Unexpectedly hit EOF\n", filename);
1183 exit(1);
1184}
1185
1186static void render_element(FILE *out, struct element *e, struct element *tag);
1187static void render_out_of_line_list(FILE *out);
1188
1189static int nr_entries;
1190static int render_depth = 1;
1191static struct element *render_list, **render_list_p = &render_list;
1192
1193__attribute__((format(printf, 2, 3)))
1194static void render_opcode(FILE *out, const char *fmt, ...)
1195{
1196 va_list va;
1197
1198 if (out) {
1199 fprintf(out, "\t[%4d] =%*s", nr_entries, render_depth, "");
1200 va_start(va, fmt);
1201 vfprintf(out, fmt, va);
1202 va_end(va);
1203 }
1204 nr_entries++;
1205}
1206
1207__attribute__((format(printf, 2, 3)))
1208static void render_more(FILE *out, const char *fmt, ...)
1209{
1210 va_list va;
1211
1212 if (out) {
1213 va_start(va, fmt);
1214 vfprintf(out, fmt, va);
1215 va_end(va);
1216 }
1217}
1218
1219/*
1220 * Render the grammar into a state machine definition.
1221 */
1222static void render(FILE *out, FILE *hdr)
1223{
1224 struct element *e;
1225 struct action *action;
1226 struct type *root;
1227 int index;
1228
1229 fprintf(hdr, "/*\n");
1230 fprintf(hdr, " * Automatically generated by asn1_compiler. Do not edit\n");
1231 fprintf(hdr, " *\n");
1232 fprintf(hdr, " * ASN.1 parser for %s\n", grammar_name);
1233 fprintf(hdr, " */\n");
1234 fprintf(hdr, "#include <linux/asn1_decoder.h>\n");
1235 fprintf(hdr, "\n");
1236 fprintf(hdr, "extern const struct asn1_decoder %s_decoder;\n", grammar_name);
1237 if (ferror(hdr)) {
1238 perror(headername);
1239 exit(1);
1240 }
1241
1242 fprintf(out, "/*\n");
1243 fprintf(out, " * Automatically generated by asn1_compiler. Do not edit\n");
1244 fprintf(out, " *\n");
1245 fprintf(out, " * ASN.1 parser for %s\n", grammar_name);
1246 fprintf(out, " */\n");
1247 fprintf(out, "#include <linux/asn1_ber_bytecode.h>\n");
1248 fprintf(out, "#include \"%s-asn1.h\"\n", grammar_name);
1249 fprintf(out, "\n");
1250 if (ferror(out)) {
1251 perror(outputname);
1252 exit(1);
1253 }
1254
1255 /* Tabulate the action functions we might have to call */
1256 fprintf(hdr, "\n");
1257 index = 0;
1258 for (action = action_list; action; action = action->next) {
1259 action->index = index++;
1260 fprintf(hdr,
1261 "extern int %s(void *, size_t, unsigned char,"
1262 " const void *, size_t);\n",
1263 action->name);
1264 }
1265 fprintf(hdr, "\n");
1266
1267 fprintf(out, "enum %s_actions {\n", grammar_name);
1268 for (action = action_list; action; action = action->next)
1269 fprintf(out, "\tACT_%s = %u,\n",
1270 action->name, action->index);
1271 fprintf(out, "\tNR__%s_actions = %u\n", grammar_name, nr_actions);
1272 fprintf(out, "};\n");
1273
1274 fprintf(out, "\n");
1275 fprintf(out, "static const asn1_action_t %s_action_table[NR__%s_actions] = {\n",
1276 grammar_name, grammar_name);
1277 for (action = action_list; action; action = action->next)
1278 fprintf(out, "\t[%4u] = %s,\n", action->index, action->name);
1279 fprintf(out, "};\n");
1280
1281 if (ferror(out)) {
1282 perror(outputname);
1283 exit(1);
1284 }
1285
1286 /* We do two passes - the first one calculates all the offsets */
1287 printf("Pass 1\n");
1288 nr_entries = 0;
1289 root = &type_list[0];
1290 render_element(NULL, root->element, NULL);
1291 render_opcode(NULL, "ASN1_OP_COMPLETE,\n");
1292 render_out_of_line_list(NULL);
1293
1294 for (e = element_list; e; e = e->list_next)
1295 e->flags &= ~ELEMENT_RENDERED;
1296
1297 /* And then we actually render */
1298 printf("Pass 2\n");
1299 fprintf(out, "\n");
1300 fprintf(out, "static const unsigned char %s_machine[] = {\n",
1301 grammar_name);
1302
1303 nr_entries = 0;
1304 root = &type_list[0];
1305 render_element(out, root->element, NULL);
1306 render_opcode(out, "ASN1_OP_COMPLETE,\n");
1307 render_out_of_line_list(out);
1308
1309 fprintf(out, "};\n");
1310
1311 fprintf(out, "\n");
1312 fprintf(out, "const struct asn1_decoder %s_decoder = {\n", grammar_name);
1313 fprintf(out, "\t.machine = %s_machine,\n", grammar_name);
1314 fprintf(out, "\t.machlen = sizeof(%s_machine),\n", grammar_name);
1315 fprintf(out, "\t.actions = %s_action_table,\n", grammar_name);
1316 fprintf(out, "};\n");
1317}
1318
1319/*
1320 * Render the out-of-line elements
1321 */
1322static void render_out_of_line_list(FILE *out)
1323{
1324 struct element *e, *ce;
1325 const char *act;
1326 int entry;
1327
1328 while ((e = render_list)) {
1329 render_list = e->render_next;
1330 if (!render_list)
1331 render_list_p = &render_list;
1332
1333 render_more(out, "\n");
1334 e->entry_index = entry = nr_entries;
1335 render_depth++;
1336 for (ce = e->children; ce; ce = ce->next)
1337 render_element(out, ce, NULL);
1338 render_depth--;
1339
1340 act = e->action ? "_ACT" : "";
1341 switch (e->compound) {
1342 case SEQUENCE:
1343 render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
1344 break;
1345 case SEQUENCE_OF:
1346 render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
1347 render_opcode(out, "_jump_target(%u),\n", entry);
1348 break;
1349 case SET:
1350 render_opcode(out, "ASN1_OP_END_SET%s,\n", act);
1351 break;
1352 case SET_OF:
1353 render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
1354 render_opcode(out, "_jump_target(%u),\n", entry);
1355 break;
1356 }
1357 if (e->action)
1358 render_opcode(out, "_action(ACT_%s),\n",
1359 e->action->name);
1360 render_opcode(out, "ASN1_OP_RETURN,\n");
1361 }
1362}
1363
1364/*
1365 * Render an element.
1366 */
1367static void render_element(FILE *out, struct element *e, struct element *tag)
1368{
1369 struct element *ec;
1370 const char *cond, *act;
1371 int entry, skippable = 0, outofline = 0;
1372
1373 if (e->flags & ELEMENT_SKIPPABLE ||
1374 (tag && tag->flags & ELEMENT_SKIPPABLE))
1375 skippable = 1;
1376
1377 if ((e->type_def && e->type_def->ref_count > 1) ||
1378 skippable)
1379 outofline = 1;
1380
1381 if (e->type_def && out) {
1382 render_more(out, "\t// %*.*s\n",
1383 (int)e->type_def->name->size, (int)e->type_def->name->size,
1384 e->type_def->name->value);
1385 }
1386
1387 /* Render the operation */
1388 cond = (e->flags & ELEMENT_CONDITIONAL ||
1389 (tag && tag->flags & ELEMENT_CONDITIONAL)) ? "COND_" : "";
1390 act = e->action ? "_ACT" : "";
1391 switch (e->compound) {
1392 case ANY:
1393 render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
1394 if (e->name)
1395 render_more(out, "\t\t// %*.*s",
1396 (int)e->name->size, (int)e->name->size,
1397 e->name->value);
1398 render_more(out, "\n");
1399 goto dont_render_tag;
1400
1401 case TAG_OVERRIDE:
1402 render_element(out, e->children, e);
1403 return;
1404
1405 case SEQUENCE:
1406 case SEQUENCE_OF:
1407 case SET:
1408 case SET_OF:
1409 render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
1410 cond,
1411 outofline ? "_JUMP" : "",
1412 skippable ? "_OR_SKIP" : "");
1413 break;
1414
1415 case CHOICE:
1416 goto dont_render_tag;
1417
1418 case TYPE_REF:
1419 if (e->class == ASN1_UNIV && e->method == ASN1_PRIM && e->tag == 0)
1420 goto dont_render_tag;
1421 default:
1422 render_opcode(out, "ASN1_OP_%sMATCH%s%s,",
1423 cond, act,
1424 skippable ? "_OR_SKIP" : "");
1425 break;
1426 }
1427
1428 if (e->name)
1429 render_more(out, "\t\t// %*.*s",
1430 (int)e->name->size, (int)e->name->size,
1431 e->name->value);
1432 render_more(out, "\n");
1433
1434 /* Render the tag */
1435 if (!tag)
1436 tag = e;
1437 if (tag->class == ASN1_UNIV &&
1438 tag->tag != 14 &&
1439 tag->tag != 15 &&
1440 tag->tag != 31)
1441 render_opcode(out, "_tag(%s, %s, %s),\n",
1442 asn1_classes[tag->class],
1443 asn1_methods[tag->method | e->method],
1444 asn1_universal_tags[tag->tag]);
1445 else
1446 render_opcode(out, "_tagn(%s, %s, %2u),\n",
1447 asn1_classes[tag->class],
1448 asn1_methods[tag->method | e->method],
1449 tag->tag);
1450 tag = NULL;
1451dont_render_tag:
1452
1453 /* Deal with compound types */
1454 switch (e->compound) {
1455 case TYPE_REF:
1456 render_element(out, e->type->type->element, tag);
1457 if (e->action)
1458 render_opcode(out, "ASN1_OP_ACT,\n");
1459 break;
1460
1461 case SEQUENCE:
1462 if (outofline) {
1463 /* Render out-of-line for multiple use or
1464 * skipability */
1465 render_opcode(out, "_jump_target(%u),", e->entry_index);
1466 if (e->type_def && e->type_def->name)
1467 render_more(out, "\t\t// --> %*.*s",
1468 (int)e->type_def->name->size,
1469 (int)e->type_def->name->size,
1470 e->type_def->name->value);
1471 render_more(out, "\n");
1472 if (!(e->flags & ELEMENT_RENDERED)) {
1473 e->flags |= ELEMENT_RENDERED;
1474 *render_list_p = e;
1475 render_list_p = &e->render_next;
1476 }
1477 return;
1478 } else {
1479 /* Render inline for single use */
1480 render_depth++;
1481 for (ec = e->children; ec; ec = ec->next)
1482 render_element(out, ec, NULL);
1483 render_depth--;
1484 render_opcode(out, "ASN1_OP_END_SEQ%s,\n", act);
1485 }
1486 break;
1487
1488 case SEQUENCE_OF:
1489 case SET_OF:
1490 if (outofline) {
1491 /* Render out-of-line for multiple use or
1492 * skipability */
1493 render_opcode(out, "_jump_target(%u),", e->entry_index);
1494 if (e->type_def && e->type_def->name)
1495 render_more(out, "\t\t// --> %*.*s",
1496 (int)e->type_def->name->size,
1497 (int)e->type_def->name->size,
1498 e->type_def->name->value);
1499 render_more(out, "\n");
1500 if (!(e->flags & ELEMENT_RENDERED)) {
1501 e->flags |= ELEMENT_RENDERED;
1502 *render_list_p = e;
1503 render_list_p = &e->render_next;
1504 }
1505 return;
1506 } else {
1507 /* Render inline for single use */
1508 entry = nr_entries;
1509 render_depth++;
1510 render_element(out, e->children, NULL);
1511 render_depth--;
1512 if (e->compound == SEQUENCE_OF)
1513 render_opcode(out, "ASN1_OP_END_SEQ_OF%s,\n", act);
1514 else
1515 render_opcode(out, "ASN1_OP_END_SET_OF%s,\n", act);
1516 render_opcode(out, "_jump_target(%u),\n", entry);
1517 }
1518 break;
1519
1520 case SET:
1521 /* I can't think of a nice way to do SET support without having
1522 * a stack of bitmasks to make sure no element is repeated.
1523 * The bitmask has also to be checked that no non-optional
1524 * elements are left out whilst not preventing optional
1525 * elements from being left out.
1526 */
1527 fprintf(stderr, "The ASN.1 SET type is not currently supported.\n");
1528 exit(1);
1529
1530 case CHOICE:
1531 for (ec = e->children; ec; ec = ec->next)
1532 render_element(out, ec, NULL);
1533 if (!skippable)
1534 render_opcode(out, "ASN1_OP_COND_FAIL,\n");
1535 if (e->action)
1536 render_opcode(out, "ASN1_OP_ACT,\n");
1537 break;
1538
1539 default:
1540 break;
1541 }
1542
1543 if (e->action)
1544 render_opcode(out, "_action(ACT_%s),\n", e->action->name);
1545}
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index ca05ba217f5f..21a9f5de0a21 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -421,7 +421,7 @@ sub top_of_kernel_tree {
421 } 421 }
422 } 422 }
423 return 1; 423 return 1;
424 } 424}
425 425
426sub parse_email { 426sub parse_email {
427 my ($formatted_email) = @_; 427 my ($formatted_email) = @_;
@@ -1386,6 +1386,8 @@ sub process {
1386 my $in_header_lines = 1; 1386 my $in_header_lines = 1;
1387 my $in_commit_log = 0; #Scanning lines before patch 1387 my $in_commit_log = 0; #Scanning lines before patch
1388 1388
1389 my $non_utf8_charset = 0;
1390
1389 our @report = (); 1391 our @report = ();
1390 our $cnt_lines = 0; 1392 our $cnt_lines = 0;
1391 our $cnt_error = 0; 1393 our $cnt_error = 0;
@@ -1686,10 +1688,17 @@ sub process {
1686 $in_commit_log = 1; 1688 $in_commit_log = 1;
1687 } 1689 }
1688 1690
1689# Still not yet in a patch, check for any UTF-8 1691# Check if there is UTF-8 in a commit log when a mail header has explicitly
1690 if ($in_commit_log && $realfile =~ /^$/ && 1692# declined it, i.e defined some charset where it is missing.
1693 if ($in_header_lines &&
1694 $rawline =~ /^Content-Type:.+charset="(.+)".*$/ &&
1695 $1 !~ /utf-8/i) {
1696 $non_utf8_charset = 1;
1697 }
1698
1699 if ($in_commit_log && $non_utf8_charset && $realfile =~ /^$/ &&
1691 $rawline =~ /$NON_ASCII_UTF8/) { 1700 $rawline =~ /$NON_ASCII_UTF8/) {
1692 CHK("UTF8_BEFORE_PATCH", 1701 WARN("UTF8_BEFORE_PATCH",
1693 "8-bit UTF-8 used in possible commit log\n" . $herecurr); 1702 "8-bit UTF-8 used in possible commit log\n" . $herecurr);
1694 } 1703 }
1695 1704
@@ -1873,6 +1882,20 @@ sub process {
1873 "No space is necessary after a cast\n" . $hereprev); 1882 "No space is necessary after a cast\n" . $hereprev);
1874 } 1883 }
1875 1884
1885 if ($realfile =~ m@^(drivers/net/|net/)@ &&
1886 $rawline =~ /^\+[ \t]*\/\*[ \t]*$/ &&
1887 $prevrawline =~ /^\+[ \t]*$/) {
1888 WARN("NETWORKING_BLOCK_COMMENT_STYLE",
1889 "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev);
1890 }
1891
1892 if ($realfile =~ m@^(drivers/net/|net/)@ &&
1893 $rawline !~ m@^\+[ \t]*(\/\*|\*\/)@ &&
1894 $rawline =~ m@^\+[ \t]*.+\*\/[ \t]*$@) {
1895 WARN("NETWORKING_BLOCK_COMMENT_STYLE",
1896 "networking block comments put the trailing */ on a separate line\n" . $herecurr);
1897 }
1898
1876# check for spaces at the beginning of a line. 1899# check for spaces at the beginning of a line.
1877# Exceptions: 1900# Exceptions:
1878# 1) within comments 1901# 1) within comments
@@ -2390,8 +2413,10 @@ sub process {
2390 my $orig = $1; 2413 my $orig = $1;
2391 my $level = lc($orig); 2414 my $level = lc($orig);
2392 $level = "warn" if ($level eq "warning"); 2415 $level = "warn" if ($level eq "warning");
2416 my $level2 = $level;
2417 $level2 = "dbg" if ($level eq "debug");
2393 WARN("PREFER_PR_LEVEL", 2418 WARN("PREFER_PR_LEVEL",
2394 "Prefer pr_$level(... to printk(KERN_$1, ...\n" . $herecurr); 2419 "Prefer netdev_$level2(netdev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
2395 } 2420 }
2396 2421
2397 if ($line =~ /\bpr_warning\s*\(/) { 2422 if ($line =~ /\bpr_warning\s*\(/) {
@@ -2947,7 +2972,7 @@ sub process {
2947 my $exceptions = qr{ 2972 my $exceptions = qr{
2948 $Declare| 2973 $Declare|
2949 module_param_named| 2974 module_param_named|
2950 MODULE_PARAM_DESC| 2975 MODULE_PARM_DESC|
2951 DECLARE_PER_CPU| 2976 DECLARE_PER_CPU|
2952 DEFINE_PER_CPU| 2977 DEFINE_PER_CPU|
2953 __typeof__\(| 2978 __typeof__\(|
diff --git a/scripts/coccicheck b/scripts/coccicheck
index 823e972149e5..1a49d1c7ecfe 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -95,6 +95,9 @@ coccinelle () {
95 $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \ 95 $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \
96 $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \ 96 $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
97 $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1 97 $SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1
98 elif [ "$MODE" = "rep+ctxt" ] ; then
99 $SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff && \
100 $SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
98 else 101 else
99 $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1 102 $SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
100 fi 103 fi
diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
index cbfd08c7d8c7..15f076fdecbe 100644
--- a/scripts/coccinelle/api/ptr_ret.cocci
+++ b/scripts/coccinelle/api/ptr_ret.cocci
@@ -30,6 +30,13 @@ expression ptr;
30- if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; 30- if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
31+ return PTR_RET(ptr); 31+ return PTR_RET(ptr);
32 32
33@depends on patch@
34expression ptr;
35@@
36
37- (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
38+ PTR_RET(ptr)
39
33@r1 depends on !patch@ 40@r1 depends on !patch@
34expression ptr; 41expression ptr;
35position p1; 42position p1;
@@ -44,6 +51,13 @@ position p2;
44 51
45* if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0; 52* if@p2 (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
46 53
54@r3 depends on !patch@
55expression ptr;
56position p3;
57@@
58
59* IS_ERR@p3(ptr) ? PTR_ERR(ptr) : 0
60
47@script:python depends on org@ 61@script:python depends on org@
48p << r1.p1; 62p << r1.p1;
49@@ 63@@
@@ -57,6 +71,12 @@ p << r2.p2;
57 71
58coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used") 72coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
59 73
74@script:python depends on org@
75p << r3.p3;
76@@
77
78coccilib.org.print_todo(p[0], "WARNING: PTR_RET can be used")
79
60@script:python depends on report@ 80@script:python depends on report@
61p << r1.p1; 81p << r1.p1;
62@@ 82@@
@@ -68,3 +88,9 @@ p << r2.p2;
68@@ 88@@
69 89
70coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used") 90coccilib.report.print_report(p[0], "WARNING: PTR_RET can be used")
91
92@script:python depends on report@
93p << r3.p3;
94@@
95
96coccilib.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 000000000000..e8dd8a6b28a2
--- /dev/null
+++ b/scripts/coccinelle/tests/odd_ptr_err.cocci
@@ -0,0 +1,65 @@
1/// PTR_ERR should access the value just tested by IS_ERR
2//# There can be false positives in the patch case, where it is the call
3//# IS_ERR that is wrong.
4///
5// Confidence: High
6// Copyright: (C) 2012 Julia Lawall, INRIA. GPLv2.
7// Copyright: (C) 2012 Gilles Muller, INRIA. GPLv2.
8// URL: http://coccinelle.lip6.fr/
9// Comments:
10// Options: -no_includes -include_headers
11
12virtual patch
13virtual context
14virtual org
15virtual report
16
17@depends on patch@
18expression e,e1;
19@@
20
21(
22if (IS_ERR(e)) { ... PTR_ERR(e) ... }
23|
24if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
25|
26if (IS_ERR(e))
27 { ...
28 PTR_ERR(
29- e1
30+ e
31 )
32 ... }
33)
34
35@r depends on !patch@
36expression e,e1;
37position p1,p2;
38@@
39
40(
41if (IS_ERR(e)) { ... PTR_ERR(e) ... }
42|
43if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... }
44|
45*if (IS_ERR@p1(e))
46 { ...
47* PTR_ERR@p2(e1)
48 ... }
49)
50
51@script:python depends on org@
52p1 << r.p1;
53p2 << r.p2;
54@@
55
56cocci.print_main("inconsistent IS_ERR and PTR_ERR",p1)
57cocci.print_secs("PTR_ERR",p2)
58
59@script:python depends on report@
60p1 << r.p1;
61p2 << r.p2;
62@@
63
64msg = "inconsistent IS_ERR and PTR_ERR, PTR_ERR on line %s" % (p2[0].line)
65coccilib.report.print_report(p1[0],msg)
diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh
index debecb5561c4..7f2126df91f2 100644
--- a/scripts/gcc-version.sh
+++ b/scripts/gcc-version.sh
@@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then
22 exit 1 22 exit 1
23fi 23fi
24 24
25MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) 25MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1)
26MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) 26MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1)
27if [ "x$with_patchlevel" != "x" ] ; then 27if [ "x$with_patchlevel" != "x" ] ; then
28 PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) 28 PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1)
29 printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL 29 printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL
30else 30else
31 printf "%02d%02d\\n" $MAJOR $MINOR 31 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 29493dc4528d..12dbd0b11ea4 100644
--- a/scripts/gcc-x86_32-has-stack-protector.sh
+++ b/scripts/gcc-x86_32-has-stack-protector.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2 2
3echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" 3echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
4if [ "$?" -eq "0" ] ; then 4if [ "$?" -eq "0" ] ; then
5 echo y 5 echo y
6else 6else
diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh
index afaec618b395..973e8c141567 100644
--- a/scripts/gcc-x86_64-has-stack-protector.sh
+++ b/scripts/gcc-x86_64-has-stack-protector.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2 2
3echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" 3echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs"
4if [ "$?" -eq "0" ] ; then 4if [ "$?" -eq "0" ] ; then
5 echo y 5 echo y
6else 6else
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile
index 77d53999ffb9..3091794e9354 100644
--- a/scripts/kconfig/Makefile
+++ b/scripts/kconfig/Makefile
@@ -76,11 +76,17 @@ PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
76allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf 76allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
77 $< --$@ $(Kconfig) 77 $< --$@ $(Kconfig)
78 78
79PHONY += listnewconfig oldnoconfig savedefconfig defconfig 79PHONY += listnewconfig olddefconfig oldnoconfig savedefconfig defconfig
80 80
81listnewconfig oldnoconfig: $(obj)/conf 81listnewconfig olddefconfig: $(obj)/conf
82 $< --$@ $(Kconfig) 82 $< --$@ $(Kconfig)
83 83
84# oldnoconfig is an alias of olddefconfig, because people already are dependent
85# on its behavior(sets new symbols to their default value but not 'n') with the
86# counter-intuitive name.
87oldnoconfig: $(obj)/conf
88 $< --olddefconfig $(Kconfig)
89
84savedefconfig: $(obj)/conf 90savedefconfig: $(obj)/conf
85 $< --$@=defconfig $(Kconfig) 91 $< --$@=defconfig $(Kconfig)
86 92
@@ -114,7 +120,7 @@ help:
114 @echo ' alldefconfig - New config with all symbols set to default' 120 @echo ' alldefconfig - New config with all symbols set to default'
115 @echo ' randconfig - New config with random answer to all options' 121 @echo ' randconfig - New config with random answer to all options'
116 @echo ' listnewconfig - List new options' 122 @echo ' listnewconfig - List new options'
117 @echo ' oldnoconfig - Same as silentoldconfig but sets new symbols to their default value' 123 @echo ' olddefconfig - Same as silentoldconfig but sets new symbols to their default value'
118 124
119# lxdialog stuff 125# lxdialog stuff
120check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh 126check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh
index fa59cbf9d62c..854d9c7c675c 100755
--- a/scripts/kconfig/check.sh
+++ b/scripts/kconfig/check.sh
@@ -1,6 +1,6 @@
1#!/bin/sh 1#!/bin/sh
2# Needed for systems without gettext 2# Needed for systems without gettext
3$* -xc -o /dev/null - > /dev/null 2>&1 << EOF 3$* -x c -o /dev/null - > /dev/null 2>&1 << EOF
4#include <libintl.h> 4#include <libintl.h>
5int main() 5int main()
6{ 6{
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 0dc4a2c779b1..4da3b4adfad2 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -32,7 +32,7 @@ enum input_mode {
32 defconfig, 32 defconfig,
33 savedefconfig, 33 savedefconfig,
34 listnewconfig, 34 listnewconfig,
35 oldnoconfig, 35 olddefconfig,
36} input_mode = oldaskconfig; 36} input_mode = oldaskconfig;
37 37
38static int indent = 1; 38static int indent = 1;
@@ -365,7 +365,7 @@ static void conf(struct menu *menu)
365 case P_MENU: 365 case P_MENU:
366 if ((input_mode == silentoldconfig || 366 if ((input_mode == silentoldconfig ||
367 input_mode == listnewconfig || 367 input_mode == listnewconfig ||
368 input_mode == oldnoconfig) && 368 input_mode == olddefconfig) &&
369 rootEntry != menu) { 369 rootEntry != menu) {
370 check_conf(menu); 370 check_conf(menu);
371 return; 371 return;
@@ -429,7 +429,7 @@ static void check_conf(struct menu *menu)
429 if (sym->name && !sym_is_choice_value(sym)) { 429 if (sym->name && !sym_is_choice_value(sym)) {
430 printf("%s%s\n", CONFIG_, sym->name); 430 printf("%s%s\n", CONFIG_, sym->name);
431 } 431 }
432 } else if (input_mode != oldnoconfig) { 432 } else if (input_mode != olddefconfig) {
433 if (!conf_cnt++) 433 if (!conf_cnt++)
434 printf(_("*\n* Restart config...\n*\n")); 434 printf(_("*\n* Restart config...\n*\n"));
435 rootEntry = menu_get_parent_menu(menu); 435 rootEntry = menu_get_parent_menu(menu);
@@ -454,7 +454,13 @@ static struct option long_opts[] = {
454 {"alldefconfig", no_argument, NULL, alldefconfig}, 454 {"alldefconfig", no_argument, NULL, alldefconfig},
455 {"randconfig", no_argument, NULL, randconfig}, 455 {"randconfig", no_argument, NULL, randconfig},
456 {"listnewconfig", no_argument, NULL, listnewconfig}, 456 {"listnewconfig", no_argument, NULL, listnewconfig},
457 {"oldnoconfig", no_argument, NULL, oldnoconfig}, 457 {"olddefconfig", no_argument, NULL, olddefconfig},
458 /*
459 * oldnoconfig is an alias of olddefconfig, because people already
460 * are dependent on its behavior(sets new symbols to their default
461 * value but not 'n') with the counter-intuitive name.
462 */
463 {"oldnoconfig", no_argument, NULL, olddefconfig},
458 {NULL, 0, NULL, 0} 464 {NULL, 0, NULL, 0}
459}; 465};
460 466
@@ -467,7 +473,8 @@ static void conf_usage(const char *progname)
467 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n"); 473 printf(" --oldaskconfig Start a new configuration using a line-oriented program\n");
468 printf(" --oldconfig Update a configuration using a provided .config as base\n"); 474 printf(" --oldconfig Update a configuration using a provided .config as base\n");
469 printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n"); 475 printf(" --silentoldconfig Same as oldconfig, but quietly, additionally update deps\n");
470 printf(" --oldnoconfig Same as silentoldconfig but set new symbols to no\n"); 476 printf(" --olddefconfig Same as silentoldconfig but sets new symbols to their default value\n");
477 printf(" --oldnoconfig An alias of olddefconfig\n");
471 printf(" --defconfig <file> New config with default defined in <file>\n"); 478 printf(" --defconfig <file> New config with default defined in <file>\n");
472 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n"); 479 printf(" --savedefconfig <file> Save the minimal current configuration to <file>\n");
473 printf(" --allnoconfig New config where all options are answered with no\n"); 480 printf(" --allnoconfig New config where all options are answered with no\n");
@@ -520,7 +527,7 @@ int main(int ac, char **av)
520 case allmodconfig: 527 case allmodconfig:
521 case alldefconfig: 528 case alldefconfig:
522 case listnewconfig: 529 case listnewconfig:
523 case oldnoconfig: 530 case olddefconfig:
524 break; 531 break;
525 case '?': 532 case '?':
526 conf_usage(progname); 533 conf_usage(progname);
@@ -565,7 +572,7 @@ int main(int ac, char **av)
565 case oldaskconfig: 572 case oldaskconfig:
566 case oldconfig: 573 case oldconfig:
567 case listnewconfig: 574 case listnewconfig:
568 case oldnoconfig: 575 case olddefconfig:
569 conf_read(NULL); 576 conf_read(NULL);
570 break; 577 break;
571 case allnoconfig: 578 case allnoconfig:
@@ -645,7 +652,7 @@ int main(int ac, char **av)
645 /* fall through */ 652 /* fall through */
646 case oldconfig: 653 case oldconfig:
647 case listnewconfig: 654 case listnewconfig:
648 case oldnoconfig: 655 case olddefconfig:
649 case silentoldconfig: 656 case silentoldconfig:
650 /* Update until a loop caused no more changes */ 657 /* Update until a loop caused no more changes */
651 do { 658 do {
@@ -653,7 +660,7 @@ int main(int ac, char **av)
653 check_conf(&rootmenu); 660 check_conf(&rootmenu);
654 } while (conf_cnt && 661 } while (conf_cnt &&
655 (input_mode != listnewconfig && 662 (input_mode != listnewconfig &&
656 input_mode != oldnoconfig)); 663 input_mode != olddefconfig));
657 break; 664 break;
658 } 665 }
659 666
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index d4ecce8bc3a6..bd2e09895553 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -12,6 +12,7 @@ extern "C" {
12 12
13#include <assert.h> 13#include <assert.h>
14#include <stdio.h> 14#include <stdio.h>
15#include <sys/queue.h>
15#ifndef __cplusplus 16#ifndef __cplusplus
16#include <stdbool.h> 17#include <stdbool.h>
17#endif 18#endif
@@ -173,6 +174,16 @@ struct menu {
173#define MENU_CHANGED 0x0001 174#define MENU_CHANGED 0x0001
174#define MENU_ROOT 0x0002 175#define MENU_ROOT 0x0002
175 176
177struct jump_key {
178 CIRCLEQ_ENTRY(jump_key) entries;
179 size_t offset;
180 struct menu *target;
181 int index;
182};
183CIRCLEQ_HEAD(jk_head, jump_key);
184
185#define JUMP_NB 9
186
176extern struct file *file_list; 187extern struct file *file_list;
177extern struct file *current_file; 188extern struct file *current_file;
178struct file *lookup_file(const char *name); 189struct file *lookup_file(const char *name);
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 47fe9c340f9a..1d1c08537f1e 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));
21P(menu_get_parent_menu,struct menu *,(struct menu *menu)); 21P(menu_get_parent_menu,struct menu *,(struct menu *menu));
22P(menu_has_help,bool,(struct menu *menu)); 22P(menu_has_help,bool,(struct menu *menu));
23P(menu_get_help,const char *,(struct menu *menu)); 23P(menu_get_help,const char *,(struct menu *menu));
24P(get_symbol_str, void, (struct gstr *r, struct symbol *sym)); 24P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
25P(get_relations_str, struct gstr, (struct symbol **sym_arr)); 25 *head));
26P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
27 *head));
26P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help)); 28P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
27 29
28/* symbol.c */ 30/* symbol.c */
diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh
index e3b12c010417..c8e8a7154753 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
38 38
39# Check if we can link to ncurses 39# Check if we can link to ncurses
40check() { 40check() {
41 $cc -xc - -o $tmp 2>/dev/null <<'EOF' 41 $cc -x c - -o $tmp 2>/dev/null <<'EOF'
42#include CURSES_LOC 42#include CURSES_LOC
43main() {} 43main() {}
44EOF 44EOF
diff --git a/scripts/kconfig/lxdialog/dialog.h b/scripts/kconfig/lxdialog/dialog.h
index b5211fce0d94..ee17a5264d5b 100644
--- a/scripts/kconfig/lxdialog/dialog.h
+++ b/scripts/kconfig/lxdialog/dialog.h
@@ -144,6 +144,7 @@ struct dialog_info {
144 */ 144 */
145extern struct dialog_info dlg; 145extern struct dialog_info dlg;
146extern char dialog_input_result[]; 146extern char dialog_input_result[];
147extern int saved_x, saved_y; /* Needed in signal handler in mconf.c */
147 148
148/* 149/*
149 * Function prototypes 150 * Function prototypes
@@ -209,7 +210,13 @@ int first_alpha(const char *string, const char *exempt);
209int dialog_yesno(const char *title, const char *prompt, int height, int width); 210int dialog_yesno(const char *title, const char *prompt, int height, int width);
210int dialog_msgbox(const char *title, const char *prompt, int height, 211int dialog_msgbox(const char *title, const char *prompt, int height,
211 int width, int pause); 212 int width, int pause);
212int dialog_textbox(const char *title, const char *file, int height, int width); 213
214
215typedef void (*update_text_fn)(char *buf, size_t start, size_t end, void
216 *_data);
217int dialog_textbox(const char *title, char *tbuf, int initial_height,
218 int initial_width, int *keys, int *_vscroll, int *_hscroll,
219 update_text_fn update_text, void *data);
213int dialog_menu(const char *title, const char *prompt, 220int dialog_menu(const char *title, const char *prompt,
214 const void *selected, int *s_scroll); 221 const void *selected, int *s_scroll);
215int dialog_checklist(const char *title, const char *prompt, int height, 222int 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 4e5de60a0c0d..a48bb93e0907 100644
--- a/scripts/kconfig/lxdialog/textbox.c
+++ b/scripts/kconfig/lxdialog/textbox.c
@@ -22,23 +22,25 @@
22#include "dialog.h" 22#include "dialog.h"
23 23
24static void back_lines(int n); 24static void back_lines(int n);
25static void print_page(WINDOW * win, int height, int width); 25static void print_page(WINDOW *win, int height, int width, update_text_fn
26static void print_line(WINDOW * win, int row, int width); 26 update_text, void *data);
27static void print_line(WINDOW *win, int row, int width);
27static char *get_line(void); 28static char *get_line(void);
28static void print_position(WINDOW * win); 29static void print_position(WINDOW * win);
29 30
30static int hscroll; 31static int hscroll;
31static int begin_reached, end_reached, page_length; 32static int begin_reached, end_reached, page_length;
32static const char *buf; 33static char *buf;
33static const char *page; 34static char *page;
34 35
35/* 36/*
36 * refresh window content 37 * refresh window content
37 */ 38 */
38static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw, 39static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
39 int cur_y, int cur_x) 40 int cur_y, int cur_x, update_text_fn update_text,
41 void *data)
40{ 42{
41 print_page(box, boxh, boxw); 43 print_page(box, boxh, boxw, update_text, data);
42 print_position(dialog); 44 print_position(dialog);
43 wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 45 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
44 wrefresh(dialog); 46 wrefresh(dialog);
@@ -47,14 +49,18 @@ static void refresh_text_box(WINDOW *dialog, WINDOW *box, int boxh, int boxw,
47 49
48/* 50/*
49 * Display text from a file in a dialog box. 51 * Display text from a file in a dialog box.
52 *
53 * keys is a null-terminated array
54 * update_text() may not add or remove any '\n' or '\0' in tbuf
50 */ 55 */
51int dialog_textbox(const char *title, const char *tbuf, 56int dialog_textbox(const char *title, char *tbuf, int initial_height,
52 int initial_height, int initial_width) 57 int initial_width, int *keys, int *_vscroll, int *_hscroll,
58 update_text_fn update_text, void *data)
53{ 59{
54 int i, x, y, cur_x, cur_y, key = 0; 60 int i, x, y, cur_x, cur_y, key = 0;
55 int height, width, boxh, boxw; 61 int height, width, boxh, boxw;
56 int passed_end;
57 WINDOW *dialog, *box; 62 WINDOW *dialog, *box;
63 bool done = false;
58 64
59 begin_reached = 1; 65 begin_reached = 1;
60 end_reached = 0; 66 end_reached = 0;
@@ -63,6 +69,15 @@ int dialog_textbox(const char *title, const char *tbuf,
63 buf = tbuf; 69 buf = tbuf;
64 page = buf; /* page is pointer to start of page to be displayed */ 70 page = buf; /* page is pointer to start of page to be displayed */
65 71
72 if (_vscroll && *_vscroll) {
73 begin_reached = 0;
74
75 for (i = 0; i < *_vscroll; i++)
76 get_line();
77 }
78 if (_hscroll)
79 hscroll = *_hscroll;
80
66do_resize: 81do_resize:
67 getmaxyx(stdscr, height, width); 82 getmaxyx(stdscr, height, width);
68 if (height < 8 || width < 8) 83 if (height < 8 || width < 8)
@@ -120,9 +135,10 @@ do_resize:
120 135
121 /* Print first page of text */ 136 /* Print first page of text */
122 attr_clear(box, boxh, boxw, dlg.dialog.atr); 137 attr_clear(box, boxh, boxw, dlg.dialog.atr);
123 refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x); 138 refresh_text_box(dialog, box, boxh, boxw, cur_y, cur_x, update_text,
139 data);
124 140
125 while ((key != KEY_ESC) && (key != '\n')) { 141 while (!done) {
126 key = wgetch(dialog); 142 key = wgetch(dialog);
127 switch (key) { 143 switch (key) {
128 case 'E': /* Exit */ 144 case 'E': /* Exit */
@@ -130,16 +146,17 @@ do_resize:
130 case 'X': 146 case 'X':
131 case 'x': 147 case 'x':
132 case 'q': 148 case 'q':
133 delwin(box); 149 case '\n':
134 delwin(dialog); 150 done = true;
135 return 0; 151 break;
136 case 'g': /* First page */ 152 case 'g': /* First page */
137 case KEY_HOME: 153 case KEY_HOME:
138 if (!begin_reached) { 154 if (!begin_reached) {
139 begin_reached = 1; 155 begin_reached = 1;
140 page = buf; 156 page = buf;
141 refresh_text_box(dialog, box, boxh, boxw, 157 refresh_text_box(dialog, box, boxh, boxw,
142 cur_y, cur_x); 158 cur_y, cur_x, update_text,
159 data);
143 } 160 }
144 break; 161 break;
145 case 'G': /* Last page */ 162 case 'G': /* Last page */
@@ -149,45 +166,18 @@ do_resize:
149 /* point to last char in buf */ 166 /* point to last char in buf */
150 page = buf + strlen(buf); 167 page = buf + strlen(buf);
151 back_lines(boxh); 168 back_lines(boxh);
152 refresh_text_box(dialog, box, boxh, boxw, 169 refresh_text_box(dialog, box, boxh, boxw, cur_y,
153 cur_y, cur_x); 170 cur_x, update_text, data);
154 break; 171 break;
155 case 'K': /* Previous line */ 172 case 'K': /* Previous line */
156 case 'k': 173 case 'k':
157 case KEY_UP: 174 case KEY_UP:
158 if (!begin_reached) { 175 if (begin_reached)
159 back_lines(page_length + 1); 176 break;
160
161 /* We don't call print_page() here but use
162 * scrolling to ensure faster screen update.
163 * However, 'end_reached' and 'page_length'
164 * should still be updated, and 'page' should
165 * point to start of next page. This is done
166 * by calling get_line() in the following
167 * 'for' loop. */
168 scrollok(box, TRUE);
169 wscrl(box, -1); /* Scroll box region down one line */
170 scrollok(box, FALSE);
171 page_length = 0;
172 passed_end = 0;
173 for (i = 0; i < boxh; i++) {
174 if (!i) {
175 /* print first line of page */
176 print_line(box, 0, boxw);
177 wnoutrefresh(box);
178 } else
179 /* Called to update 'end_reached' and 'page' */
180 get_line();
181 if (!passed_end)
182 page_length++;
183 if (end_reached && !passed_end)
184 passed_end = 1;
185 }
186 177
187 print_position(dialog); 178 back_lines(page_length + 1);
188 wmove(dialog, cur_y, cur_x); /* Restore cursor position */ 179 refresh_text_box(dialog, box, boxh, boxw, cur_y,
189 wrefresh(dialog); 180 cur_x, update_text, data);
190 }
191 break; 181 break;
192 case 'B': /* Previous page */ 182 case 'B': /* Previous page */
193 case 'b': 183 case 'b':
@@ -196,23 +186,18 @@ do_resize:
196 if (begin_reached) 186 if (begin_reached)
197 break; 187 break;
198 back_lines(page_length + boxh); 188 back_lines(page_length + boxh);
199 refresh_text_box(dialog, box, boxh, boxw, 189 refresh_text_box(dialog, box, boxh, boxw, cur_y,
200 cur_y, cur_x); 190 cur_x, update_text, data);
201 break; 191 break;
202 case 'J': /* Next line */ 192 case 'J': /* Next line */
203 case 'j': 193 case 'j':
204 case KEY_DOWN: 194 case KEY_DOWN:
205 if (!end_reached) { 195 if (end_reached)
206 begin_reached = 0; 196 break;
207 scrollok(box, TRUE); 197
208 scroll(box); /* Scroll box region up one line */ 198 back_lines(page_length - 1);
209 scrollok(box, FALSE); 199 refresh_text_box(dialog, box, boxh, boxw, cur_y,
210 print_line(box, boxh - 1, boxw); 200 cur_x, update_text, data);
211 wnoutrefresh(box);
212 print_position(dialog);
213 wmove(dialog, cur_y, cur_x); /* Restore cursor position */
214 wrefresh(dialog);
215 }
216 break; 201 break;
217 case KEY_NPAGE: /* Next page */ 202 case KEY_NPAGE: /* Next page */
218 case ' ': 203 case ' ':
@@ -221,8 +206,8 @@ do_resize:
221 break; 206 break;
222 207
223 begin_reached = 0; 208 begin_reached = 0;
224 refresh_text_box(dialog, box, boxh, boxw, 209 refresh_text_box(dialog, box, boxh, boxw, cur_y,
225 cur_y, cur_x); 210 cur_x, update_text, data);
226 break; 211 break;
227 case '0': /* Beginning of line */ 212 case '0': /* Beginning of line */
228 case 'H': /* Scroll left */ 213 case 'H': /* Scroll left */
@@ -237,8 +222,8 @@ do_resize:
237 hscroll--; 222 hscroll--;
238 /* Reprint current page to scroll horizontally */ 223 /* Reprint current page to scroll horizontally */
239 back_lines(page_length); 224 back_lines(page_length);
240 refresh_text_box(dialog, box, boxh, boxw, 225 refresh_text_box(dialog, box, boxh, boxw, cur_y,
241 cur_y, cur_x); 226 cur_x, update_text, data);
242 break; 227 break;
243 case 'L': /* Scroll right */ 228 case 'L': /* Scroll right */
244 case 'l': 229 case 'l':
@@ -248,11 +233,12 @@ do_resize:
248 hscroll++; 233 hscroll++;
249 /* Reprint current page to scroll horizontally */ 234 /* Reprint current page to scroll horizontally */
250 back_lines(page_length); 235 back_lines(page_length);
251 refresh_text_box(dialog, box, boxh, boxw, 236 refresh_text_box(dialog, box, boxh, boxw, cur_y,
252 cur_y, cur_x); 237 cur_x, update_text, data);
253 break; 238 break;
254 case KEY_ESC: 239 case KEY_ESC:
255 key = on_key_esc(dialog); 240 if (on_key_esc(dialog) == KEY_ESC)
241 done = true;
256 break; 242 break;
257 case KEY_RESIZE: 243 case KEY_RESIZE:
258 back_lines(height); 244 back_lines(height);
@@ -260,11 +246,31 @@ do_resize:
260 delwin(dialog); 246 delwin(dialog);
261 on_key_resize(); 247 on_key_resize();
262 goto do_resize; 248 goto do_resize;
249 default:
250 for (i = 0; keys[i]; i++) {
251 if (key == keys[i]) {
252 done = true;
253 break;
254 }
255 }
263 } 256 }
264 } 257 }
265 delwin(box); 258 delwin(box);
266 delwin(dialog); 259 delwin(dialog);
267 return key; /* ESC pressed */ 260 if (_vscroll) {
261 const char *s;
262
263 s = buf;
264 *_vscroll = 0;
265 back_lines(page_length);
266 while (s < page && (s = strchr(s, '\n'))) {
267 (*_vscroll)++;
268 s++;
269 }
270 }
271 if (_hscroll)
272 *_hscroll = hscroll;
273 return key;
268} 274}
269 275
270/* 276/*
@@ -301,12 +307,23 @@ static void back_lines(int n)
301} 307}
302 308
303/* 309/*
304 * Print a new page of text. Called by dialog_textbox(). 310 * Print a new page of text.
305 */ 311 */
306static void print_page(WINDOW * win, int height, int width) 312static void print_page(WINDOW *win, int height, int width, update_text_fn
313 update_text, void *data)
307{ 314{
308 int i, passed_end = 0; 315 int i, passed_end = 0;
309 316
317 if (update_text) {
318 char *end;
319
320 for (i = 0; i < height; i++)
321 get_line();
322 end = page;
323 back_lines(height);
324 update_text(buf, page - buf, end - buf, data);
325 }
326
310 page_length = 0; 327 page_length = 0;
311 for (i = 0; i < height; i++) { 328 for (i = 0; i < height; i++) {
312 print_line(win, i, width); 329 print_line(win, i, width);
@@ -319,7 +336,7 @@ static void print_page(WINDOW * win, int height, int width)
319} 336}
320 337
321/* 338/*
322 * Print a new line of text. Called by dialog_textbox() and print_page(). 339 * Print a new line of text.
323 */ 340 */
324static void print_line(WINDOW * win, int row, int width) 341static void print_line(WINDOW * win, int row, int width)
325{ 342{
@@ -357,10 +374,8 @@ static char *get_line(void)
357 end_reached = 0; 374 end_reached = 0;
358 while (*page != '\n') { 375 while (*page != '\n') {
359 if (*page == '\0') { 376 if (*page == '\0') {
360 if (!end_reached) { 377 end_reached = 1;
361 end_reached = 1; 378 break;
362 break;
363 }
364 } else if (i < MAX_LEN) 379 } else if (i < MAX_LEN)
365 line[i++] = *(page++); 380 line[i++] = *(page++);
366 else { 381 else {
@@ -373,7 +388,7 @@ static char *get_line(void)
373 if (i <= MAX_LEN) 388 if (i <= MAX_LEN)
374 line[i] = '\0'; 389 line[i] = '\0';
375 if (!end_reached) 390 if (!end_reached)
376 page++; /* move pass '\n' */ 391 page++; /* move past '\n' */
377 392
378 return line; 393 return line;
379} 394}
diff --git a/scripts/kconfig/lxdialog/util.c b/scripts/kconfig/lxdialog/util.c
index f2375ad7ebc9..109d53117d22 100644
--- a/scripts/kconfig/lxdialog/util.c
+++ b/scripts/kconfig/lxdialog/util.c
@@ -23,6 +23,9 @@
23 23
24#include "dialog.h" 24#include "dialog.h"
25 25
26/* Needed in signal handler in mconf.c */
27int saved_x, saved_y;
28
26struct dialog_info dlg; 29struct dialog_info dlg;
27 30
28static void set_mono_theme(void) 31static void set_mono_theme(void)
@@ -273,6 +276,10 @@ int init_dialog(const char *backtitle)
273 int height, width; 276 int height, width;
274 277
275 initscr(); /* Init curses */ 278 initscr(); /* Init curses */
279
280 /* Get current cursor position for signal handler in mconf.c */
281 getyx(stdscr, saved_y, saved_x);
282
276 getmaxyx(stdscr, height, width); 283 getmaxyx(stdscr, height, width);
277 if (height < 19 || width < 80) { 284 if (height < 19 || width < 80) {
278 endwin(); 285 endwin();
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index f584a281bb4c..48f67448af7b 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -236,16 +236,19 @@ search_help[] = N_(
236 "Result:\n" 236 "Result:\n"
237 "-----------------------------------------------------------------\n" 237 "-----------------------------------------------------------------\n"
238 "Symbol: FOO [=m]\n" 238 "Symbol: FOO [=m]\n"
239 "Type : tristate\n"
239 "Prompt: Foo bus is used to drive the bar HW\n" 240 "Prompt: Foo bus is used to drive the bar HW\n"
240 "Defined at drivers/pci/Kconfig:47\n" 241 " Defined at drivers/pci/Kconfig:47\n"
241 "Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n" 242 " Depends on: X86_LOCAL_APIC && X86_IO_APIC || IA64\n"
242 "Location:\n" 243 " Location:\n"
243 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n" 244 " -> Bus options (PCI, PCMCIA, EISA, ISA)\n"
244 " -> PCI support (PCI [=y])\n" 245 " -> PCI support (PCI [=y])\n"
245 " -> PCI access mode (<choice> [=y])\n" 246 "(1) -> PCI access mode (<choice> [=y])\n"
246 "Selects: LIBCRC32\n" 247 " Selects: LIBCRC32\n"
247 "Selected by: BAR\n" 248 " Selected by: BAR\n"
248 "-----------------------------------------------------------------\n" 249 "-----------------------------------------------------------------\n"
250 "o The line 'Type:' shows the type of the configuration option for\n"
251 " this symbol (boolean, tristate, string, ...)\n"
249 "o The line 'Prompt:' shows the text used in the menu structure for\n" 252 "o The line 'Prompt:' shows the text used in the menu structure for\n"
250 " this symbol\n" 253 " this symbol\n"
251 "o The 'Defined at' line tell at what file / line number the symbol\n" 254 "o The 'Defined at' line tell at what file / line number the symbol\n"
@@ -254,8 +257,12 @@ search_help[] = N_(
254 " this symbol to be visible in the menu (selectable)\n" 257 " this symbol to be visible in the menu (selectable)\n"
255 "o The 'Location:' lines tell where in the menu structure this symbol\n" 258 "o The 'Location:' lines tell where in the menu structure this symbol\n"
256 " is located\n" 259 " is located\n"
257 " A location followed by a [=y] indicate that this is a selectable\n" 260 " A location followed by a [=y] indicates that this is a\n"
258 " menu item - and current value is displayed inside brackets.\n" 261 " selectable menu item - and the current value is displayed inside\n"
262 " brackets.\n"
263 " Press the key in the (#) prefix to jump directly to that\n"
264 " location. You will be returned to the current search results\n"
265 " after exiting this new menu.\n"
259 "o The 'Selects:' line tell what symbol will be automatically\n" 266 "o The 'Selects:' line tell what symbol will be automatically\n"
260 " selected if this symbol is selected (y or m)\n" 267 " selected if this symbol is selected (y or m)\n"
261 "o The 'Selected by' line tell what symbol has selected this symbol\n" 268 "o The 'Selected by' line tell what symbol has selected this symbol\n"
@@ -273,13 +280,15 @@ static struct menu *current_menu;
273static int child_count; 280static int child_count;
274static int single_menu_mode; 281static int single_menu_mode;
275static int show_all_options; 282static int show_all_options;
276static int saved_x, saved_y;
277 283
278static void conf(struct menu *menu); 284static void conf(struct menu *menu, struct menu *active_menu);
279static void conf_choice(struct menu *menu); 285static void conf_choice(struct menu *menu);
280static void conf_string(struct menu *menu); 286static void conf_string(struct menu *menu);
281static void conf_load(void); 287static void conf_load(void);
282static void conf_save(void); 288static void conf_save(void);
289static int show_textbox_ext(const char *title, char *text, int r, int c,
290 int *keys, int *vscroll, int *hscroll,
291 update_text_fn update_text, void *data);
283static void show_textbox(const char *title, const char *text, int r, int c); 292static void show_textbox(const char *title, const char *text, int r, int c);
284static void show_helptext(const char *title, const char *text); 293static void show_helptext(const char *title, const char *text);
285static void show_help(struct menu *menu); 294static void show_help(struct menu *menu);
@@ -302,12 +311,47 @@ static void set_config_filename(const char *config_filename)
302} 311}
303 312
304 313
314struct search_data {
315 struct jk_head *head;
316 struct menu **targets;
317 int *keys;
318};
319
320static void update_text(char *buf, size_t start, size_t end, void *_data)
321{
322 struct search_data *data = _data;
323 struct jump_key *pos;
324 int k = 0;
325
326 CIRCLEQ_FOREACH(pos, data->head, entries) {
327 if (pos->offset >= start && pos->offset < end) {
328 char header[4];
329
330 if (k < JUMP_NB) {
331 int key = '0' + (pos->index % JUMP_NB) + 1;
332
333 sprintf(header, "(%c)", key);
334 data->keys[k] = key;
335 data->targets[k] = pos->target;
336 k++;
337 } else {
338 sprintf(header, " ");
339 }
340
341 memcpy(buf + pos->offset, header, sizeof(header) - 1);
342 }
343 }
344 data->keys[k] = 0;
345}
346
305static void search_conf(void) 347static void search_conf(void)
306{ 348{
307 struct symbol **sym_arr; 349 struct symbol **sym_arr;
308 struct gstr res; 350 struct gstr res;
309 char *dialog_input; 351 char *dialog_input;
310 int dres; 352 int dres, vscroll = 0, hscroll = 0;
353 bool again;
354
311again: 355again:
312 dialog_clear(); 356 dialog_clear();
313 dres = dialog_inputbox(_("Search Configuration Parameter"), 357 dres = dialog_inputbox(_("Search Configuration Parameter"),
@@ -330,10 +374,30 @@ again:
330 dialog_input += strlen(CONFIG_); 374 dialog_input += strlen(CONFIG_);
331 375
332 sym_arr = sym_re_search(dialog_input); 376 sym_arr = sym_re_search(dialog_input);
333 res = get_relations_str(sym_arr); 377 do {
378 struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
379 struct menu *targets[JUMP_NB];
380 int keys[JUMP_NB + 1], i;
381 struct search_data data = {
382 .head = &head,
383 .targets = targets,
384 .keys = keys,
385 };
386
387 res = get_relations_str(sym_arr, &head);
388 dres = show_textbox_ext(_("Search Results"), (char *)
389 str_get(&res), 0, 0, keys, &vscroll,
390 &hscroll, &update_text, (void *)
391 &data);
392 again = false;
393 for (i = 0; i < JUMP_NB && keys[i]; i++)
394 if (dres == keys[i]) {
395 conf(targets[i]->parent, targets[i]);
396 again = true;
397 }
398 str_free(&res);
399 } while (again);
334 free(sym_arr); 400 free(sym_arr);
335 show_textbox(_("Search Results"), str_get(&res), 0, 0);
336 str_free(&res);
337} 401}
338 402
339static void build_conf(struct menu *menu) 403static void build_conf(struct menu *menu)
@@ -514,12 +578,11 @@ conf_childs:
514 indent -= doint; 578 indent -= doint;
515} 579}
516 580
517static void conf(struct menu *menu) 581static void conf(struct menu *menu, struct menu *active_menu)
518{ 582{
519 struct menu *submenu; 583 struct menu *submenu;
520 const char *prompt = menu_get_prompt(menu); 584 const char *prompt = menu_get_prompt(menu);
521 struct symbol *sym; 585 struct symbol *sym;
522 struct menu *active_menu = NULL;
523 int res; 586 int res;
524 int s_scroll = 0; 587 int s_scroll = 0;
525 588
@@ -562,13 +625,13 @@ static void conf(struct menu *menu)
562 if (single_menu_mode) 625 if (single_menu_mode)
563 submenu->data = (void *) (long) !submenu->data; 626 submenu->data = (void *) (long) !submenu->data;
564 else 627 else
565 conf(submenu); 628 conf(submenu, NULL);
566 break; 629 break;
567 case 't': 630 case 't':
568 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes) 631 if (sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)
569 conf_choice(submenu); 632 conf_choice(submenu);
570 else if (submenu->prompt->type == P_MENU) 633 else if (submenu->prompt->type == P_MENU)
571 conf(submenu); 634 conf(submenu, NULL);
572 break; 635 break;
573 case 's': 636 case 's':
574 conf_string(submenu); 637 conf_string(submenu);
@@ -607,7 +670,7 @@ static void conf(struct menu *menu)
607 if (item_is_tag('t')) 670 if (item_is_tag('t'))
608 sym_toggle_tristate_value(sym); 671 sym_toggle_tristate_value(sym);
609 else if (item_is_tag('m')) 672 else if (item_is_tag('m'))
610 conf(submenu); 673 conf(submenu, NULL);
611 break; 674 break;
612 case 7: 675 case 7:
613 search_conf(); 676 search_conf();
@@ -619,10 +682,19 @@ static void conf(struct menu *menu)
619 } 682 }
620} 683}
621 684
622static void show_textbox(const char *title, const char *text, int r, int c) 685static int show_textbox_ext(const char *title, char *text, int r, int c, int
686 *keys, int *vscroll, int *hscroll, update_text_fn
687 update_text, void *data)
623{ 688{
624 dialog_clear(); 689 dialog_clear();
625 dialog_textbox(title, text, r, c); 690 return dialog_textbox(title, text, r, c, keys, vscroll, hscroll,
691 update_text, data);
692}
693
694static void show_textbox(const char *title, const char *text, int r, int c)
695{
696 show_textbox_ext(title, (char *) text, r, c, (int []) {0}, NULL, NULL,
697 NULL, NULL);
626} 698}
627 699
628static void show_helptext(const char *title, const char *text) 700static void show_helptext(const char *title, const char *text)
@@ -862,9 +934,6 @@ int main(int ac, char **av)
862 single_menu_mode = 1; 934 single_menu_mode = 1;
863 } 935 }
864 936
865 initscr();
866
867 getyx(stdscr, saved_y, saved_x);
868 if (init_dialog(NULL)) { 937 if (init_dialog(NULL)) {
869 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n")); 938 fprintf(stderr, N_("Your display is too small to run Menuconfig!\n"));
870 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n")); 939 fprintf(stderr, N_("It must be at least 19 lines by 80 columns.\n"));
@@ -873,7 +942,7 @@ int main(int ac, char **av)
873 942
874 set_config_filename(conf_get_configname()); 943 set_config_filename(conf_get_configname());
875 do { 944 do {
876 conf(&rootmenu); 945 conf(&rootmenu, NULL);
877 res = handle_exit(); 946 res = handle_exit();
878 } while (res == KEY_ESC); 947 } while (res == KEY_ESC);
879 948
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 8c2a97e60faf..a3cade659f89 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -507,10 +507,12 @@ const char *menu_get_help(struct menu *menu)
507 return ""; 507 return "";
508} 508}
509 509
510static void get_prompt_str(struct gstr *r, struct property *prop) 510static void get_prompt_str(struct gstr *r, struct property *prop,
511 struct jk_head *head)
511{ 512{
512 int i, j; 513 int i, j;
513 struct menu *submenu[8], *menu; 514 struct menu *submenu[8], *menu, *location = NULL;
515 struct jump_key *jump;
514 516
515 str_printf(r, _("Prompt: %s\n"), _(prop->text)); 517 str_printf(r, _("Prompt: %s\n"), _(prop->text));
516 str_printf(r, _(" Defined at %s:%d\n"), prop->menu->file->name, 518 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)
521 str_append(r, "\n"); 523 str_append(r, "\n");
522 } 524 }
523 menu = prop->menu->parent; 525 menu = prop->menu->parent;
524 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) 526 for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
527 bool accessible = menu_is_visible(menu);
528
525 submenu[i++] = menu; 529 submenu[i++] = menu;
530 if (location == NULL && accessible)
531 location = menu;
532 }
533 if (head && location) {
534 jump = malloc(sizeof(struct jump_key));
535
536 if (menu_is_visible(prop->menu)) {
537 /*
538 * There is not enough room to put the hint at the
539 * beginning of the "Prompt" line. Put the hint on the
540 * last "Location" line even when it would belong on
541 * the former.
542 */
543 jump->target = prop->menu;
544 } else
545 jump->target = location;
546
547 if (CIRCLEQ_EMPTY(head))
548 jump->index = 0;
549 else
550 jump->index = CIRCLEQ_LAST(head)->index + 1;
551
552 CIRCLEQ_INSERT_TAIL(head, jump, entries);
553 }
554
526 if (i > 0) { 555 if (i > 0) {
527 str_printf(r, _(" Location:\n")); 556 str_printf(r, _(" Location:\n"));
528 for (j = 4; --i >= 0; j += 2) { 557 for (j = 4; --i >= 0; j += 2) {
529 menu = submenu[i]; 558 menu = submenu[i];
530 str_printf(r, "%*c-> %s", j, ' ', _(menu_get_prompt(menu))); 559 if (head && location && menu == location)
560 jump->offset = r->len - 1;
561 str_printf(r, "%*c-> %s", j, ' ',
562 _(menu_get_prompt(menu)));
531 if (menu->sym) { 563 if (menu->sym) {
532 str_printf(r, " (%s [=%s])", menu->sym->name ? 564 str_printf(r, " (%s [=%s])", menu->sym->name ?
533 menu->sym->name : _("<choice>"), 565 menu->sym->name : _("<choice>"),
@@ -538,7 +570,10 @@ static void get_prompt_str(struct gstr *r, struct property *prop)
538 } 570 }
539} 571}
540 572
541void get_symbol_str(struct gstr *r, struct symbol *sym) 573/*
574 * head is optional and may be NULL
575 */
576void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
542{ 577{
543 bool hit; 578 bool hit;
544 struct property *prop; 579 struct property *prop;
@@ -557,7 +592,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
557 } 592 }
558 } 593 }
559 for_all_prompts(sym, prop) 594 for_all_prompts(sym, prop)
560 get_prompt_str(r, prop); 595 get_prompt_str(r, prop, head);
561 hit = false; 596 hit = false;
562 for_all_properties(sym, prop, P_SELECT) { 597 for_all_properties(sym, prop, P_SELECT) {
563 if (!hit) { 598 if (!hit) {
@@ -577,14 +612,14 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
577 str_append(r, "\n\n"); 612 str_append(r, "\n\n");
578} 613}
579 614
580struct gstr get_relations_str(struct symbol **sym_arr) 615struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
581{ 616{
582 struct symbol *sym; 617 struct symbol *sym;
583 struct gstr res = str_new(); 618 struct gstr res = str_new();
584 int i; 619 int i;
585 620
586 for (i = 0; sym_arr && (sym = sym_arr[i]); i++) 621 for (i = 0; sym_arr && (sym = sym_arr[i]); i++)
587 get_symbol_str(&res, sym); 622 get_symbol_str(&res, sym, head);
588 if (!i) 623 if (!i)
589 str_append(&res, _("No matches found.\n")); 624 str_append(&res, _("No matches found.\n"));
590 return res; 625 return res;
@@ -603,5 +638,5 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
603 } 638 }
604 str_printf(help, "%s\n", _(help_text)); 639 str_printf(help, "%s\n", _(help_text));
605 if (sym) 640 if (sym)
606 get_symbol_str(help, sym); 641 get_symbol_str(help, sym, NULL);
607} 642}
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 1704a8562a5d..87d4b15da951 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -721,7 +721,7 @@ again:
721 dialog_input += strlen(CONFIG_); 721 dialog_input += strlen(CONFIG_);
722 722
723 sym_arr = sym_re_search(dialog_input); 723 sym_arr = sym_re_search(dialog_input);
724 res = get_relations_str(sym_arr); 724 res = get_relations_str(sym_arr, NULL);
725 free(sym_arr); 725 free(sym_arr);
726 show_scroll_win(main_window, 726 show_scroll_win(main_window,
727 _("Search Results"), str_get(&res)); 727 _("Search Results"), str_get(&res));
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 8fd107a3fac4..46e7aff80d1a 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -6,6 +6,7 @@ use strict;
6## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ## 6## Copyright (C) 2000, 1 Tim Waugh <twaugh@redhat.com> ##
7## Copyright (C) 2001 Simon Huggins ## 7## Copyright (C) 2001 Simon Huggins ##
8## Copyright (C) 2005-2012 Randy Dunlap ## 8## Copyright (C) 2005-2012 Randy Dunlap ##
9## Copyright (C) 2012 Dan Luedtke ##
9## ## 10## ##
10## #define enhancements by Armin Kuster <akuster@mvista.com> ## 11## #define enhancements by Armin Kuster <akuster@mvista.com> ##
11## Copyright (c) 2000 MontaVista Software, Inc. ## 12## Copyright (c) 2000 MontaVista Software, Inc. ##
@@ -35,6 +36,8 @@ use strict;
35# Small fixes (like spaces vs. \s in regex) 36# Small fixes (like spaces vs. \s in regex)
36# -- Tim Jansen <tim@tjansen.de> 37# -- Tim Jansen <tim@tjansen.de>
37 38
39# 25/07/2012 - Added support for HTML5
40# -- Dan Luedtke <mail@danrl.de>
38 41
39# 42#
40# This will read a 'c' file and scan for embedded comments in the 43# This will read a 'c' file and scan for embedded comments in the
@@ -44,12 +47,16 @@ use strict;
44# Note: This only supports 'c'. 47# Note: This only supports 'c'.
45 48
46# usage: 49# usage:
47# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ] 50# kernel-doc [ -docbook | -html | -html5 | -text | -man | -list ]
48# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile 51# [ -no-doc-sections ]
52# [ -function funcname [ -function funcname ...] ]
53# c file(s)s > outputfile
49# or 54# or
50# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile 55# [ -nofunction funcname [ -function funcname ...] ]
56# c file(s)s > outputfile
51# 57#
52# Set output format using one of -docbook -html -text or -man. Default is man. 58# Set output format using one of -docbook -html -html5 -text or -man.
59# Default is man.
53# The -list format is for internal use by docproc. 60# The -list format is for internal use by docproc.
54# 61#
55# -no-doc-sections 62# -no-doc-sections
@@ -182,6 +189,14 @@ my $local_lt = "\\\\\\\\lt:";
182my $local_gt = "\\\\\\\\gt:"; 189my $local_gt = "\\\\\\\\gt:";
183my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>" 190my $blankline_html = $local_lt . "p" . $local_gt; # was "<p>"
184 191
192# html version 5
193my %highlights_html5 = ( $type_constant, "<span class=\"const\">\$1</span>",
194 $type_func, "<span class=\"func\">\$1</span>",
195 $type_struct_xml, "<span class=\"struct\">\$1</span>",
196 $type_env, "<span class=\"env\">\$1</span>",
197 $type_param, "<span class=\"param\">\$1</span>" );
198my $blankline_html5 = $local_lt . "br /" . $local_gt;
199
185# XML, docbook format 200# XML, docbook format
186my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>", 201my %highlights_xml = ( "([^=])\\\"([^\\\"<]+)\\\"", "\$1<quote>\$2</quote>",
187 $type_constant, "<constant>\$1</constant>", 202 $type_constant, "<constant>\$1</constant>",
@@ -230,6 +245,7 @@ my $dohighlight = "";
230 245
231my $verbose = 0; 246my $verbose = 0;
232my $output_mode = "man"; 247my $output_mode = "man";
248my $output_preformatted = 0;
233my $no_doc_sections = 0; 249my $no_doc_sections = 0;
234my %highlights = %highlights_man; 250my %highlights = %highlights_man;
235my $blankline = $blankline_man; 251my $blankline = $blankline_man;
@@ -280,9 +296,10 @@ my $doc_special = "\@\%\$\&";
280my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start. 296my $doc_start = '^/\*\*\s*$'; # Allow whitespace at end of comment start.
281my $doc_end = '\*/'; 297my $doc_end = '\*/';
282my $doc_com = '\s*\*\s*'; 298my $doc_com = '\s*\*\s*';
299my $doc_com_body = '\s*\* ?';
283my $doc_decl = $doc_com . '(\w+)'; 300my $doc_decl = $doc_com . '(\w+)';
284my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)'; 301my $doc_sect = $doc_com . '([' . $doc_special . ']?[\w\s]+):(.*)';
285my $doc_content = $doc_com . '(.*)'; 302my $doc_content = $doc_com_body . '(.*)';
286my $doc_block = $doc_com . 'DOC:\s*(.*)?'; 303my $doc_block = $doc_com . 'DOC:\s*(.*)?';
287 304
288my %constants; 305my %constants;
@@ -309,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
309 $output_mode = "html"; 326 $output_mode = "html";
310 %highlights = %highlights_html; 327 %highlights = %highlights_html;
311 $blankline = $blankline_html; 328 $blankline = $blankline_html;
329 } elsif ($cmd eq "-html5") {
330 $output_mode = "html5";
331 %highlights = %highlights_html5;
332 $blankline = $blankline_html5;
312 } elsif ($cmd eq "-man") { 333 } elsif ($cmd eq "-man") {
313 $output_mode = "man"; 334 $output_mode = "man";
314 %highlights = %highlights_man; 335 %highlights = %highlights_man;
@@ -351,10 +372,11 @@ while ($ARGV[0] =~ m/^-(.*)/) {
351# continue execution near EOF; 372# continue execution near EOF;
352 373
353sub usage { 374sub usage {
354 print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n"; 375 print "Usage: $0 [ -docbook | -html | -html5 | -text | -man | -list ]\n";
355 print " [ -no-doc-sections ]\n"; 376 print " [ -no-doc-sections ]\n";
356 print " [ -function funcname [ -function funcname ...] ]\n"; 377 print " [ -function funcname [ -function funcname ...] ]\n";
357 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n"; 378 print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
379 print " [ -v ]\n";
358 print " c source file(s) > outputfile\n"; 380 print " c source file(s) > outputfile\n";
359 print " -v : verbose output, more warnings & other info listed\n"; 381 print " -v : verbose output, more warnings & other info listed\n";
360 exit 1; 382 exit 1;
@@ -448,7 +470,8 @@ sub output_highlight {
448# confess "output_highlight got called with no args?\n"; 470# confess "output_highlight got called with no args?\n";
449# } 471# }
450 472
451 if ($output_mode eq "html" || $output_mode eq "xml") { 473 if ($output_mode eq "html" || $output_mode eq "html5" ||
474 $output_mode eq "xml") {
452 $contents = local_unescape($contents); 475 $contents = local_unescape($contents);
453 # convert data read & converted thru xml_escape() into &xyz; format: 476 # convert data read & converted thru xml_escape() into &xyz; format:
454 $contents =~ s/\\\\\\/\&/g; 477 $contents =~ s/\\\\\\/\&/g;
@@ -458,9 +481,19 @@ sub output_highlight {
458 die $@ if $@; 481 die $@ if $@;
459# print STDERR "contents af:$contents\n"; 482# print STDERR "contents af:$contents\n";
460 483
484# strip whitespaces when generating html5
485 if ($output_mode eq "html5") {
486 $contents =~ s/^\s+//;
487 $contents =~ s/\s+$//;
488 }
461 foreach $line (split "\n", $contents) { 489 foreach $line (split "\n", $contents) {
490 if (! $output_preformatted) {
491 $line =~ s/^\s*//;
492 }
462 if ($line eq ""){ 493 if ($line eq ""){
463 print $lineprefix, local_unescape($blankline); 494 if (! $output_preformatted) {
495 print $lineprefix, local_unescape($blankline);
496 }
464 } else { 497 } else {
465 $line =~ s/\\\\\\/\&/g; 498 $line =~ s/\\\\\\/\&/g;
466 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") { 499 if ($output_mode eq "man" && substr($line, 0, 1) eq ".") {
@@ -473,7 +506,7 @@ sub output_highlight {
473 } 506 }
474} 507}
475 508
476#output sections in html 509# output sections in html
477sub output_section_html(%) { 510sub output_section_html(%) {
478 my %args = %{$_[0]}; 511 my %args = %{$_[0]};
479 my $section; 512 my $section;
@@ -633,6 +666,239 @@ sub output_blockhead_html(%) {
633 print "<hr>\n"; 666 print "<hr>\n";
634} 667}
635 668
669# output sections in html5
670sub output_section_html5(%) {
671 my %args = %{$_[0]};
672 my $section;
673
674 foreach $section (@{$args{'sectionlist'}}) {
675 print "<section>\n";
676 print "<h1>$section</h1>\n";
677 print "<p>\n";
678 output_highlight($args{'sections'}{$section});
679 print "</p>\n";
680 print "</section>\n";
681 }
682}
683
684# output enum in html5
685sub output_enum_html5(%) {
686 my %args = %{$_[0]};
687 my ($parameter);
688 my $count;
689 my $html5id;
690
691 $html5id = $args{'enum'};
692 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
693 print "<article class=\"enum\" id=\"enum:". $html5id . "\">";
694 print "<h1>enum " . $args{'enum'} . "</h1>\n";
695 print "<ol class=\"code\">\n";
696 print "<li>";
697 print "<span class=\"keyword\">enum</span> ";
698 print "<span class=\"identifier\">" . $args{'enum'} . "</span> {";
699 print "</li>\n";
700 $count = 0;
701 foreach $parameter (@{$args{'parameterlist'}}) {
702 print "<li class=\"indent\">";
703 print "<span class=\"param\">" . $parameter . "</span>";
704 if ($count != $#{$args{'parameterlist'}}) {
705 $count++;
706 print ",";
707 }
708 print "</li>\n";
709 }
710 print "<li>};</li>\n";
711 print "</ol>\n";
712
713 print "<section>\n";
714 print "<h1>Constants</h1>\n";
715 print "<dl>\n";
716 foreach $parameter (@{$args{'parameterlist'}}) {
717 print "<dt>" . $parameter . "</dt>\n";
718 print "<dd>";
719 output_highlight($args{'parameterdescs'}{$parameter});
720 print "</dd>\n";
721 }
722 print "</dl>\n";
723 print "</section>\n";
724 output_section_html5(@_);
725 print "</article>\n";
726}
727
728# output typedef in html5
729sub output_typedef_html5(%) {
730 my %args = %{$_[0]};
731 my ($parameter);
732 my $count;
733 my $html5id;
734
735 $html5id = $args{'typedef'};
736 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
737 print "<article class=\"typedef\" id=\"typedef:" . $html5id . "\">\n";
738 print "<h1>typedef " . $args{'typedef'} . "</h1>\n";
739
740 print "<ol class=\"code\">\n";
741 print "<li>";
742 print "<span class=\"keyword\">typedef</span> ";
743 print "<span class=\"identifier\">" . $args{'typedef'} . "</span>";
744 print "</li>\n";
745 print "</ol>\n";
746 output_section_html5(@_);
747 print "</article>\n";
748}
749
750# output struct in html5
751sub output_struct_html5(%) {
752 my %args = %{$_[0]};
753 my ($parameter);
754 my $html5id;
755
756 $html5id = $args{'struct'};
757 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
758 print "<article class=\"struct\" id=\"struct:" . $html5id . "\">\n";
759 print "<hgroup>\n";
760 print "<h1>" . $args{'type'} . " " . $args{'struct'} . "</h1>";
761 print "<h2>". $args{'purpose'} . "</h2>\n";
762 print "</hgroup>\n";
763 print "<ol class=\"code\">\n";
764 print "<li>";
765 print "<span class=\"type\">" . $args{'type'} . "</span> ";
766 print "<span class=\"identifier\">" . $args{'struct'} . "</span> {";
767 print "</li>\n";
768 foreach $parameter (@{$args{'parameterlist'}}) {
769 print "<li class=\"indent\">";
770 if ($parameter =~ /^#/) {
771 print "<span class=\"param\">" . $parameter ."</span>\n";
772 print "</li>\n";
773 next;
774 }
775 my $parameter_name = $parameter;
776 $parameter_name =~ s/\[.*//;
777
778 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
779 $type = $args{'parametertypes'}{$parameter};
780 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
781 # pointer-to-function
782 print "<span class=\"type\">$1</span> ";
783 print "<span class=\"param\">$parameter</span>";
784 print "<span class=\"type\">)</span> ";
785 print "(<span class=\"args\">$2</span>);";
786 } elsif ($type =~ m/^(.*?)\s*(:.*)/) {
787 # bitfield
788 print "<span class=\"type\">$1</span> ";
789 print "<span class=\"param\">$parameter</span>";
790 print "<span class=\"bits\">$2</span>;";
791 } else {
792 print "<span class=\"type\">$type</span> ";
793 print "<span class=\"param\">$parameter</span>;";
794 }
795 print "</li>\n";
796 }
797 print "<li>};</li>\n";
798 print "</ol>\n";
799
800 print "<section>\n";
801 print "<h1>Members</h1>\n";
802 print "<dl>\n";
803 foreach $parameter (@{$args{'parameterlist'}}) {
804 ($parameter =~ /^#/) && next;
805
806 my $parameter_name = $parameter;
807 $parameter_name =~ s/\[.*//;
808
809 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
810 print "<dt>" . $parameter . "</dt>\n";
811 print "<dd>";
812 output_highlight($args{'parameterdescs'}{$parameter_name});
813 print "</dd>\n";
814 }
815 print "</dl>\n";
816 print "</section>\n";
817 output_section_html5(@_);
818 print "</article>\n";
819}
820
821# output function in html5
822sub output_function_html5(%) {
823 my %args = %{$_[0]};
824 my ($parameter, $section);
825 my $count;
826 my $html5id;
827
828 $html5id = $args{'function'};
829 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
830 print "<article class=\"function\" id=\"func:". $html5id . "\">\n";
831 print "<hgroup>\n";
832 print "<h1>" . $args{'function'} . "</h1>";
833 print "<h2>" . $args{'purpose'} . "</h2>\n";
834 print "</hgroup>\n";
835 print "<ol class=\"code\">\n";
836 print "<li>";
837 print "<span class=\"type\">" . $args{'functiontype'} . "</span> ";
838 print "<span class=\"identifier\">" . $args{'function'} . "</span> (";
839 print "</li>";
840 $count = 0;
841 foreach $parameter (@{$args{'parameterlist'}}) {
842 print "<li class=\"indent\">";
843 $type = $args{'parametertypes'}{$parameter};
844 if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) {
845 # pointer-to-function
846 print "<span class=\"type\">$1</span> ";
847 print "<span class=\"param\">$parameter</span>";
848 print "<span class=\"type\">)</span> ";
849 print "(<span class=\"args\">$2</span>)";
850 } else {
851 print "<span class=\"type\">$type</span> ";
852 print "<span class=\"param\">$parameter</span>";
853 }
854 if ($count != $#{$args{'parameterlist'}}) {
855 $count++;
856 print ",";
857 }
858 print "</li>\n";
859 }
860 print "<li>)</li>\n";
861 print "</ol>\n";
862
863 print "<section>\n";
864 print "<h1>Arguments</h1>\n";
865 print "<p>\n";
866 print "<dl>\n";
867 foreach $parameter (@{$args{'parameterlist'}}) {
868 my $parameter_name = $parameter;
869 $parameter_name =~ s/\[.*//;
870
871 ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next;
872 print "<dt>" . $parameter . "</dt>\n";
873 print "<dd>";
874 output_highlight($args{'parameterdescs'}{$parameter_name});
875 print "</dd>\n";
876 }
877 print "</dl>\n";
878 print "</section>\n";
879 output_section_html5(@_);
880 print "</article>\n";
881}
882
883# output DOC: block header in html5
884sub output_blockhead_html5(%) {
885 my %args = %{$_[0]};
886 my ($parameter, $section);
887 my $count;
888 my $html5id;
889
890 foreach $section (@{$args{'sectionlist'}}) {
891 $html5id = $section;
892 $html5id =~ s/[^a-zA-Z0-9\-]+/_/g;
893 print "<article class=\"doc\" id=\"doc:". $html5id . "\">\n";
894 print "<h1>$section</h1>\n";
895 print "<p>\n";
896 output_highlight($args{'sections'}{$section});
897 print "</p>\n";
898 }
899 print "</article>\n";
900}
901
636sub output_section_xml(%) { 902sub output_section_xml(%) {
637 my %args = %{$_[0]}; 903 my %args = %{$_[0]};
638 my $section; 904 my $section;
@@ -643,10 +909,12 @@ sub output_section_xml(%) {
643 print "<title>$section</title>\n"; 909 print "<title>$section</title>\n";
644 if ($section =~ m/EXAMPLE/i) { 910 if ($section =~ m/EXAMPLE/i) {
645 print "<informalexample><programlisting>\n"; 911 print "<informalexample><programlisting>\n";
912 $output_preformatted = 1;
646 } else { 913 } else {
647 print "<para>\n"; 914 print "<para>\n";
648 } 915 }
649 output_highlight($args{'sections'}{$section}); 916 output_highlight($args{'sections'}{$section});
917 $output_preformatted = 0;
650 if ($section =~ m/EXAMPLE/i) { 918 if ($section =~ m/EXAMPLE/i) {
651 print "</programlisting></informalexample>\n"; 919 print "</programlisting></informalexample>\n";
652 } else { 920 } else {
@@ -949,10 +1217,12 @@ sub output_blockhead_xml(%) {
949 } 1217 }
950 if ($section =~ m/EXAMPLE/i) { 1218 if ($section =~ m/EXAMPLE/i) {
951 print "<example><para>\n"; 1219 print "<example><para>\n";
1220 $output_preformatted = 1;
952 } else { 1221 } else {
953 print "<para>\n"; 1222 print "<para>\n";
954 } 1223 }
955 output_highlight($args{'sections'}{$section}); 1224 output_highlight($args{'sections'}{$section});
1225 $output_preformatted = 0;
956 if ($section =~ m/EXAMPLE/i) { 1226 if ($section =~ m/EXAMPLE/i) {
957 print "</para></example>\n"; 1227 print "</para></example>\n";
958 } else { 1228 } else {
@@ -1028,10 +1298,12 @@ sub output_function_gnome {
1028 print "<simplesect>\n <title>$section</title>\n"; 1298 print "<simplesect>\n <title>$section</title>\n";
1029 if ($section =~ m/EXAMPLE/i) { 1299 if ($section =~ m/EXAMPLE/i) {
1030 print "<example><programlisting>\n"; 1300 print "<example><programlisting>\n";
1301 $output_preformatted = 1;
1031 } else { 1302 } else {
1032 } 1303 }
1033 print "<para>\n"; 1304 print "<para>\n";
1034 output_highlight($args{'sections'}{$section}); 1305 output_highlight($args{'sections'}{$section});
1306 $output_preformatted = 0;
1035 print "</para>\n"; 1307 print "</para>\n";
1036 if ($section =~ m/EXAMPLE/i) { 1308 if ($section =~ m/EXAMPLE/i) {
1037 print "</programlisting></example>\n"; 1309 print "</programlisting></example>\n";
@@ -2046,6 +2318,9 @@ sub process_file($) {
2046 2318
2047 $section_counter = 0; 2319 $section_counter = 0;
2048 while (<IN>) { 2320 while (<IN>) {
2321 while (s/\\\s*$//) {
2322 $_ .= <IN>;
2323 }
2049 if ($state == 0) { 2324 if ($state == 0) {
2050 if (/$doc_start/o) { 2325 if (/$doc_start/o) {
2051 $state = 1; # next line is always the function name 2326 $state = 1; # next line is always the function name
@@ -2073,7 +2348,7 @@ sub process_file($) {
2073 $descr= $1; 2348 $descr= $1;
2074 $descr =~ s/^\s*//; 2349 $descr =~ s/^\s*//;
2075 $descr =~ s/\s*$//; 2350 $descr =~ s/\s*$//;
2076 $descr =~ s/\s+/ /; 2351 $descr =~ s/\s+/ /g;
2077 $declaration_purpose = xml_escape($descr); 2352 $declaration_purpose = xml_escape($descr);
2078 $in_purpose = 1; 2353 $in_purpose = 1;
2079 } else { 2354 } else {
@@ -2165,6 +2440,7 @@ sub process_file($) {
2165 # Continued declaration purpose 2440 # Continued declaration purpose
2166 chomp($declaration_purpose); 2441 chomp($declaration_purpose);
2167 $declaration_purpose .= " " . xml_escape($1); 2442 $declaration_purpose .= " " . xml_escape($1);
2443 $declaration_purpose =~ s/\s+/ /g;
2168 } else { 2444 } else {
2169 $contents .= $1 . "\n"; 2445 $contents .= $1 . "\n";
2170 } 2446 }
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 68e9f5ed0a6f..0d93856a03f4 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -821,12 +821,15 @@ static const char *section_white_list[] =
821 ".debug*", 821 ".debug*",
822 ".zdebug*", /* Compressed debug sections. */ 822 ".zdebug*", /* Compressed debug sections. */
823 ".GCC-command-line", /* mn10300 */ 823 ".GCC-command-line", /* mn10300 */
824 ".GCC.command.line", /* record-gcc-switches, non mn10300 */
824 ".mdebug*", /* alpha, score, mips etc. */ 825 ".mdebug*", /* alpha, score, mips etc. */
825 ".pdr", /* alpha, score, mips etc. */ 826 ".pdr", /* alpha, score, mips etc. */
826 ".stab*", 827 ".stab*",
827 ".note*", 828 ".note*",
828 ".got*", 829 ".got*",
829 ".toc*", 830 ".toc*",
831 ".xt.prop", /* xtensa */
832 ".xt.lit", /* xtensa */
830 NULL 833 NULL
831}; 834};
832 835
diff --git a/scripts/package/buildtar b/scripts/package/buildtar
index 8a7b15598ea9..62d8234f8787 100644
--- a/scripts/package/buildtar
+++ b/scripts/package/buildtar
@@ -28,15 +28,15 @@ case "${1}" in
28 file_ext="" 28 file_ext=""
29 ;; 29 ;;
30 targz-pkg) 30 targz-pkg)
31 compress="gzip -c9" 31 compress="gzip"
32 file_ext=".gz" 32 file_ext=".gz"
33 ;; 33 ;;
34 tarbz2-pkg) 34 tarbz2-pkg)
35 compress="bzip2 -c9" 35 compress="bzip2"
36 file_ext=".bz2" 36 file_ext=".bz2"
37 ;; 37 ;;
38 tarxz-pkg) 38 tarxz-pkg)
39 compress="xz -c9" 39 compress="xz"
40 file_ext=".xz" 40 file_ext=".xz"
41 ;; 41 ;;
42 *) 42 *)
@@ -109,7 +109,7 @@ esac
109 if tar --owner=root --group=root --help >/dev/null 2>&1; then 109 if tar --owner=root --group=root --help >/dev/null 2>&1; then
110 opts="--owner=root --group=root" 110 opts="--owner=root --group=root"
111 fi 111 fi
112 tar cf - . $opts | ${compress} > "${tarball}${file_ext}" 112 tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}"
113) 113)
114 114
115echo "Tarball successfully created in ${tarball}${file_ext}" 115echo "Tarball successfully created in ${tarball}${file_ext}"
diff --git a/scripts/sign-file b/scripts/sign-file
new file mode 100644
index 000000000000..e58e34e50ac5
--- /dev/null
+++ b/scripts/sign-file
@@ -0,0 +1,115 @@
1#!/bin/sh
2#
3# Sign a module file using the given key.
4#
5# Format: sign-file <key> <x509> <src-file> <dst-file>
6#
7
8scripts=`dirname $0`
9
10CONFIG_MODULE_SIG_SHA512=y
11if [ -r .config ]
12then
13 . ./.config
14fi
15
16key="$1"
17x509="$2"
18src="$3"
19dst="$4"
20
21if [ ! -r "$key" ]
22then
23 echo "Can't read private key" >&2
24 exit 2
25fi
26
27if [ ! -r "$x509" ]
28then
29 echo "Can't read X.509 certificate" >&2
30 exit 2
31fi
32if [ ! -r "$x509.signer" ]
33then
34 echo "Can't read Signer name" >&2
35 exit 2;
36fi
37if [ ! -r "$x509.keyid" ]
38then
39 echo "Can't read Key identifier" >&2
40 exit 2;
41fi
42
43#
44# Signature parameters
45#
46algo=1 # Public-key crypto algorithm: RSA
47hash= # Digest algorithm
48id_type=1 # Identifier type: X.509
49
50#
51# Digest the data
52#
53dgst=
54if [ "$CONFIG_MODULE_SIG_SHA1" = "y" ]
55then
56 prologue="0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14"
57 dgst=-sha1
58 hash=2
59elif [ "$CONFIG_MODULE_SIG_SHA224" = "y" ]
60then
61 prologue="0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1C"
62 dgst=-sha224
63 hash=7
64elif [ "$CONFIG_MODULE_SIG_SHA256" = "y" ]
65then
66 prologue="0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20"
67 dgst=-sha256
68 hash=4
69elif [ "$CONFIG_MODULE_SIG_SHA384" = "y" ]
70then
71 prologue="0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30"
72 dgst=-sha384
73 hash=5
74elif [ "$CONFIG_MODULE_SIG_SHA512" = "y" ]
75then
76 prologue="0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40"
77 dgst=-sha512
78 hash=6
79else
80 echo "$0: Can't determine hash algorithm" >&2
81 exit 2
82fi
83
84(
85perl -e "binmode STDOUT; print pack(\"C*\", $prologue)" || exit $?
86openssl dgst $dgst -binary $src || exit $?
87) >$src.dig || exit $?
88
89#
90# Generate the binary signature, which will be just the integer that comprises
91# the signature with no metadata attached.
92#
93openssl rsautl -sign -inkey $key -keyform PEM -in $src.dig -out $src.sig || exit $?
94signerlen=`stat -c %s $x509.signer`
95keyidlen=`stat -c %s $x509.keyid`
96siglen=`stat -c %s $src.sig`
97
98#
99# Build the signed binary
100#
101(
102 cat $src || exit $?
103 echo '~Module signature appended~' || exit $?
104 cat $x509.signer $x509.keyid || exit $?
105
106 # Preface each signature integer with a 2-byte BE length
107 perl -e "binmode STDOUT; print pack(\"n\", $siglen)" || exit $?
108 cat $src.sig || exit $?
109
110 # Generate the information block
111 perl -e "binmode STDOUT; print pack(\"CCCCCxxxN\", $algo, $hash, $id_type, $signerlen, $keyidlen, $siglen + 2)" || exit $?
112) >$dst~ || exit $?
113
114# Permit in-place signing
115mv $dst~ $dst || exit $?
diff --git a/scripts/tags.sh b/scripts/tags.sh
index cff8faad73d1..79fdafb0d263 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -154,7 +154,9 @@ exuberant()
154 --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ 154 --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
155 --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ 155 --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
156 --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ 156 --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
157 --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' 157 --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \
158 --regex-c='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
159 --regex-c='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
158 160
159 all_kconfigs | xargs $1 -a \ 161 all_kconfigs | xargs $1 -a \
160 --langdef=kconfig --language-force=kconfig \ 162 --langdef=kconfig --language-force=kconfig \
@@ -197,7 +199,9 @@ emacs()
197 --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ 199 --regex='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \
198 --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ 200 --regex='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \
199 --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ 201 --regex='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \
200 --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' 202 --regex='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \
203 --regex='/PCI_OP_READ\(([a-z]*[a-z]).*[1-4]\)/pci_bus_read_config_\1/' \
204 --regex='/PCI_OP_WRITE\(([a-z]*[a-z]).*[1-4]\)/pci_bus_write_config_\1/'
201 205
202 all_kconfigs | xargs $1 -a \ 206 all_kconfigs | xargs $1 -a \
203 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' 207 --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
diff --git a/scripts/x509keyid b/scripts/x509keyid
new file mode 100755
index 000000000000..c8e91a4af385
--- /dev/null
+++ b/scripts/x509keyid
@@ -0,0 +1,268 @@
1#!/usr/bin/perl -w
2#
3# Generate an identifier from an X.509 certificate that can be placed in a
4# module signature to indentify the key to use.
5#
6# Format:
7#
8# ./scripts/x509keyid <x509-cert> <signer's-name> <key-id>
9#
10# We read the DER-encoded X509 certificate and parse it to extract the Subject
11# name and Subject Key Identifier. The provide the data we need to build the
12# certificate identifier.
13#
14# The signer's name part of the identifier is fabricated from the commonName,
15# the organizationName or the emailAddress components of the X.509 subject
16# name and written to the second named file.
17#
18# The subject key ID to select which of that signer's certificates we're
19# intending to use to sign the module is written to the third named file.
20#
21use strict;
22
23my $raw_data;
24
25die "Need three filenames\n" if ($#ARGV != 2);
26
27my $src = $ARGV[0];
28
29open(FD, "<$src") || die $src;
30binmode FD;
31my @st = stat(FD);
32die $src if (!@st);
33read(FD, $raw_data, $st[7]) || die $src;
34close(FD);
35
36my $UNIV = 0 << 6;
37my $APPL = 1 << 6;
38my $CONT = 2 << 6;
39my $PRIV = 3 << 6;
40
41my $CONS = 0x20;
42
43my $BOOLEAN = 0x01;
44my $INTEGER = 0x02;
45my $BIT_STRING = 0x03;
46my $OCTET_STRING = 0x04;
47my $NULL = 0x05;
48my $OBJ_ID = 0x06;
49my $UTF8String = 0x0c;
50my $SEQUENCE = 0x10;
51my $SET = 0x11;
52my $UTCTime = 0x17;
53my $GeneralizedTime = 0x18;
54
55my %OIDs = (
56 pack("CCC", 85, 4, 3) => "commonName",
57 pack("CCC", 85, 4, 6) => "countryName",
58 pack("CCC", 85, 4, 10) => "organizationName",
59 pack("CCC", 85, 4, 11) => "organizationUnitName",
60 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1) => "rsaEncryption",
61 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5) => "sha1WithRSAEncryption",
62 pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1) => "emailAddress",
63 pack("CCC", 85, 29, 35) => "authorityKeyIdentifier",
64 pack("CCC", 85, 29, 14) => "subjectKeyIdentifier",
65 pack("CCC", 85, 29, 19) => "basicConstraints"
66);
67
68###############################################################################
69#
70# Extract an ASN.1 element from a string and return information about it.
71#
72###############################################################################
73sub asn1_extract($$@)
74{
75 my ($cursor, $expected_tag, $optional) = @_;
76
77 return [ -1 ]
78 if ($cursor->[1] == 0 && $optional);
79
80 die $src, ": ", $cursor->[0], ": ASN.1 data underrun (elem ", $cursor->[1], ")\n"
81 if ($cursor->[1] < 2);
82
83 my ($tag, $len) = unpack("CC", substr(${$cursor->[2]}, $cursor->[0], 2));
84
85 if ($expected_tag != -1 && $tag != $expected_tag) {
86 return [ -1 ]
87 if ($optional);
88 die $src, ": ", $cursor->[0], ": ASN.1 unexpected tag (", $tag,
89 " not ", $expected_tag, ")\n";
90 }
91
92 $cursor->[0] += 2;
93 $cursor->[1] -= 2;
94
95 die $src, ": ", $cursor->[0], ": ASN.1 long tag\n"
96 if (($tag & 0x1f) == 0x1f);
97 die $src, ": ", $cursor->[0], ": ASN.1 indefinite length\n"
98 if ($len == 0x80);
99
100 if ($len > 0x80) {
101 my $l = $len - 0x80;
102 die $src, ": ", $cursor->[0], ": ASN.1 data underrun (len len $l)\n"
103 if ($cursor->[1] < $l);
104
105 if ($l == 0x1) {
106 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
107 } elsif ($l = 0x2) {
108 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
109 } elsif ($l = 0x3) {
110 $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
111 $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
112 } elsif ($l = 0x4) {
113 $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
114 } else {
115 die $src, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
116 }
117
118 $cursor->[0] += $l;
119 $cursor->[1] -= $l;
120 }
121
122 die $src, ": ", $cursor->[0], ": ASN.1 data underrun (", $len, ")\n"
123 if ($cursor->[1] < $len);
124
125 my $ret = [ $tag, [ $cursor->[0], $len, $cursor->[2] ] ];
126 $cursor->[0] += $len;
127 $cursor->[1] -= $len;
128
129 return $ret;
130}
131
132###############################################################################
133#
134# Retrieve the data referred to by a cursor
135#
136###############################################################################
137sub asn1_retrieve($)
138{
139 my ($cursor) = @_;
140 my ($offset, $len, $data) = @$cursor;
141 return substr($$data, $offset, $len);
142}
143
144###############################################################################
145#
146# Roughly parse the X.509 certificate
147#
148###############################################################################
149my $cursor = [ 0, length($raw_data), \$raw_data ];
150
151my $cert = asn1_extract($cursor, $UNIV | $CONS | $SEQUENCE);
152my $tbs = asn1_extract($cert->[1], $UNIV | $CONS | $SEQUENCE);
153my $version = asn1_extract($tbs->[1], $CONT | $CONS | 0, 1);
154my $serial_number = asn1_extract($tbs->[1], $UNIV | $INTEGER);
155my $sig_type = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
156my $issuer = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
157my $validity = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
158my $subject = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
159my $key = asn1_extract($tbs->[1], $UNIV | $CONS | $SEQUENCE);
160my $issuer_uid = asn1_extract($tbs->[1], $CONT | $CONS | 1, 1);
161my $subject_uid = asn1_extract($tbs->[1], $CONT | $CONS | 2, 1);
162my $extension_list = asn1_extract($tbs->[1], $CONT | $CONS | 3, 1);
163
164my $subject_key_id = ();
165my $authority_key_id = ();
166
167#
168# Parse the extension list
169#
170if ($extension_list->[0] != -1) {
171 my $extensions = asn1_extract($extension_list->[1], $UNIV | $CONS | $SEQUENCE);
172
173 while ($extensions->[1]->[1] > 0) {
174 my $ext = asn1_extract($extensions->[1], $UNIV | $CONS | $SEQUENCE);
175 my $x_oid = asn1_extract($ext->[1], $UNIV | $OBJ_ID);
176 my $x_crit = asn1_extract($ext->[1], $UNIV | $BOOLEAN, 1);
177 my $x_val = asn1_extract($ext->[1], $UNIV | $OCTET_STRING);
178
179 my $raw_oid = asn1_retrieve($x_oid->[1]);
180 next if (!exists($OIDs{$raw_oid}));
181 my $x_type = $OIDs{$raw_oid};
182
183 my $raw_value = asn1_retrieve($x_val->[1]);
184
185 if ($x_type eq "subjectKeyIdentifier") {
186 my $vcursor = [ 0, length($raw_value), \$raw_value ];
187
188 $subject_key_id = asn1_extract($vcursor, $UNIV | $OCTET_STRING);
189 }
190 }
191}
192
193###############################################################################
194#
195# Determine what we're going to use as the signer's name. In order of
196# preference, take one of: commonName, organizationName or emailAddress.
197#
198###############################################################################
199my $org = "";
200my $cn = "";
201my $email = "";
202
203while ($subject->[1]->[1] > 0) {
204 my $rdn = asn1_extract($subject->[1], $UNIV | $CONS | $SET);
205 my $attr = asn1_extract($rdn->[1], $UNIV | $CONS | $SEQUENCE);
206 my $n_oid = asn1_extract($attr->[1], $UNIV | $OBJ_ID);
207 my $n_val = asn1_extract($attr->[1], -1);
208
209 my $raw_oid = asn1_retrieve($n_oid->[1]);
210 next if (!exists($OIDs{$raw_oid}));
211 my $n_type = $OIDs{$raw_oid};
212
213 my $raw_value = asn1_retrieve($n_val->[1]);
214
215 if ($n_type eq "organizationName") {
216 $org = $raw_value;
217 } elsif ($n_type eq "commonName") {
218 $cn = $raw_value;
219 } elsif ($n_type eq "emailAddress") {
220 $email = $raw_value;
221 }
222}
223
224my $id_name = $email;
225
226if ($org && $cn) {
227 # Don't use the organizationName if the commonName repeats it
228 if (length($org) <= length($cn) &&
229 substr($cn, 0, length($org)) eq $org) {
230 $id_name = $cn;
231 goto got_id_name;
232 }
233
234 # Or a signifcant chunk of it
235 if (length($org) >= 7 &&
236 length($cn) >= 7 &&
237 substr($cn, 0, 7) eq substr($org, 0, 7)) {
238 $id_name = $cn;
239 goto got_id_name;
240 }
241
242 $id_name = $org . ": " . $cn;
243} elsif ($org) {
244 $id_name = $org;
245} elsif ($cn) {
246 $id_name = $cn;
247}
248
249got_id_name:
250
251###############################################################################
252#
253# Output the signer's name and the key identifier that we're going to include
254# in module signatures.
255#
256###############################################################################
257die $src, ": ", "X.509: Couldn't find the Subject Key Identifier extension\n"
258 if (!$subject_key_id);
259
260my $id_key_id = asn1_retrieve($subject_key_id->[1]);
261
262open(OUTFD, ">$ARGV[1]") || die $ARGV[1];
263print OUTFD $id_name;
264close OUTFD || die $ARGV[1];
265
266open(OUTFD, ">$ARGV[2]") || die $ARGV[2];
267print OUTFD $id_key_id;
268close OUTFD || die $ARGV[2];