Merge commit 'v2.6.37-rc1' into kbuild/kbuild
This commit is contained in:
@@ -11,6 +11,7 @@ hostprogs-$(CONFIG_KALLSYMS) += kallsyms
|
||||
hostprogs-$(CONFIG_LOGO) += pnmtologo
|
||||
hostprogs-$(CONFIG_VT) += conmakehash
|
||||
hostprogs-$(CONFIG_IKCONFIG) += bin2c
|
||||
hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
|
||||
|
||||
always := $(hostprogs-y) $(hostprogs-m)
|
||||
|
||||
|
@@ -209,12 +209,23 @@ cmd_modversions = \
|
||||
endif
|
||||
|
||||
ifdef CONFIG_FTRACE_MCOUNT_RECORD
|
||||
ifdef BUILD_C_RECORDMCOUNT
|
||||
# Due to recursion, we must skip empty.o.
|
||||
# The empty.o file is created in the make process in order to determine
|
||||
# the target endianness and word size. It is made before all other C
|
||||
# files, including recordmcount.
|
||||
cmd_record_mcount = if [ $(@) != "scripts/mod/empty.o" ]; then \
|
||||
$(objtree)/scripts/recordmcount "$(@)"; \
|
||||
fi;
|
||||
else
|
||||
cmd_record_mcount = set -e ; perl $(srctree)/scripts/recordmcount.pl "$(ARCH)" \
|
||||
"$(if $(CONFIG_CPU_BIG_ENDIAN),big,little)" \
|
||||
"$(if $(CONFIG_64BIT),64,32)" \
|
||||
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC)" "$(LD)" "$(NM)" "$(RM)" "$(MV)" \
|
||||
"$(OBJDUMP)" "$(OBJCOPY)" "$(CC) $(KBUILD_CFLAGS)" \
|
||||
"$(LD)" "$(NM)" "$(RM)" "$(MV)" \
|
||||
"$(if $(part-of-module),1,0)" "$(@)";
|
||||
endif
|
||||
endif
|
||||
|
||||
define rule_cc_o_c
|
||||
$(call echo-cmd,checksrc) $(cmd_checksrc) \
|
||||
|
@@ -3,7 +3,6 @@
|
||||
#
|
||||
# header-y - list files to be installed. They are preprocessed
|
||||
# to remove __KERNEL__ section of the file
|
||||
# unifdef-y - Same as header-y. Obsolete
|
||||
# objhdr-y - Same as header-y but for generated files
|
||||
#
|
||||
# ==========================================================================
|
||||
@@ -20,7 +19,7 @@ include scripts/Kbuild.include
|
||||
|
||||
install := $(INSTALL_HDR_PATH)/$(_dst)
|
||||
|
||||
header-y := $(sort $(header-y) $(unifdef-y))
|
||||
header-y := $(sort $(header-y))
|
||||
subdirs := $(patsubst %/,%,$(filter %/, $(header-y)))
|
||||
header-y := $(filter-out %/, $(header-y))
|
||||
|
||||
|
3
scripts/Makefile.help
Normal file
3
scripts/Makefile.help
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
checker-help:
|
||||
@echo ' coccicheck - Check with Coccinelle.'
|
@@ -101,14 +101,6 @@ basename_flags = -D"KBUILD_BASENAME=KBUILD_STR($(call name-fix,$(basetarget)))"
|
||||
modname_flags = $(if $(filter 1,$(words $(modname))),\
|
||||
-D"KBUILD_MODNAME=KBUILD_STR($(call name-fix,$(modname)))")
|
||||
|
||||
#hash values
|
||||
ifdef CONFIG_DYNAMIC_DEBUG
|
||||
debug_flags = -D"DEBUG_HASH=$(shell ./scripts/basic/hash djb2 $(@D)$(modname))"\
|
||||
-D"DEBUG_HASH2=$(shell ./scripts/basic/hash r5 $(@D)$(modname))"
|
||||
else
|
||||
debug_flags =
|
||||
endif
|
||||
|
||||
orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \
|
||||
$(ccflags-y) $(CFLAGS_$(basetarget).o)
|
||||
_c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags))
|
||||
@@ -154,8 +146,7 @@ endif
|
||||
|
||||
c_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
|
||||
$(__c_flags) $(modkern_cflags) \
|
||||
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags) \
|
||||
$(debug_flags)
|
||||
-D"KBUILD_STR(s)=\#s" $(basename_flags) $(modname_flags)
|
||||
|
||||
a_flags = -Wp,-MD,$(depfile) $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \
|
||||
$(__a_flags) $(modkern_aflags)
|
||||
|
@@ -9,7 +9,7 @@
|
||||
# fixdep: Used to generate dependency information during build process
|
||||
# docproc: Used in Documentation/DocBook
|
||||
|
||||
hostprogs-y := fixdep docproc hash
|
||||
hostprogs-y := fixdep docproc
|
||||
always := $(hostprogs-y)
|
||||
|
||||
# fixdep is needed to compile other host programs
|
||||
|
@@ -34,12 +34,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
@@ -54,6 +56,7 @@ typedef void FILEONLY(char * file);
|
||||
FILEONLY *internalfunctions;
|
||||
FILEONLY *externalfunctions;
|
||||
FILEONLY *symbolsonly;
|
||||
FILEONLY *findall;
|
||||
|
||||
typedef void FILELINE(char * file, char * line);
|
||||
FILELINE * singlefunctions;
|
||||
@@ -65,12 +68,30 @@ FILELINE * docsection;
|
||||
#define KERNELDOCPATH "scripts/"
|
||||
#define KERNELDOC "kernel-doc"
|
||||
#define DOCBOOK "-docbook"
|
||||
#define LIST "-list"
|
||||
#define FUNCTION "-function"
|
||||
#define NOFUNCTION "-nofunction"
|
||||
#define NODOCSECTIONS "-no-doc-sections"
|
||||
|
||||
static char *srctree, *kernsrctree;
|
||||
|
||||
static char **all_list = NULL;
|
||||
static int all_list_len = 0;
|
||||
|
||||
static void consume_symbol(const char *sym)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < all_list_len; i++) {
|
||||
if (!all_list[i])
|
||||
continue;
|
||||
if (strcmp(sym, all_list[i]))
|
||||
continue;
|
||||
all_list[i] = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage (void)
|
||||
{
|
||||
fprintf(stderr, "Usage: docproc {doc|depend} file\n");
|
||||
@@ -248,6 +269,7 @@ static void docfunctions(char * filename, char * type)
|
||||
struct symfile * sym = &symfilelist[i];
|
||||
for (j=0; j < sym->symbolcnt; j++) {
|
||||
vec[idx++] = type;
|
||||
consume_symbol(sym->symbollist[j].name);
|
||||
vec[idx++] = sym->symbollist[j].name;
|
||||
}
|
||||
}
|
||||
@@ -287,6 +309,11 @@ static void singfunc(char * filename, char * line)
|
||||
vec[idx++] = &line[i];
|
||||
}
|
||||
}
|
||||
for (i = 0; i < idx; i++) {
|
||||
if (strcmp(vec[i], FUNCTION))
|
||||
continue;
|
||||
consume_symbol(vec[i + 1]);
|
||||
}
|
||||
vec[idx++] = filename;
|
||||
vec[idx] = NULL;
|
||||
exec_kernel_doc(vec);
|
||||
@@ -306,6 +333,13 @@ static void docsect(char *filename, char *line)
|
||||
if (*s == '\n')
|
||||
*s = '\0';
|
||||
|
||||
if (asprintf(&s, "DOC: %s", line) < 0) {
|
||||
perror("asprintf");
|
||||
exit(1);
|
||||
}
|
||||
consume_symbol(s);
|
||||
free(s);
|
||||
|
||||
vec[0] = KERNELDOC;
|
||||
vec[1] = DOCBOOK;
|
||||
vec[2] = FUNCTION;
|
||||
@@ -315,6 +349,84 @@ static void docsect(char *filename, char *line)
|
||||
exec_kernel_doc(vec);
|
||||
}
|
||||
|
||||
static void find_all_symbols(char *filename)
|
||||
{
|
||||
char *vec[4]; /* kerneldoc -list file NULL */
|
||||
pid_t pid;
|
||||
int ret, i, count, start;
|
||||
char real_filename[PATH_MAX + 1];
|
||||
int pipefd[2];
|
||||
char *data, *str;
|
||||
size_t data_len = 0;
|
||||
|
||||
vec[0] = KERNELDOC;
|
||||
vec[1] = LIST;
|
||||
vec[2] = filename;
|
||||
vec[3] = NULL;
|
||||
|
||||
if (pipe(pipefd)) {
|
||||
perror("pipe");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
switch (pid=fork()) {
|
||||
case -1:
|
||||
perror("fork");
|
||||
exit(1);
|
||||
case 0:
|
||||
close(pipefd[0]);
|
||||
dup2(pipefd[1], 1);
|
||||
memset(real_filename, 0, sizeof(real_filename));
|
||||
strncat(real_filename, kernsrctree, PATH_MAX);
|
||||
strncat(real_filename, "/" KERNELDOCPATH KERNELDOC,
|
||||
PATH_MAX - strlen(real_filename));
|
||||
execvp(real_filename, vec);
|
||||
fprintf(stderr, "exec ");
|
||||
perror(real_filename);
|
||||
exit(1);
|
||||
default:
|
||||
close(pipefd[1]);
|
||||
data = malloc(4096);
|
||||
do {
|
||||
while ((ret = read(pipefd[0],
|
||||
data + data_len,
|
||||
4096)) > 0) {
|
||||
data_len += ret;
|
||||
data = realloc(data, data_len + 4096);
|
||||
}
|
||||
} while (ret == -EAGAIN);
|
||||
if (ret != 0) {
|
||||
perror("read");
|
||||
exit(1);
|
||||
}
|
||||
waitpid(pid, &ret ,0);
|
||||
}
|
||||
if (WIFEXITED(ret))
|
||||
exitstatus |= WEXITSTATUS(ret);
|
||||
else
|
||||
exitstatus = 0xff;
|
||||
|
||||
count = 0;
|
||||
/* poor man's strtok, but with counting */
|
||||
for (i = 0; i < data_len; i++) {
|
||||
if (data[i] == '\n') {
|
||||
count++;
|
||||
data[i] = '\0';
|
||||
}
|
||||
}
|
||||
start = all_list_len;
|
||||
all_list_len += count;
|
||||
all_list = realloc(all_list, sizeof(char *) * all_list_len);
|
||||
str = data;
|
||||
for (i = 0; i < data_len && start != all_list_len; i++) {
|
||||
if (data[i] == '\0') {
|
||||
all_list[start] = str;
|
||||
str = data + i + 1;
|
||||
start++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse file, calling action specific functions for:
|
||||
* 1) Lines containing !E
|
||||
@@ -322,7 +434,8 @@ static void docsect(char *filename, char *line)
|
||||
* 3) Lines containing !D
|
||||
* 4) Lines containing !F
|
||||
* 5) Lines containing !P
|
||||
* 6) Default lines - lines not matching the above
|
||||
* 6) Lines containing !C
|
||||
* 7) Default lines - lines not matching the above
|
||||
*/
|
||||
static void parse_file(FILE *infile)
|
||||
{
|
||||
@@ -365,6 +478,12 @@ static void parse_file(FILE *infile)
|
||||
s++;
|
||||
docsection(line + 2, s);
|
||||
break;
|
||||
case 'C':
|
||||
while (*s && !isspace(*s)) s++;
|
||||
*s = '\0';
|
||||
if (findall)
|
||||
findall(line+2);
|
||||
break;
|
||||
default:
|
||||
defaultline(line);
|
||||
}
|
||||
@@ -380,6 +499,7 @@ static void parse_file(FILE *infile)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
FILE * infile;
|
||||
int i;
|
||||
|
||||
srctree = getenv("SRCTREE");
|
||||
if (!srctree)
|
||||
@@ -415,6 +535,7 @@ int main(int argc, char *argv[])
|
||||
symbolsonly = find_export_symbols;
|
||||
singlefunctions = noaction2;
|
||||
docsection = noaction2;
|
||||
findall = find_all_symbols;
|
||||
parse_file(infile);
|
||||
|
||||
/* Rewind to start from beginning of file again */
|
||||
@@ -425,8 +546,16 @@ int main(int argc, char *argv[])
|
||||
symbolsonly = printline;
|
||||
singlefunctions = singfunc;
|
||||
docsection = docsect;
|
||||
findall = NULL;
|
||||
|
||||
parse_file(infile);
|
||||
|
||||
for (i = 0; i < all_list_len; i++) {
|
||||
if (!all_list[i])
|
||||
continue;
|
||||
fprintf(stderr, "Warning: didn't use docs for %s\n",
|
||||
all_list[i]);
|
||||
}
|
||||
}
|
||||
else if (strcmp("depend", argv[1]) == 0)
|
||||
{
|
||||
@@ -439,6 +568,7 @@ int main(int argc, char *argv[])
|
||||
symbolsonly = adddep;
|
||||
singlefunctions = adddep2;
|
||||
docsection = adddep2;
|
||||
findall = adddep;
|
||||
parse_file(infile);
|
||||
printf("\n");
|
||||
}
|
||||
|
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 Red Hat, Inc., Jason Baron <jbaron@redhat.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define DYNAMIC_DEBUG_HASH_BITS 6
|
||||
|
||||
static const char *program;
|
||||
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: %s <djb2|r5> <modname>\n", program);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* djb2 hashing algorithm by Dan Bernstein. From:
|
||||
* http://www.cse.yorku.ca/~oz/hash.html
|
||||
*/
|
||||
|
||||
static unsigned int djb2_hash(char *str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
|
||||
c = *str;
|
||||
while (c) {
|
||||
hash = ((hash << 5) + hash) + c;
|
||||
c = *++str;
|
||||
}
|
||||
return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
|
||||
}
|
||||
|
||||
static unsigned int r5_hash(char *str)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
int c;
|
||||
|
||||
c = *str;
|
||||
while (c) {
|
||||
hash = (hash + (c << 4) + (c >> 4)) * 11;
|
||||
c = *++str;
|
||||
}
|
||||
return (unsigned int)(hash & ((1 << DYNAMIC_DEBUG_HASH_BITS) - 1));
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
program = argv[0];
|
||||
|
||||
if (argc != 3)
|
||||
usage();
|
||||
if (!strcmp(argv[1], "djb2"))
|
||||
printf("%d\n", djb2_hash(argv[2]));
|
||||
else if (!strcmp(argv[1], "r5"))
|
||||
printf("%d\n", r5_hash(argv[2]));
|
||||
else
|
||||
usage();
|
||||
exit(0);
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@ find $paths -name '*.[chS]' -o -name 'Makefile' -o -name 'Makefile*[^~]'| while
|
||||
do
|
||||
# Output the bare Kconfig variable and the filename; the _MODULE part at
|
||||
# the end is not removed here (would need perl an not-hungry regexp for that).
|
||||
sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Z_]\+\).*!\2 '$i'!p' < $i
|
||||
sed -ne 's!^.*\<\(UML_\)\?CONFIG_\([0-9A-Za-z_]\+\).*!\2 '$i'!p' < $i
|
||||
done | \
|
||||
# Smart "sort|uniq" implemented in awk and tuned to collect the names of all
|
||||
# files which use a given symbol
|
||||
|
@@ -2,7 +2,7 @@
|
||||
# (c) 2001, Dave Jones. (the file handling bit)
|
||||
# (c) 2005, Joel Schopp <jschopp@austin.ibm.com> (the ugly bit)
|
||||
# (c) 2007,2008, Andy Whitcroft <apw@uk.ibm.com> (new conditions, test suite)
|
||||
# (c) 2008,2009, Andy Whitcroft <apw@canonical.com>
|
||||
# (c) 2008-2010 Andy Whitcroft <apw@canonical.com>
|
||||
# Licensed under the terms of the GNU GPL License version 2
|
||||
|
||||
use strict;
|
||||
@@ -10,7 +10,7 @@ use strict;
|
||||
my $P = $0;
|
||||
$P =~ s@.*/@@g;
|
||||
|
||||
my $V = '0.30';
|
||||
my $V = '0.31';
|
||||
|
||||
use Getopt::Long qw(:config no_auto_abbrev);
|
||||
|
||||
@@ -103,6 +103,8 @@ for my $key (keys %debug) {
|
||||
die "$@" if ($@);
|
||||
}
|
||||
|
||||
my $rpt_cleaners = 0;
|
||||
|
||||
if ($terse) {
|
||||
$emacs = 1;
|
||||
$quiet++;
|
||||
@@ -150,6 +152,20 @@ our $Sparse = qr{
|
||||
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
|
||||
our $Attribute = qr{
|
||||
const|
|
||||
__percpu|
|
||||
__nocast|
|
||||
__safe|
|
||||
__bitwise__|
|
||||
__packed__|
|
||||
__packed2__|
|
||||
__naked|
|
||||
__maybe_unused|
|
||||
__always_unused|
|
||||
__noreturn|
|
||||
__used|
|
||||
__cold|
|
||||
__noclone|
|
||||
__deprecated|
|
||||
__read_mostly|
|
||||
__kprobes|
|
||||
__(?:mem|cpu|dev|)(?:initdata|initconst|init\b)|
|
||||
@@ -195,7 +211,7 @@ our $typeTypedefs = qr{(?x:
|
||||
our $logFunctions = qr{(?x:
|
||||
printk|
|
||||
pr_(debug|dbg|vdbg|devel|info|warning|err|notice|alert|crit|emerg|cont)|
|
||||
dev_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
|
||||
(dev|netdev|netif)_(printk|dbg|vdbg|info|warn|err|notice|alert|crit|emerg|WARN)|
|
||||
WARN|
|
||||
panic
|
||||
)};
|
||||
@@ -224,6 +240,12 @@ our @modifierList = (
|
||||
qr{fastcall},
|
||||
);
|
||||
|
||||
our $allowed_asm_includes = qr{(?x:
|
||||
irq|
|
||||
memory
|
||||
)};
|
||||
# memory.h: ARM has a custom one
|
||||
|
||||
sub build_types {
|
||||
my $mods = "(?x: \n" . join("|\n ", @modifierList) . "\n)";
|
||||
my $all = "(?x: \n" . join("|\n ", @typeList) . "\n)";
|
||||
@@ -552,6 +574,9 @@ sub ctx_statement_block {
|
||||
$type = ($level != 0)? '{' : '';
|
||||
|
||||
if ($level == 0) {
|
||||
if (substr($blk, $off + 1, 1) eq ';') {
|
||||
$off++;
|
||||
}
|
||||
last;
|
||||
}
|
||||
}
|
||||
@@ -666,15 +691,15 @@ sub ctx_block_get {
|
||||
$blk .= $rawlines[$line];
|
||||
|
||||
# Handle nested #if/#else.
|
||||
if ($rawlines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
|
||||
if ($lines[$line] =~ /^.\s*#\s*(?:ifndef|ifdef|if)\s/) {
|
||||
push(@stack, $level);
|
||||
} elsif ($rawlines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
|
||||
} elsif ($lines[$line] =~ /^.\s*#\s*(?:else|elif)\b/) {
|
||||
$level = $stack[$#stack - 1];
|
||||
} elsif ($rawlines[$line] =~ /^.\s*#\s*endif\b/) {
|
||||
} elsif ($lines[$line] =~ /^.\s*#\s*endif\b/) {
|
||||
$level = pop(@stack);
|
||||
}
|
||||
|
||||
foreach my $c (split(//, $rawlines[$line])) {
|
||||
foreach my $c (split(//, $lines[$line])) {
|
||||
##print "C<$c>L<$level><$open$close>O<$off>\n";
|
||||
if ($off > 0) {
|
||||
$off--;
|
||||
@@ -834,7 +859,12 @@ sub annotate_values {
|
||||
$av_preprocessor = 0;
|
||||
}
|
||||
|
||||
} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\()/) {
|
||||
} elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
|
||||
print "CAST($1)\n" if ($dbg_values > 1);
|
||||
push(@av_paren_type, $type);
|
||||
$type = 'C';
|
||||
|
||||
} elsif ($cur =~ /^($Type)\s*(?:$Ident|,|\)|\(|\s*$)/) {
|
||||
print "DECLARE($1)\n" if ($dbg_values > 1);
|
||||
$type = 'T';
|
||||
|
||||
@@ -1299,7 +1329,11 @@ sub process {
|
||||
$here = "#$realline: " if ($file);
|
||||
|
||||
# extract the filename as it passes
|
||||
if ($line=~/^\+\+\+\s+(\S+)/) {
|
||||
if ($line =~ /^diff --git.*?(\S+)$/) {
|
||||
$realfile = $1;
|
||||
$realfile =~ s@^([^/]*)/@@;
|
||||
|
||||
} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
|
||||
$realfile = $1;
|
||||
$realfile =~ s@^([^/]*)/@@;
|
||||
|
||||
@@ -1323,6 +1357,14 @@ sub process {
|
||||
|
||||
$cnt_lines++ if ($realcnt != 0);
|
||||
|
||||
# Check for incorrect file permissions
|
||||
if ($line =~ /^new (file )?mode.*[7531]\d{0,2}$/) {
|
||||
my $permhere = $here . "FILE: $realfile\n";
|
||||
if ($realfile =~ /(Makefile|Kconfig|\.c|\.h|\.S|\.tmpl)$/) {
|
||||
ERROR("do not set execute permissions for source files\n" . $permhere);
|
||||
}
|
||||
}
|
||||
|
||||
#check the patch for a signoff:
|
||||
if ($line =~ /^\s*signed-off-by:/i) {
|
||||
# This is a signoff, if ugly, so do not double report.
|
||||
@@ -1380,21 +1422,38 @@ sub process {
|
||||
} elsif ($rawline =~ /^\+.*\S\s+$/ || $rawline =~ /^\+\s+$/) {
|
||||
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
|
||||
ERROR("trailing whitespace\n" . $herevet);
|
||||
$rpt_cleaners = 1;
|
||||
}
|
||||
|
||||
# check for Kconfig help text having a real description
|
||||
# Only applies when adding the entry originally, after that we do not have
|
||||
# sufficient context to determine whether it is indeed long enough.
|
||||
if ($realfile =~ /Kconfig/ &&
|
||||
$line =~ /\+?\s*(---)?help(---)?$/) {
|
||||
$line =~ /\+\s*(?:---)?help(?:---)?$/) {
|
||||
my $length = 0;
|
||||
for (my $l = $linenr; defined($lines[$l]); $l++) {
|
||||
my $f = $lines[$l];
|
||||
my $cnt = $realcnt;
|
||||
my $ln = $linenr + 1;
|
||||
my $f;
|
||||
my $is_end = 0;
|
||||
while ($cnt > 0 && defined $lines[$ln - 1]) {
|
||||
$f = $lines[$ln - 1];
|
||||
$cnt-- if ($lines[$ln - 1] !~ /^-/);
|
||||
$is_end = $lines[$ln - 1] =~ /^\+/;
|
||||
$ln++;
|
||||
|
||||
next if ($f =~ /^-/);
|
||||
$f =~ s/^.//;
|
||||
$f =~ s/#.*//;
|
||||
$f =~ s/^\s+//;
|
||||
next if ($f =~ /^$/);
|
||||
last if ($f =~ /^\s*config\s/);
|
||||
if ($f =~ /^\s*config\s/) {
|
||||
$is_end = 1;
|
||||
last;
|
||||
}
|
||||
$length++;
|
||||
}
|
||||
WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($length < 4);
|
||||
WARN("please write a paragraph that describes the config symbol fully\n" . $herecurr) if ($is_end && $length < 4);
|
||||
#print "is_end<$is_end> length<$length>\n";
|
||||
}
|
||||
|
||||
# check we are in a valid source file if not then ignore this hunk
|
||||
@@ -1403,7 +1462,8 @@ sub process {
|
||||
#80 column limit
|
||||
if ($line =~ /^\+/ && $prevrawline !~ /\/\*\*/ &&
|
||||
$rawline !~ /^.\s*\*\s*\@$Ident\s/ &&
|
||||
$line !~ /^\+\s*$logFunctions\s*\(\s*(?:KERN_\S+\s*)?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ &&
|
||||
!($line =~ /^\+\s*$logFunctions\s*\(\s*(?:(KERN_\S+\s*|[^"]*))?"[X\t]*"\s*(?:,|\)\s*;)\s*$/ ||
|
||||
$line =~ /^\+\s*"[^"]*"\s*(?:\s*|,|\)\s*;)\s*$/) &&
|
||||
$length > 80)
|
||||
{
|
||||
WARN("line over 80 characters\n" . $herecurr);
|
||||
@@ -1440,6 +1500,7 @@ sub process {
|
||||
$rawline =~ /^\+\s* \s*/) {
|
||||
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
|
||||
ERROR("code indent should use tabs where possible\n" . $herevet);
|
||||
$rpt_cleaners = 1;
|
||||
}
|
||||
|
||||
# check for space before tabs.
|
||||
@@ -1448,6 +1509,16 @@ sub process {
|
||||
WARN("please, no space before tabs\n" . $herevet);
|
||||
}
|
||||
|
||||
# check for spaces at the beginning of a line.
|
||||
# Exceptions:
|
||||
# 1) within comments
|
||||
# 2) indented preprocessor commands
|
||||
# 3) hanging labels
|
||||
if ($rawline =~ /^\+ / && $line !~ /\+ *(?:$;|#|$Ident:)/) {
|
||||
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
|
||||
WARN("please, no spaces at the start of a line\n" . $herevet);
|
||||
}
|
||||
|
||||
# check we are in a valid C source file if not then ignore this hunk
|
||||
next if ($realfile !~ /\.(h|c)$/);
|
||||
|
||||
@@ -1581,7 +1652,7 @@ sub process {
|
||||
|
||||
if ($ctx !~ /{\s*/ && defined($lines[$ctx_ln -1]) && $lines[$ctx_ln - 1] =~ /^\+\s*{/) {
|
||||
ERROR("that open brace { should be on the previous line\n" .
|
||||
"$here\n$ctx\n$lines[$ctx_ln - 1]\n");
|
||||
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
|
||||
}
|
||||
if ($level == 0 && $pre_ctx !~ /}\s*while\s*\($/ &&
|
||||
$ctx =~ /\)\s*\;\s*$/ &&
|
||||
@@ -1590,7 +1661,7 @@ sub process {
|
||||
my ($nlength, $nindent) = line_stats($lines[$ctx_ln - 1]);
|
||||
if ($nindent > $indent) {
|
||||
WARN("trailing semicolon indicates no statements, indent implies otherwise\n" .
|
||||
"$here\n$ctx\n$lines[$ctx_ln - 1]\n");
|
||||
"$here\n$ctx\n$rawlines[$ctx_ln - 1]\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1751,8 +1822,17 @@ sub process {
|
||||
!defined $suppress_export{$realline_next} &&
|
||||
($lines[$realline_next - 1] =~ /EXPORT_SYMBOL.*\((.*)\)/ ||
|
||||
$lines[$realline_next - 1] =~ /EXPORT_UNUSED_SYMBOL.*\((.*)\)/)) {
|
||||
# Handle definitions which produce identifiers with
|
||||
# a prefix:
|
||||
# XXX(foo);
|
||||
# EXPORT_SYMBOL(something_foo);
|
||||
my $name = $1;
|
||||
if ($stat !~ /(?:
|
||||
if ($stat =~ /^.([A-Z_]+)\s*\(\s*($Ident)/ &&
|
||||
$name =~ /^${Ident}_$2/) {
|
||||
#print "FOO C name<$name>\n";
|
||||
$suppress_export{$realline_next} = 1;
|
||||
|
||||
} elsif ($stat !~ /(?:
|
||||
\n.}\s*$|
|
||||
^.DEFINE_$Ident\(\Q$name\E\)|
|
||||
^.DECLARE_$Ident\(\Q$name\E\)|
|
||||
@@ -1778,9 +1858,9 @@ sub process {
|
||||
WARN("EXPORT_SYMBOL(foo); should immediately follow its function/variable\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for external initialisers.
|
||||
# check for global initialisers.
|
||||
if ($line =~ /^.$Type\s*$Ident\s*(?:\s+$Modifier)*\s*=\s*(0|NULL|false)\s*;/) {
|
||||
ERROR("do not initialise externals to 0 or NULL\n" .
|
||||
ERROR("do not initialise globals to 0 or NULL\n" .
|
||||
$herecurr);
|
||||
}
|
||||
# check for static initialisers.
|
||||
@@ -1789,6 +1869,23 @@ sub process {
|
||||
$herecurr);
|
||||
}
|
||||
|
||||
# check for static const char * arrays.
|
||||
if ($line =~ /\bstatic\s+const\s+char\s*\*\s*(\w+)\s*\[\s*\]\s*=\s*/) {
|
||||
WARN("static const char * array should probably be static const char * const\n" .
|
||||
$herecurr);
|
||||
}
|
||||
|
||||
# check for static char foo[] = "bar" declarations.
|
||||
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
|
||||
WARN("static char array declaration should probably be static const char\n" .
|
||||
$herecurr);
|
||||
}
|
||||
|
||||
# check for declarations of struct pci_device_id
|
||||
if ($line =~ /\bstruct\s+pci_device_id\s+\w+\s*\[\s*\]\s*\=\s*\{/) {
|
||||
WARN("Use DEFINE_PCI_DEVICE_TABLE for struct pci_device_id\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for new typedefs, only function parameters and sparse annotations
|
||||
# make sense.
|
||||
if ($line =~ /\btypedef\s/ &&
|
||||
@@ -1882,6 +1979,11 @@ sub process {
|
||||
ERROR("open brace '{' following $1 go on the same line\n" . $hereprev);
|
||||
}
|
||||
|
||||
# missing space after union, struct or enum definition
|
||||
if ($line =~ /^.\s*(?:typedef\s+)?(enum|union|struct)(?:\s+$Ident)?(?:\s+$Ident)?[=\{]/) {
|
||||
WARN("missing space after $1 definition\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for spacing round square brackets; allowed:
|
||||
# 1. with a type on the left -- int [] a;
|
||||
# 2. at the beginning of a line for slice initialisers -- [0...10] = 5,
|
||||
@@ -2159,21 +2261,29 @@ sub process {
|
||||
my $value = $2;
|
||||
|
||||
# Flatten any parentheses
|
||||
$value =~ s/\)\(/\) \(/g;
|
||||
$value =~ s/\(/ \(/g;
|
||||
$value =~ s/\)/\) /g;
|
||||
while ($value =~ s/\[[^\{\}]*\]/1/ ||
|
||||
$value !~ /(?:$Ident|-?$Constant)\s*
|
||||
$Compare\s*
|
||||
(?:$Ident|-?$Constant)/x &&
|
||||
$value =~ s/\([^\(\)]*\)/1/) {
|
||||
}
|
||||
|
||||
if ($value =~ /^(?:$Ident|-?$Constant)$/) {
|
||||
#print "value<$value>\n";
|
||||
if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
|
||||
ERROR("return is not a function, parentheses are not required\n" . $herecurr);
|
||||
|
||||
} elsif ($spacing !~ /\s+/) {
|
||||
ERROR("space required before the open parenthesis '('\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
# Return of what appears to be an errno should normally be -'ve
|
||||
if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
|
||||
my $name = $1;
|
||||
if ($name ne 'EOF' && $name ne 'ERROR') {
|
||||
WARN("return of an errno should typically be -ve (return -$1)\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
|
||||
# Need a space before open parenthesis after if, while etc
|
||||
if ($line=~/\b(if|while|for|switch)\(/) {
|
||||
@@ -2308,7 +2418,7 @@ sub process {
|
||||
my $checkfile = "include/linux/$file";
|
||||
if (-f "$root/$checkfile" &&
|
||||
$realfile ne $checkfile &&
|
||||
$1 ne 'irq')
|
||||
$1 !~ /$allowed_asm_includes/)
|
||||
{
|
||||
if ($realfile =~ m{^arch/}) {
|
||||
CHK("Consider using #include <linux/$file> instead of <asm/$file>\n" . $herecurr);
|
||||
@@ -2392,8 +2502,8 @@ sub process {
|
||||
\.$Ident\s*=\s*|
|
||||
^\"|\"$
|
||||
}x;
|
||||
#print "REST<$rest> dstat<$dstat>\n";
|
||||
if ($rest ne '') {
|
||||
#print "REST<$rest> dstat<$dstat> ctx<$ctx>\n";
|
||||
if ($rest ne '' && $rest ne ',') {
|
||||
if ($rest !~ /while\s*\(/ &&
|
||||
$dstat !~ /$exceptions/)
|
||||
{
|
||||
@@ -2570,6 +2680,21 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# prefer usleep_range over udelay
|
||||
if ($line =~ /\budelay\s*\(\s*(\w+)\s*\)/) {
|
||||
# ignore udelay's < 10, however
|
||||
if (! (($1 =~ /(\d+)/) && ($1 < 10)) ) {
|
||||
CHK("usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $line);
|
||||
}
|
||||
}
|
||||
|
||||
# warn about unexpectedly long msleep's
|
||||
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
|
||||
if ($1 < 20) {
|
||||
WARN("msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $line);
|
||||
}
|
||||
}
|
||||
|
||||
# warn about #ifdefs in C files
|
||||
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
|
||||
# print "#ifdef in C files should be avoided\n";
|
||||
@@ -2669,12 +2794,8 @@ sub process {
|
||||
WARN("__func__ should be used instead of gcc specific __FUNCTION__\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for semaphores used as mutexes
|
||||
if ($line =~ /^.\s*(DECLARE_MUTEX|init_MUTEX)\s*\(/) {
|
||||
WARN("mutexes are preferred for single holder semaphores\n" . $herecurr);
|
||||
}
|
||||
# check for semaphores used as mutexes
|
||||
if ($line =~ /^.\s*init_MUTEX_LOCKED\s*\(/) {
|
||||
# check for semaphores initialized locked
|
||||
if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
|
||||
WARN("consider using a completion\n" . $herecurr);
|
||||
|
||||
}
|
||||
@@ -2807,6 +2928,15 @@ sub process {
|
||||
print "\n" if ($quiet == 0);
|
||||
}
|
||||
|
||||
if ($quiet == 0) {
|
||||
# If there were whitespace errors which cleanpatch can fix
|
||||
# then suggest that.
|
||||
if ($rpt_cleaners) {
|
||||
print "NOTE: whitespace errors detected, you may wish to use scripts/cleanpatch or\n";
|
||||
print " scripts/cleanfile\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ($clean == 1 && $quiet == 0) {
|
||||
print "$vname has no obvious style problems and is ready for submission.\n"
|
||||
}
|
||||
|
@@ -183,7 +183,6 @@ cat << EOF
|
||||
#define __IGNORE_ustat /* statfs */
|
||||
#define __IGNORE_utime /* utimes */
|
||||
#define __IGNORE_vfork /* clone */
|
||||
#define __IGNORE_wait4 /* waitid */
|
||||
|
||||
/* sync_file_range had a stupid ABI. Allow sync_file_range2 instead */
|
||||
#ifdef __NR_sync_file_range2
|
||||
|
106
scripts/coccicheck
Executable file
106
scripts/coccicheck
Executable file
@@ -0,0 +1,106 @@
|
||||
#!/bin/sh
|
||||
|
||||
SPATCH="`which ${SPATCH:=spatch}`"
|
||||
|
||||
if [ "$C" = "1" -o "$C" = "2" ]; then
|
||||
ONLINE=1
|
||||
|
||||
# This requires Coccinelle >= 0.2.3
|
||||
# FLAGS="-ignore_unknown_options -very_quiet"
|
||||
# OPTIONS=$*
|
||||
|
||||
# Workaround for Coccinelle < 0.2.3
|
||||
FLAGS="-I $srctree/include -very_quiet"
|
||||
shift $(( $# - 1 ))
|
||||
OPTIONS=$1
|
||||
else
|
||||
ONLINE=0
|
||||
FLAGS="-very_quiet"
|
||||
OPTIONS="-dir $srctree"
|
||||
fi
|
||||
|
||||
if [ ! -x "$SPATCH" ]; then
|
||||
echo 'spatch is part of the Coccinelle project and is available at http://coccinelle.lip6.fr/'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "" ] ; then
|
||||
if [ "$ONLINE" = "0" ] ; then
|
||||
echo 'You have not explicitly specified the mode to use. Using default "chain" mode.'
|
||||
echo 'All available modes will be tried (in that order): patch, report, context, org'
|
||||
echo 'You can specify the mode with "make coccicheck MODE=<mode>"'
|
||||
fi
|
||||
MODE="chain"
|
||||
elif [ "$MODE" = "report" -o "$MODE" = "org" ] ; then
|
||||
FLAGS="$FLAGS -no_show_diff"
|
||||
fi
|
||||
|
||||
if [ "$ONLINE" = "0" ] ; then
|
||||
echo ''
|
||||
echo 'Please check for false positives in the output before submitting a patch.'
|
||||
echo 'When using "patch" mode, carefully review the patch before submitting it.'
|
||||
echo ''
|
||||
fi
|
||||
|
||||
coccinelle () {
|
||||
COCCI="$1"
|
||||
|
||||
OPT=`grep "Option" $COCCI | cut -d':' -f2`
|
||||
|
||||
# The option '-parse_cocci' can be used to syntactically check the SmPL files.
|
||||
#
|
||||
# $SPATCH -D $MODE $FLAGS -parse_cocci $COCCI $OPT > /dev/null
|
||||
|
||||
if [ "$ONLINE" = "0" ] ; then
|
||||
|
||||
FILE=`echo $COCCI | sed "s|$srctree/||"`
|
||||
|
||||
echo "Processing `basename $COCCI`"
|
||||
echo "with option(s) \"$OPT\""
|
||||
echo ''
|
||||
echo 'Message example to submit a patch:'
|
||||
|
||||
sed -ne 's|^///||p' $COCCI
|
||||
|
||||
if [ "$MODE" = "patch" ] ; then
|
||||
echo ' The semantic patch that makes this change is available'
|
||||
elif [ "$MODE" = "report" ] ; then
|
||||
echo ' The semantic patch that makes this report is available'
|
||||
elif [ "$MODE" = "context" ] ; then
|
||||
echo ' The semantic patch that spots this code is available'
|
||||
elif [ "$MODE" = "org" ] ; then
|
||||
echo ' The semantic patch that makes this Org report is available'
|
||||
else
|
||||
echo ' The semantic patch that makes this output is available'
|
||||
fi
|
||||
echo " in $FILE."
|
||||
echo ''
|
||||
echo ' More information about semantic patching is available at'
|
||||
echo ' http://coccinelle.lip6.fr/'
|
||||
echo ''
|
||||
|
||||
if [ "`sed -ne 's|^//#||p' $COCCI`" ] ; then
|
||||
echo 'Semantic patch information:'
|
||||
sed -ne 's|^//#||p' $COCCI
|
||||
echo ''
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "chain" ] ; then
|
||||
$SPATCH -D patch $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
|
||||
$SPATCH -D report $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || \
|
||||
$SPATCH -D context $FLAGS -sp_file $COCCI $OPT $OPTIONS || \
|
||||
$SPATCH -D org $FLAGS -sp_file $COCCI $OPT $OPTIONS -no_show_diff || exit 1
|
||||
else
|
||||
$SPATCH -D $MODE $FLAGS -sp_file $COCCI $OPT $OPTIONS || exit 1
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
if [ "$COCCI" = "" ] ; then
|
||||
for f in `find $srctree/scripts/coccinelle/ -name '*.cocci' -type f | sort`; do
|
||||
coccinelle $f
|
||||
done
|
||||
else
|
||||
coccinelle $COCCI
|
||||
fi
|
67
scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci
Normal file
67
scripts/coccinelle/api/alloc/drop_kmalloc_cast.cocci
Normal file
@@ -0,0 +1,67 @@
|
||||
///
|
||||
/// Casting (void *) value returned by kmalloc is useless
|
||||
/// as mentioned in Documentation/CodingStyle, Chap 14.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: 2009,2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Options: -no_includes -include_headers
|
||||
//
|
||||
// Keywords: kmalloc, kzalloc, kcalloc
|
||||
// Version min: < 2.6.12 kmalloc
|
||||
// Version min: < 2.6.12 kcalloc
|
||||
// Version min: 2.6.14 kzalloc
|
||||
//
|
||||
|
||||
virtual context
|
||||
virtual patch
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For context mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@depends on context@
|
||||
type T;
|
||||
@@
|
||||
|
||||
* (T *)
|
||||
\(kmalloc\|kzalloc\|kcalloc\)(...)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For patch mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@depends on patch@
|
||||
type T;
|
||||
@@
|
||||
|
||||
- (T *)
|
||||
\(kmalloc\|kzalloc\|kcalloc\)(...)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For org and report mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@r depends on org || report@
|
||||
type T;
|
||||
position p;
|
||||
@@
|
||||
|
||||
(T@p *)\(kmalloc\|kzalloc\|kcalloc\)(...)
|
||||
|
||||
@script:python depends on org@
|
||||
p << r.p;
|
||||
t << r.T;
|
||||
@@
|
||||
|
||||
coccilib.org.print_safe_todo(p[0], t)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r.p;
|
||||
t << r.T;
|
||||
@@
|
||||
|
||||
msg="WARNING: casting value returned by k[cmz]alloc to (%s *) is useless." % (t)
|
||||
coccilib.report.print_report(p[0], msg)
|
86
scripts/coccinelle/api/alloc/kzalloc-simple.cocci
Normal file
86
scripts/coccinelle/api/alloc/kzalloc-simple.cocci
Normal file
@@ -0,0 +1,86 @@
|
||||
///
|
||||
/// Use kzalloc rather than kmalloc followed by memset with 0
|
||||
///
|
||||
/// This considers some simple cases that are common and easy to validate
|
||||
/// Note in particular that there are no ...s in the rule, so all of the
|
||||
/// matched code has to be contiguous
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2009-2010 Julia Lawall, Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2009-2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/rules/kzalloc.html
|
||||
// Options: -no_includes -include_headers
|
||||
//
|
||||
// Keywords: kmalloc, kzalloc
|
||||
// Version min: < 2.6.12 kmalloc
|
||||
// Version min: 2.6.14 kzalloc
|
||||
//
|
||||
|
||||
virtual context
|
||||
virtual patch
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For context mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@depends on context@
|
||||
type T, T2;
|
||||
expression x;
|
||||
expression E1,E2;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
* x = (T)kmalloc(E1,E2);
|
||||
if ((x==NULL) || ...) S
|
||||
* memset((T2)x,0,E1);
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For patch mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@depends on patch@
|
||||
type T, T2;
|
||||
expression x;
|
||||
expression E1,E2;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
- x = (T)kmalloc(E1,E2);
|
||||
+ x = kzalloc(E1,E2);
|
||||
if ((x==NULL) || ...) S
|
||||
- memset((T2)x,0,E1);
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For org mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@r depends on org || report@
|
||||
type T, T2;
|
||||
expression x;
|
||||
expression E1,E2;
|
||||
statement S;
|
||||
position p;
|
||||
@@
|
||||
|
||||
x = (T)kmalloc@p(E1,E2);
|
||||
if ((x==NULL) || ...) S
|
||||
memset((T2)x,0,E1);
|
||||
|
||||
@script:python depends on org@
|
||||
p << r.p;
|
||||
x << r.x;
|
||||
@@
|
||||
|
||||
msg="%s" % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
coccilib.org.print_todo(p[0], msg_safe)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r.p;
|
||||
x << r.x;
|
||||
@@
|
||||
|
||||
msg="WARNING: kzalloc should be used for %s, instead of kmalloc/memset" % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
56
scripts/coccinelle/api/err_cast.cocci
Normal file
56
scripts/coccinelle/api/err_cast.cocci
Normal file
@@ -0,0 +1,56 @@
|
||||
///
|
||||
/// Use ERR_CAST inlined function instead of ERR_PTR(PTR_ERR(...))
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Options:
|
||||
//
|
||||
// Keywords: ERR_PTR, PTR_ERR, ERR_CAST
|
||||
// Version min: 2.6.25
|
||||
//
|
||||
|
||||
virtual context
|
||||
virtual patch
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
|
||||
@ depends on context && !patch && !org && !report@
|
||||
expression x;
|
||||
@@
|
||||
|
||||
* ERR_PTR(PTR_ERR(x))
|
||||
|
||||
@ depends on !context && patch && !org && !report @
|
||||
expression x;
|
||||
@@
|
||||
|
||||
- ERR_PTR(PTR_ERR(x))
|
||||
+ ERR_CAST(x)
|
||||
|
||||
@r depends on !context && !patch && (org || report)@
|
||||
expression x;
|
||||
position p;
|
||||
@@
|
||||
|
||||
ERR_PTR@p(PTR_ERR(x))
|
||||
|
||||
@script:python depends on org@
|
||||
p << r.p;
|
||||
x << r.x;
|
||||
@@
|
||||
|
||||
msg="WARNING ERR_CAST can be used with %s" % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
coccilib.org.print_todo(p[0], msg_safe)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r.p;
|
||||
x << r.x;
|
||||
@@
|
||||
|
||||
msg="WARNING: ERR_CAST can be used with %s" % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
39
scripts/coccinelle/api/kstrdup.cocci
Normal file
39
scripts/coccinelle/api/kstrdup.cocci
Normal file
@@ -0,0 +1,39 @@
|
||||
/// Use kstrdup rather than duplicating its implementation
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
expression from,to;
|
||||
expression flag,E1,E2;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
- to = kmalloc(strlen(from) + 1,flag);
|
||||
+ to = kstrdup(from, flag);
|
||||
... when != \(from = E1 \| to = E1 \)
|
||||
if (to==NULL || ...) S
|
||||
... when != \(from = E2 \| to = E2 \)
|
||||
- strcpy(to, from);
|
||||
|
||||
@@
|
||||
expression x,from,to;
|
||||
expression flag,E1,E2,E3;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
- x = strlen(from) + 1;
|
||||
... when != \( x = E1 \| from = E1 \)
|
||||
- to = \(kmalloc\|kzalloc\)(x,flag);
|
||||
+ to = kstrdup(from, flag);
|
||||
... when != \(x = E2 \| from = E2 \| to = E2 \)
|
||||
if (to==NULL || ...) S
|
||||
... when != \(x = E3 \| from = E3 \| to = E3 \)
|
||||
- memcpy(to, from, x);
|
40
scripts/coccinelle/api/memdup.cocci
Normal file
40
scripts/coccinelle/api/memdup.cocci
Normal file
@@ -0,0 +1,40 @@
|
||||
/// Use kmemdup rather than duplicating its implementation
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@r1@
|
||||
expression from,to;
|
||||
expression flag;
|
||||
position p;
|
||||
@@
|
||||
|
||||
to = \(kmalloc@p\|kzalloc@p\)(strlen(from) + 1,flag);
|
||||
|
||||
@r2@
|
||||
expression x,from,to;
|
||||
expression flag,E1;
|
||||
position p;
|
||||
@@
|
||||
|
||||
x = strlen(from) + 1;
|
||||
... when != \( x = E1 \| from = E1 \)
|
||||
to = \(kmalloc@p\|kzalloc@p\)(x,flag);
|
||||
|
||||
@@
|
||||
expression from,to,size,flag;
|
||||
position p != {r1.p,r2.p};
|
||||
statement S;
|
||||
@@
|
||||
|
||||
- to = \(kmalloc@p\|kzalloc@p\)(size,flag);
|
||||
+ to = kmemdup(from,size,flag);
|
||||
if (to==NULL || ...) S
|
||||
- memcpy(to, from, size);
|
35
scripts/coccinelle/api/memdup_user.cocci
Normal file
35
scripts/coccinelle/api/memdup_user.cocci
Normal file
@@ -0,0 +1,35 @@
|
||||
/// Use kmemdup_user rather than duplicating its implementation
|
||||
/// This is a little bit restricted to reduce false positives
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
expression from,to,size,flag;
|
||||
position p;
|
||||
identifier l1,l2;
|
||||
@@
|
||||
|
||||
- to = \(kmalloc@p\|kzalloc@p\)(size,flag);
|
||||
+ to = memdup_user(from,size);
|
||||
if (
|
||||
- to==NULL
|
||||
+ IS_ERR(to)
|
||||
|| ...) {
|
||||
<+... when != goto l1;
|
||||
- -ENOMEM
|
||||
+ PTR_ERR(to)
|
||||
...+>
|
||||
}
|
||||
- if (copy_from_user(to, from, size) != 0) {
|
||||
- <+... when != goto l2;
|
||||
- -EFAULT
|
||||
- ...+>
|
||||
- }
|
93
scripts/coccinelle/api/resource_size.cocci
Normal file
93
scripts/coccinelle/api/resource_size.cocci
Normal file
@@ -0,0 +1,93 @@
|
||||
///
|
||||
/// Use resource_size function on resource object
|
||||
/// instead of explicit computation.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2009, 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2009, 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2009, 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Options:
|
||||
//
|
||||
// Keywords: resource_size
|
||||
// Version min: 2.6.27 resource_size
|
||||
//
|
||||
|
||||
virtual context
|
||||
virtual patch
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For context mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@r_context depends on context && !patch && !org@
|
||||
struct resource *res;
|
||||
@@
|
||||
|
||||
* (res->end - res->start) + 1
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For patch mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
@r_patch depends on !context && patch && !org@
|
||||
struct resource *res;
|
||||
@@
|
||||
|
||||
- (res->end - res->start) + 1
|
||||
+ resource_size(res)
|
||||
|
||||
//----------------------------------------------------------
|
||||
// For org mode
|
||||
//----------------------------------------------------------
|
||||
|
||||
|
||||
@r_org depends on !context && !patch && (org || report)@
|
||||
struct resource *res;
|
||||
position p;
|
||||
@@
|
||||
|
||||
(res->end@p - res->start) + 1
|
||||
|
||||
@rbad_org depends on !context && !patch && (org || report)@
|
||||
struct resource *res;
|
||||
position p != r_org.p;
|
||||
@@
|
||||
|
||||
res->end@p - res->start
|
||||
|
||||
@script:python depends on org@
|
||||
p << r_org.p;
|
||||
x << r_org.res;
|
||||
@@
|
||||
|
||||
msg="ERROR with %s" % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
coccilib.org.print_todo(p[0], msg_safe)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r_org.p;
|
||||
x << r_org.res;
|
||||
@@
|
||||
|
||||
msg="ERROR: Missing resource_size with %s" % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
||||
|
||||
@script:python depends on org@
|
||||
p << rbad_org.p;
|
||||
x << rbad_org.res;
|
||||
@@
|
||||
|
||||
msg="WARNING with %s" % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
coccilib.org.print_todo(p[0], msg_safe)
|
||||
|
||||
@script:python depends on report@
|
||||
p << rbad_org.p;
|
||||
x << rbad_org.res;
|
||||
@@
|
||||
|
||||
msg="WARNING: Suspicious code. resource_size is maybe missing with %s" % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
117
scripts/coccinelle/free/kfree.cocci
Normal file
117
scripts/coccinelle/free/kfree.cocci
Normal file
@@ -0,0 +1,117 @@
|
||||
/// Find a use after free.
|
||||
//# Values of variables may imply that some
|
||||
//# execution paths are not possible, resulting in false positives.
|
||||
//# Another source of false positives are macros such as
|
||||
//# SCTP_DBG_OBJCNT_DEC that do not actually evaluate their argument
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@free@
|
||||
expression E;
|
||||
position p1;
|
||||
@@
|
||||
|
||||
kfree@p1(E)
|
||||
|
||||
@print expression@
|
||||
constant char *c;
|
||||
expression free.E,E2;
|
||||
type T;
|
||||
position p;
|
||||
identifier f;
|
||||
@@
|
||||
|
||||
(
|
||||
f(...,c,...,(T)E@p,...)
|
||||
|
|
||||
E@p == E2
|
||||
|
|
||||
E@p != E2
|
||||
|
|
||||
!E@p
|
||||
|
|
||||
E@p || ...
|
||||
)
|
||||
|
||||
@sz@
|
||||
expression free.E;
|
||||
position p;
|
||||
@@
|
||||
|
||||
sizeof(<+...E@p...+>)
|
||||
|
||||
@loop exists@
|
||||
expression E;
|
||||
identifier l;
|
||||
position ok;
|
||||
@@
|
||||
|
||||
while (1) { ...
|
||||
kfree@ok(E)
|
||||
... when != break;
|
||||
when != goto l;
|
||||
when forall
|
||||
}
|
||||
|
||||
@r exists@
|
||||
expression free.E, subE<=free.E, E2;
|
||||
expression E1;
|
||||
iterator iter;
|
||||
statement S;
|
||||
position free.p1!=loop.ok,p2!={print.p,sz.p};
|
||||
@@
|
||||
|
||||
kfree@p1(E,...)
|
||||
...
|
||||
(
|
||||
iter(...,subE,...) S // no use
|
||||
|
|
||||
list_remove_head(E1,subE,...)
|
||||
|
|
||||
subE = E2
|
||||
|
|
||||
subE++
|
||||
|
|
||||
++subE
|
||||
|
|
||||
--subE
|
||||
|
|
||||
subE--
|
||||
|
|
||||
&subE
|
||||
|
|
||||
BUG(...)
|
||||
|
|
||||
BUG_ON(...)
|
||||
|
|
||||
return_VALUE(...)
|
||||
|
|
||||
return_ACPI_STATUS(...)
|
||||
|
|
||||
E@p2 // bad use
|
||||
)
|
||||
|
||||
@script:python depends on org@
|
||||
p1 << free.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
cocci.print_main("kfree",p1)
|
||||
cocci.print_secs("ref",p2)
|
||||
|
||||
@script:python depends on report@
|
||||
p1 << free.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
msg = "reference preceded by free on line %s" % (p1[0].line)
|
||||
coccilib.report.print_report(p2[0],msg)
|
64
scripts/coccinelle/iterators/fen.cocci
Normal file
64
scripts/coccinelle/iterators/fen.cocci
Normal file
@@ -0,0 +1,64 @@
|
||||
/// These iterators only exit normally when the loop cursor is NULL, so there
|
||||
/// is no point to call of_node_put on the final value.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
iterator name for_each_node_by_name;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
@@
|
||||
|
||||
for_each_node_by_name(np,...) {
|
||||
... when != break;
|
||||
when != goto l;
|
||||
}
|
||||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
iterator name for_each_node_by_type;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
@@
|
||||
|
||||
for_each_node_by_type(np,...) {
|
||||
... when != break;
|
||||
when != goto l;
|
||||
}
|
||||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
iterator name for_each_compatible_node;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
@@
|
||||
|
||||
for_each_compatible_node(np,...) {
|
||||
... when != break;
|
||||
when != goto l;
|
||||
}
|
||||
... when != np = E
|
||||
- of_node_put(np);
|
||||
|
||||
@@
|
||||
iterator name for_each_matching_node;
|
||||
expression np,E;
|
||||
identifier l;
|
||||
@@
|
||||
|
||||
for_each_matching_node(np,...) {
|
||||
... when != break;
|
||||
when != goto l;
|
||||
}
|
||||
... when != np = E
|
||||
- of_node_put(np);
|
58
scripts/coccinelle/iterators/itnull.cocci
Normal file
58
scripts/coccinelle/iterators/itnull.cocci
Normal file
@@ -0,0 +1,58 @@
|
||||
/// Many iterators have the property that the first argument is always bound
|
||||
/// to a real list element, never NULL. False positives arise for some
|
||||
/// iterators that do not have this property, or in cases when the loop
|
||||
/// cursor is reassigned. The latter should only happen when the matched
|
||||
/// code is on the way to a loop exit (break, goto, or return).
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
iterator I;
|
||||
expression x,E,E1,E2;
|
||||
statement S,S1,S2;
|
||||
@@
|
||||
|
||||
I(x,...) { <...
|
||||
(
|
||||
- if (x == NULL && ...) S
|
||||
|
|
||||
- if (x != NULL || ...)
|
||||
S
|
||||
|
|
||||
- (x == NULL) ||
|
||||
E
|
||||
|
|
||||
- (x != NULL) &&
|
||||
E
|
||||
|
|
||||
- (x == NULL && ...) ? E1 :
|
||||
E2
|
||||
|
|
||||
- (x != NULL || ...) ?
|
||||
E1
|
||||
- : E2
|
||||
|
|
||||
- if (x == NULL && ...) S1 else
|
||||
S2
|
||||
|
|
||||
- if (x != NULL || ...)
|
||||
S1
|
||||
- else S2
|
||||
|
|
||||
+ BAD(
|
||||
x == NULL
|
||||
+ )
|
||||
|
|
||||
+ BAD(
|
||||
x != NULL
|
||||
+ )
|
||||
)
|
||||
...> }
|
62
scripts/coccinelle/iterators/list_entry_update.cocci
Normal file
62
scripts/coccinelle/iterators/list_entry_update.cocci
Normal file
@@ -0,0 +1,62 @@
|
||||
/// list_for_each_entry uses its first argument to get from one element of
|
||||
/// the list to the next, so it is usually not a good idea to reassign it.
|
||||
/// The first rule finds such a reassignment and the second rule checks
|
||||
/// that there is a path from the reassignment back to the top of the loop.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r@
|
||||
iterator name list_for_each_entry;
|
||||
expression x,E;
|
||||
position p1,p2;
|
||||
@@
|
||||
|
||||
list_for_each_entry@p1(x,...) { <... x =@p2 E ...> }
|
||||
|
||||
@depends on context && !org && !report@
|
||||
expression x,E;
|
||||
position r.p1,r.p2;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
*x =@p2 E
|
||||
...
|
||||
list_for_each_entry@p1(x,...) S
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@back depends on (org || report) && !context exists@
|
||||
expression x,E;
|
||||
position r.p1,r.p2;
|
||||
statement S;
|
||||
@@
|
||||
|
||||
x =@p2 E
|
||||
...
|
||||
list_for_each_entry@p1(x,...) S
|
||||
|
||||
@script:python depends on back && org@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
cocci.print_main("iterator",p1)
|
||||
cocci.print_secs("update",p2)
|
||||
|
||||
@script:python depends on back && report@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
msg = "iterator with update on line %s" % (p2[0].line)
|
||||
coccilib.report.print_report(p1[0],msg)
|
74
scripts/coccinelle/locks/call_kern.cocci
Normal file
74
scripts/coccinelle/locks/call_kern.cocci
Normal file
@@ -0,0 +1,74 @@
|
||||
/// Find functions that refer to GFP_KERNEL but are called with locks held.
|
||||
/// The proposed change of converting the GFP_KERNEL is not necessarily the
|
||||
/// correct one. It may be desired to unlock the lock, or to not call the
|
||||
/// function under the lock in the first place.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@gfp exists@
|
||||
identifier fn;
|
||||
position p;
|
||||
@@
|
||||
|
||||
fn(...) {
|
||||
... when != read_unlock_irq(...)
|
||||
when != write_unlock_irq(...)
|
||||
when != read_unlock_irqrestore(...)
|
||||
when != write_unlock_irqrestore(...)
|
||||
when != spin_unlock(...)
|
||||
when != spin_unlock_irq(...)
|
||||
when != spin_unlock_irqrestore(...)
|
||||
when != local_irq_enable(...)
|
||||
when any
|
||||
GFP_KERNEL@p
|
||||
... when any
|
||||
}
|
||||
|
||||
@locked@
|
||||
identifier gfp.fn;
|
||||
@@
|
||||
|
||||
(
|
||||
read_lock_irq
|
||||
|
|
||||
write_lock_irq
|
||||
|
|
||||
read_lock_irqsave
|
||||
|
|
||||
write_lock_irqsave
|
||||
|
|
||||
spin_lock
|
||||
|
|
||||
spin_trylock
|
||||
|
|
||||
spin_lock_irq
|
||||
|
|
||||
spin_lock_irqsave
|
||||
|
|
||||
local_irq_disable
|
||||
)
|
||||
(...)
|
||||
... when != read_unlock_irq(...)
|
||||
when != write_unlock_irq(...)
|
||||
when != read_unlock_irqrestore(...)
|
||||
when != write_unlock_irqrestore(...)
|
||||
when != spin_unlock(...)
|
||||
when != spin_unlock_irq(...)
|
||||
when != spin_unlock_irqrestore(...)
|
||||
when != local_irq_enable(...)
|
||||
fn(...)
|
||||
|
||||
@depends on locked@
|
||||
position gfp.p;
|
||||
@@
|
||||
|
||||
- GFP_KERNEL@p
|
||||
+ GFP_ATOMIC
|
92
scripts/coccinelle/locks/double_lock.cocci
Normal file
92
scripts/coccinelle/locks/double_lock.cocci
Normal file
@@ -0,0 +1,92 @@
|
||||
/// Find double locks. False positives may occur when some paths cannot
|
||||
/// occur at execution, due to the values of variables, and when there is
|
||||
/// an intervening function call that releases the lock.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@locked@
|
||||
position p1;
|
||||
expression E1;
|
||||
position p;
|
||||
@@
|
||||
|
||||
(
|
||||
mutex_lock@p1
|
||||
|
|
||||
mutex_trylock@p1
|
||||
|
|
||||
spin_lock@p1
|
||||
|
|
||||
spin_trylock@p1
|
||||
|
|
||||
read_lock@p1
|
||||
|
|
||||
read_trylock@p1
|
||||
|
|
||||
write_lock@p1
|
||||
|
|
||||
write_trylock@p1
|
||||
) (E1@p,...);
|
||||
|
||||
@balanced@
|
||||
position p1 != locked.p1;
|
||||
position locked.p;
|
||||
identifier lock,unlock;
|
||||
expression x <= locked.E1;
|
||||
expression E,locked.E1;
|
||||
expression E2;
|
||||
@@
|
||||
|
||||
if (E) {
|
||||
<+... when != E1
|
||||
lock(E1@p,...)
|
||||
...+>
|
||||
}
|
||||
... when != E1
|
||||
when != \(x = E2\|&x\)
|
||||
when forall
|
||||
if (E) {
|
||||
<+... when != E1
|
||||
unlock@p1(E1,...)
|
||||
...+>
|
||||
}
|
||||
|
||||
@r depends on !balanced exists@
|
||||
expression x <= locked.E1;
|
||||
expression locked.E1;
|
||||
expression E2;
|
||||
identifier lock;
|
||||
position locked.p,p1,p2;
|
||||
@@
|
||||
|
||||
lock@p1 (E1@p,...);
|
||||
... when != E1
|
||||
when != \(x = E2\|&x\)
|
||||
lock@p2 (E1,...);
|
||||
|
||||
@script:python depends on org@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
lock << r.lock;
|
||||
@@
|
||||
|
||||
cocci.print_main(lock,p1)
|
||||
cocci.print_secs("second lock",p2)
|
||||
|
||||
@script:python depends on report@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
lock << r.lock;
|
||||
@@
|
||||
|
||||
msg = "second lock on line %s" % (p2[0].line)
|
||||
coccilib.report.print_report(p1[0],msg)
|
80
scripts/coccinelle/locks/flags.cocci
Normal file
80
scripts/coccinelle/locks/flags.cocci
Normal file
@@ -0,0 +1,80 @@
|
||||
/// Find nested lock+irqsave functions that use the same flags variables
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r@
|
||||
expression lock1,lock2,flags;
|
||||
position p1,p2;
|
||||
@@
|
||||
|
||||
(
|
||||
spin_lock_irqsave@p1(lock1,flags)
|
||||
|
|
||||
read_lock_irqsave@p1(lock1,flags)
|
||||
|
|
||||
write_lock_irqsave@p1(lock1,flags)
|
||||
)
|
||||
... when != flags
|
||||
(
|
||||
spin_lock_irqsave(lock1,flags)
|
||||
|
|
||||
read_lock_irqsave(lock1,flags)
|
||||
|
|
||||
write_lock_irqsave(lock1,flags)
|
||||
|
|
||||
spin_lock_irqsave@p2(lock2,flags)
|
||||
|
|
||||
read_lock_irqsave@p2(lock2,flags)
|
||||
|
|
||||
write_lock_irqsave@p2(lock2,flags)
|
||||
)
|
||||
|
||||
@d@
|
||||
expression f <= r.flags;
|
||||
expression lock1,lock2,flags;
|
||||
position r.p1, r.p2;
|
||||
@@
|
||||
|
||||
(
|
||||
*spin_lock_irqsave@p1(lock1,flags)
|
||||
|
|
||||
*read_lock_irqsave@p1(lock1,flags)
|
||||
|
|
||||
*write_lock_irqsave@p1(lock1,flags)
|
||||
)
|
||||
... when != f
|
||||
(
|
||||
*spin_lock_irqsave@p2(lock2,flags)
|
||||
|
|
||||
*read_lock_irqsave@p2(lock2,flags)
|
||||
|
|
||||
*write_lock_irqsave@p2(lock2,flags)
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@script:python depends on d && org@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
cocci.print_main("original lock",p1)
|
||||
cocci.print_secs("nested lock+irqsave that reuses flags",p2)
|
||||
|
||||
@script:python depends on d && report@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
msg="ERROR: nested lock+irqsave that reuses flags from %s." % (p1[0].line)
|
||||
coccilib.report.print_report(p2[0], msg)
|
95
scripts/coccinelle/locks/mini_lock.cocci
Normal file
95
scripts/coccinelle/locks/mini_lock.cocci
Normal file
@@ -0,0 +1,95 @@
|
||||
/// Find missing unlocks. This semantic match considers the specific case
|
||||
/// where the unlock is missing from an if branch, and there is a lock
|
||||
/// before the if and an unlock after the if. False positives are due to
|
||||
/// cases where the if branch represents a case where the function is
|
||||
/// supposed to exit with the lock held, or where there is some preceding
|
||||
/// function call that releases the lock.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@prelocked@
|
||||
position p1,p;
|
||||
expression E1;
|
||||
@@
|
||||
|
||||
(
|
||||
mutex_lock@p1
|
||||
|
|
||||
mutex_trylock@p1
|
||||
|
|
||||
spin_lock@p1
|
||||
|
|
||||
spin_trylock@p1
|
||||
|
|
||||
read_lock@p1
|
||||
|
|
||||
read_trylock@p1
|
||||
|
|
||||
write_lock@p1
|
||||
|
|
||||
write_trylock@p1
|
||||
|
|
||||
read_lock_irq@p1
|
||||
|
|
||||
write_lock_irq@p1
|
||||
|
|
||||
read_lock_irqsave@p1
|
||||
|
|
||||
write_lock_irqsave@p1
|
||||
|
|
||||
spin_lock_irq@p1
|
||||
|
|
||||
spin_lock_irqsave@p1
|
||||
) (E1@p,...);
|
||||
|
||||
@looped@
|
||||
position r;
|
||||
@@
|
||||
|
||||
for(...;...;...) { <+... return@r ...; ...+> }
|
||||
|
||||
@err@
|
||||
expression E1;
|
||||
position prelocked.p;
|
||||
position up != prelocked.p1;
|
||||
position r!=looped.r;
|
||||
identifier lock,unlock;
|
||||
@@
|
||||
|
||||
lock(E1@p,...);
|
||||
<+... when != E1
|
||||
if (...) {
|
||||
... when != E1
|
||||
return@r ...;
|
||||
}
|
||||
...+>
|
||||
unlock@up(E1,...);
|
||||
|
||||
@script:python depends on org@
|
||||
p << prelocked.p1;
|
||||
lock << err.lock;
|
||||
unlock << err.unlock;
|
||||
p2 << err.r;
|
||||
@@
|
||||
|
||||
cocci.print_main(lock,p)
|
||||
cocci.print_secs(unlock,p2)
|
||||
|
||||
@script:python depends on report@
|
||||
p << prelocked.p1;
|
||||
lock << err.lock;
|
||||
unlock << err.unlock;
|
||||
p2 << err.r;
|
||||
@@
|
||||
|
||||
msg = "preceding lock on line %s" % (p[0].line)
|
||||
coccilib.report.print_report(p2[0],msg)
|
53
scripts/coccinelle/misc/doubleinit.cocci
Normal file
53
scripts/coccinelle/misc/doubleinit.cocci
Normal file
@@ -0,0 +1,53 @@
|
||||
/// Find duplicate field initializations. This has a high rate of false
|
||||
/// positives due to #ifdefs, which Coccinelle is not aware of in a structure
|
||||
/// initialization.
|
||||
///
|
||||
// Confidence: Low
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r@
|
||||
identifier I, s, fld;
|
||||
position p0,p;
|
||||
expression E;
|
||||
@@
|
||||
|
||||
struct I s =@p0 { ... .fld@p = E, ...};
|
||||
|
||||
@s@
|
||||
identifier I, s, r.fld;
|
||||
position r.p0,p;
|
||||
expression E;
|
||||
@@
|
||||
|
||||
struct I s =@p0 { ... .fld@p = E, ...};
|
||||
|
||||
@script:python depends on org@
|
||||
p0 << r.p0;
|
||||
fld << r.fld;
|
||||
ps << s.p;
|
||||
pr << r.p;
|
||||
@@
|
||||
|
||||
if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
|
||||
cocci.print_main(fld,p0)
|
||||
cocci.print_secs("s",ps)
|
||||
cocci.print_secs("r",pr)
|
||||
|
||||
@script:python depends on report@
|
||||
p0 << r.p0;
|
||||
fld << r.fld;
|
||||
ps << s.p;
|
||||
pr << r.p;
|
||||
@@
|
||||
|
||||
if int(ps[0].line) < int(pr[0].line) or (int(ps[0].line) == int(pr[0].line) and int(ps[0].column) < int(pr[0].column)):
|
||||
msg = "%s: first occurrence %s, second occurrence %s" % (fld,ps[0].line,pr[0].line)
|
||||
coccilib.report.print_report(p0[0],msg)
|
48
scripts/coccinelle/misc/ifcol.cocci
Normal file
48
scripts/coccinelle/misc/ifcol.cocci
Normal file
@@ -0,0 +1,48 @@
|
||||
/// Find confusingly indented code in or after an if. An if branch should
|
||||
/// be indented. The code following an if should not be indented.
|
||||
/// Sometimes, code after an if that is indented is actually intended to be
|
||||
/// part of the if branch.
|
||||
///
|
||||
/// This has a high rate of false positives, because Coccinelle's column
|
||||
/// calculation does not distinguish between spaces and tabs, so code that
|
||||
/// is not visually aligned may be considered to be in the same column.
|
||||
///
|
||||
// Confidence: Low
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r disable braces4@
|
||||
position p1,p2;
|
||||
statement S1,S2;
|
||||
@@
|
||||
|
||||
(
|
||||
if (...) { ... }
|
||||
|
|
||||
if (...) S1@p1 S2@p2
|
||||
)
|
||||
|
||||
@script:python depends on org@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
if (p1[0].column == p2[0].column):
|
||||
cocci.print_main("branch",p1)
|
||||
cocci.print_secs("after",p2)
|
||||
|
||||
@script:python depends on report@
|
||||
p1 << r.p1;
|
||||
p2 << r.p2;
|
||||
@@
|
||||
|
||||
if (p1[0].column == p2[0].column):
|
||||
msg = "code aligned with following code on line %s" % (p2[0].line)
|
||||
coccilib.report.print_report(p1[0],msg)
|
293
scripts/coccinelle/null/deref_null.cocci
Normal file
293
scripts/coccinelle/null/deref_null.cocci
Normal file
@@ -0,0 +1,293 @@
|
||||
///
|
||||
/// A variable is dereference under a NULL test.
|
||||
/// Even though it is know to be NULL.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments: -I ... -all_includes can give more complete results
|
||||
// Options:
|
||||
|
||||
virtual context
|
||||
virtual patch
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@initialize:python depends on !context && patch && !org && !report@
|
||||
|
||||
import sys
|
||||
print >> sys.stderr, "This semantic patch does not support the 'patch' mode."
|
||||
|
||||
@depends on patch@
|
||||
@@
|
||||
|
||||
this_rule_should_never_matches();
|
||||
|
||||
@ifm depends on !patch@
|
||||
expression *E;
|
||||
statement S1,S2;
|
||||
position p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...) S1 else S2
|
||||
|
||||
// The following two rules are separate, because both can match a single
|
||||
// expression in different ways
|
||||
@pr1 depends on !patch expression@
|
||||
expression *ifm.E;
|
||||
identifier f;
|
||||
position p1;
|
||||
@@
|
||||
|
||||
(E != NULL && ...) ? <+...E->f@p1...+> : ...
|
||||
|
||||
@pr2 depends on !patch expression@
|
||||
expression *ifm.E;
|
||||
identifier f;
|
||||
position p2;
|
||||
@@
|
||||
|
||||
(
|
||||
(E != NULL) && ... && <+...E->f@p2...+>
|
||||
|
|
||||
(E == NULL) || ... || <+...E->f@p2...+>
|
||||
|
|
||||
sizeof(<+...E->f@p2...+>)
|
||||
)
|
||||
|
||||
// For org and report modes
|
||||
|
||||
@r depends on !context && !patch && (org || report) exists@
|
||||
expression subE <= ifm.E;
|
||||
expression *ifm.E;
|
||||
expression E1,E2;
|
||||
identifier f;
|
||||
statement S1,S2,S3,S4;
|
||||
iterator iter;
|
||||
position p!={pr1.p1,pr2.p2};
|
||||
position ifm.p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...)
|
||||
{
|
||||
... when != if (...) S1 else S2
|
||||
(
|
||||
iter(subE,...) S4 // no use
|
||||
|
|
||||
list_remove_head(E2,subE,...)
|
||||
|
|
||||
subE = E1
|
||||
|
|
||||
for(subE = E1;...;...) S4
|
||||
|
|
||||
subE++
|
||||
|
|
||||
++subE
|
||||
|
|
||||
--subE
|
||||
|
|
||||
subE--
|
||||
|
|
||||
&subE
|
||||
|
|
||||
E->f@p // bad use
|
||||
)
|
||||
... when any
|
||||
return ...;
|
||||
}
|
||||
else S3
|
||||
|
||||
@script:python depends on !context && !patch && !org && report@
|
||||
p << r.p;
|
||||
p1 << ifm.p1;
|
||||
x << ifm.E;
|
||||
@@
|
||||
|
||||
msg="ERROR: %s is NULL but dereferenced." % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
||||
cocci.include_match(False)
|
||||
|
||||
@script:python depends on !context && !patch && org && !report@
|
||||
p << r.p;
|
||||
p1 << ifm.p1;
|
||||
x << ifm.E;
|
||||
@@
|
||||
|
||||
msg="ERROR: %s is NULL but dereferenced." % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
cocci.print_main(msg_safe,p)
|
||||
cocci.include_match(False)
|
||||
|
||||
@s depends on !context && !patch && (org || report) exists@
|
||||
expression subE <= ifm.E;
|
||||
expression *ifm.E;
|
||||
expression E1,E2;
|
||||
identifier f;
|
||||
statement S1,S2,S3,S4;
|
||||
iterator iter;
|
||||
position p!={pr1.p1,pr2.p2};
|
||||
position ifm.p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...)
|
||||
{
|
||||
... when != if (...) S1 else S2
|
||||
(
|
||||
iter(subE,...) S4 // no use
|
||||
|
|
||||
list_remove_head(E2,subE,...)
|
||||
|
|
||||
subE = E1
|
||||
|
|
||||
for(subE = E1;...;...) S4
|
||||
|
|
||||
subE++
|
||||
|
|
||||
++subE
|
||||
|
|
||||
--subE
|
||||
|
|
||||
subE--
|
||||
|
|
||||
&subE
|
||||
|
|
||||
E->f@p // bad use
|
||||
)
|
||||
... when any
|
||||
}
|
||||
else S3
|
||||
|
||||
@script:python depends on !context && !patch && !org && report@
|
||||
p << s.p;
|
||||
p1 << ifm.p1;
|
||||
x << ifm.E;
|
||||
@@
|
||||
|
||||
msg="ERROR: %s is NULL but dereferenced." % (x)
|
||||
coccilib.report.print_report(p[0], msg)
|
||||
|
||||
@script:python depends on !context && !patch && org && !report@
|
||||
p << s.p;
|
||||
p1 << ifm.p1;
|
||||
x << ifm.E;
|
||||
@@
|
||||
|
||||
msg="ERROR: %s is NULL but dereferenced." % (x)
|
||||
msg_safe=msg.replace("[","@(").replace("]",")")
|
||||
cocci.print_main(msg_safe,p)
|
||||
|
||||
// For context mode
|
||||
|
||||
@depends on context && !patch && !org && !report exists@
|
||||
expression subE <= ifm.E;
|
||||
expression *ifm.E;
|
||||
expression E1,E2;
|
||||
identifier f;
|
||||
statement S1,S2,S3,S4;
|
||||
iterator iter;
|
||||
position p!={pr1.p1,pr2.p2};
|
||||
position ifm.p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...)
|
||||
{
|
||||
... when != if (...) S1 else S2
|
||||
(
|
||||
iter(subE,...) S4 // no use
|
||||
|
|
||||
list_remove_head(E2,subE,...)
|
||||
|
|
||||
subE = E1
|
||||
|
|
||||
for(subE = E1;...;...) S4
|
||||
|
|
||||
subE++
|
||||
|
|
||||
++subE
|
||||
|
|
||||
--subE
|
||||
|
|
||||
subE--
|
||||
|
|
||||
&subE
|
||||
|
|
||||
* E->f@p // bad use
|
||||
)
|
||||
... when any
|
||||
return ...;
|
||||
}
|
||||
else S3
|
||||
|
||||
// The following three rules are duplicates of ifm, pr1 and pr2 respectively.
|
||||
// It is need because the previous rule as already made a "change".
|
||||
|
||||
@ifm1 depends on !patch@
|
||||
expression *E;
|
||||
statement S1,S2;
|
||||
position p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...) S1 else S2
|
||||
|
||||
@pr11 depends on !patch expression@
|
||||
expression *ifm1.E;
|
||||
identifier f;
|
||||
position p1;
|
||||
@@
|
||||
|
||||
(E != NULL && ...) ? <+...E->f@p1...+> : ...
|
||||
|
||||
@pr12 depends on !patch expression@
|
||||
expression *ifm1.E;
|
||||
identifier f;
|
||||
position p2;
|
||||
@@
|
||||
|
||||
(
|
||||
(E != NULL) && ... && <+...E->f@p2...+>
|
||||
|
|
||||
(E == NULL) || ... || <+...E->f@p2...+>
|
||||
|
|
||||
sizeof(<+...E->f@p2...+>)
|
||||
)
|
||||
|
||||
@depends on context && !patch && !org && !report exists@
|
||||
expression subE <= ifm1.E;
|
||||
expression *ifm1.E;
|
||||
expression E1,E2;
|
||||
identifier f;
|
||||
statement S1,S2,S3,S4;
|
||||
iterator iter;
|
||||
position p!={pr11.p1,pr12.p2};
|
||||
position ifm1.p1;
|
||||
@@
|
||||
|
||||
if@p1 ((E == NULL && ...) || ...)
|
||||
{
|
||||
... when != if (...) S1 else S2
|
||||
(
|
||||
iter(subE,...) S4 // no use
|
||||
|
|
||||
list_remove_head(E2,subE,...)
|
||||
|
|
||||
subE = E1
|
||||
|
|
||||
for(subE = E1;...;...) S4
|
||||
|
|
||||
subE++
|
||||
|
|
||||
++subE
|
||||
|
|
||||
--subE
|
||||
|
|
||||
subE--
|
||||
|
|
||||
&subE
|
||||
|
|
||||
* E->f@p // bad use
|
||||
)
|
||||
... when any
|
||||
}
|
||||
else S3
|
20
scripts/coccinelle/null/eno.cocci
Normal file
20
scripts/coccinelle/null/eno.cocci
Normal file
@@ -0,0 +1,20 @@
|
||||
/// The various basic memory allocation functions don't return ERR_PTR
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual patch
|
||||
|
||||
@@
|
||||
expression x,E;
|
||||
@@
|
||||
|
||||
x = \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\)(...)
|
||||
... when != x = E
|
||||
- IS_ERR(x)
|
||||
+ !x
|
72
scripts/coccinelle/null/kmerr.cocci
Normal file
72
scripts/coccinelle/null/kmerr.cocci
Normal file
@@ -0,0 +1,72 @@
|
||||
/// This semantic patch looks for kmalloc etc that are not followed by a
|
||||
/// NULL check. It only gives a report in the case where there is some
|
||||
/// error handling code later in the function, which may be helpful
|
||||
/// in determining what the error handling code for the call to kmalloc etc
|
||||
/// should be.
|
||||
///
|
||||
// Confidence: High
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@withtest@
|
||||
expression x;
|
||||
position p;
|
||||
identifier f,fld;
|
||||
@@
|
||||
|
||||
x@p = f(...);
|
||||
... when != x->fld
|
||||
\(x == NULL \| x != NULL\)
|
||||
|
||||
@fixed depends on context && !org && !report@
|
||||
expression x,x1;
|
||||
position p1 != withtest.p;
|
||||
statement S;
|
||||
position any withtest.p;
|
||||
identifier f;
|
||||
@@
|
||||
|
||||
*x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
|
||||
...
|
||||
*x1@p = f(...);
|
||||
if (!x1) S
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
@rfixed depends on (org || report) && !context exists@
|
||||
expression x,x1;
|
||||
position p1 != withtest.p;
|
||||
position p2;
|
||||
statement S;
|
||||
position any withtest.p;
|
||||
identifier f;
|
||||
@@
|
||||
|
||||
x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...);
|
||||
...
|
||||
x1@p = f@p2(...);
|
||||
if (!x1) S
|
||||
|
||||
@script:python depends on org@
|
||||
p1 << rfixed.p1;
|
||||
p2 << rfixed.p2;
|
||||
@@
|
||||
|
||||
cocci.print_main("alloc call",p1)
|
||||
cocci.print_secs("possible model",p2)
|
||||
|
||||
@script:python depends on report@
|
||||
p1 << rfixed.p1;
|
||||
p2 << rfixed.p2;
|
||||
@@
|
||||
|
||||
msg = "alloc with no test, possible model on line %s" % (p2[0].line)
|
||||
coccilib.report.print_report(p1[0],msg)
|
54
scripts/coccinelle/tests/doublebitand.cocci
Normal file
54
scripts/coccinelle/tests/doublebitand.cocci
Normal file
@@ -0,0 +1,54 @@
|
||||
/// Find bit operations that include the same argument more than once
|
||||
//# One source of false positives is when the argument performs a side
|
||||
//# effect. Another source of false positives is when a neutral value
|
||||
//# such as 0 for | is used to indicate no information, to maintain the
|
||||
//# same structure as other similar expressions
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r expression@
|
||||
expression E;
|
||||
position p;
|
||||
@@
|
||||
|
||||
(
|
||||
* E@p
|
||||
& ... & E
|
||||
|
|
||||
* E@p
|
||||
| ... | E
|
||||
|
|
||||
* E@p
|
||||
& ... & !E
|
||||
|
|
||||
* E@p
|
||||
| ... | !E
|
||||
|
|
||||
* !E@p
|
||||
& ... & E
|
||||
|
|
||||
* !E@p
|
||||
| ... | E
|
||||
)
|
||||
|
||||
@script:python depends on org@
|
||||
p << r.p;
|
||||
@@
|
||||
|
||||
cocci.print_main("duplicated argument to & or |",p)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r.p;
|
||||
@@
|
||||
|
||||
coccilib.report.print_report(p[0],"duplicated argument to & or |")
|
40
scripts/coccinelle/tests/doubletest.cocci
Normal file
40
scripts/coccinelle/tests/doubletest.cocci
Normal file
@@ -0,0 +1,40 @@
|
||||
/// Find &&/|| operations that include the same argument more than once
|
||||
//# A common source of false positives is when the argument performs a side
|
||||
//# effect.
|
||||
///
|
||||
// Confidence: Moderate
|
||||
// Copyright: (C) 2010 Nicolas Palix, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Julia Lawall, DIKU. GPLv2.
|
||||
// Copyright: (C) 2010 Gilles Muller, INRIA/LiP6. GPLv2.
|
||||
// URL: http://coccinelle.lip6.fr/
|
||||
// Comments:
|
||||
// Options: -no_includes -include_headers
|
||||
|
||||
virtual context
|
||||
virtual org
|
||||
virtual report
|
||||
|
||||
@r expression@
|
||||
expression E;
|
||||
position p;
|
||||
@@
|
||||
|
||||
(
|
||||
* E@p
|
||||
|| ... || E
|
||||
|
|
||||
* E@p
|
||||
&& ... && E
|
||||
)
|
||||
|
||||
@script:python depends on org@
|
||||
p << r.p;
|
||||
@@
|
||||
|
||||
cocci.print_main("duplicated argument to && or ||",p)
|
||||
|
||||
@script:python depends on report@
|
||||
p << r.p;
|
||||
@@
|
||||
|
||||
coccilib.report.print_report(p[0],"duplicated argument to && or ||")
|
@@ -40,7 +40,7 @@ echo $code
|
||||
code=`echo $code | sed -e 's/.*Code: //'`
|
||||
|
||||
width=`expr index "$code" ' '`
|
||||
width=$[($width-1)/2]
|
||||
width=$((($width-1)/2))
|
||||
case $width in
|
||||
1) type=byte ;;
|
||||
2) type=2byte ;;
|
||||
@@ -48,10 +48,10 @@ case $width in
|
||||
esac
|
||||
|
||||
disas() {
|
||||
${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s &> /dev/null
|
||||
${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1
|
||||
|
||||
if [ "$ARCH" == "arm" ]; then
|
||||
if [ $width == 2 ]; then
|
||||
if [ "$ARCH" = "arm" ]; then
|
||||
if [ $width -eq 2 ]; then
|
||||
OBJDUMPFLAGS="-M force-thumb"
|
||||
fi
|
||||
|
||||
@@ -59,7 +59,7 @@ disas() {
|
||||
fi
|
||||
|
||||
${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
|
||||
grep -v "/tmp\|Disassembly\|\.text\|^$" &> $1.dis
|
||||
grep -v "/tmp\|Disassembly\|\.text\|^$" > $1.dis 2>&1
|
||||
}
|
||||
|
||||
marker=`expr index "$code" "\<"`
|
||||
|
@@ -77,6 +77,7 @@ static struct node *read_fstree(const char *dirname)
|
||||
free(tmpnam);
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
return tree;
|
||||
}
|
||||
|
||||
|
@@ -7,12 +7,10 @@
|
||||
# The obscure use of the "tr" filter is to work around older versions of
|
||||
# "grep" that report the byte offset of the line instead of the pattern.
|
||||
#
|
||||
# (c) 2009, Dick Streefland <dick@streefland.net>
|
||||
# (c) 2009,2010 Dick Streefland <dick@streefland.net>
|
||||
# Licensed under the terms of the GNU General Public License.
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
gz1='\037\213\010'
|
||||
gz2='01'
|
||||
cf1='IKCFG_ST\037\213\010'
|
||||
cf2='0123456789'
|
||||
|
||||
@@ -21,11 +19,25 @@ dump_config()
|
||||
if pos=`tr "$cf1\n$cf2" "\n$cf2=" < "$1" | grep -abo "^$cf2"`
|
||||
then
|
||||
pos=${pos%%:*}
|
||||
tail -c+$(($pos+8)) "$1" | zcat -q
|
||||
exit 0
|
||||
tail -c+$(($pos+8)) "$1" | zcat > $tmp1 2> /dev/null
|
||||
if [ $? != 1 ]
|
||||
then # exit status must be 0 or 2 (trailing garbage warning)
|
||||
cat $tmp1
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
try_decompress()
|
||||
{
|
||||
for pos in `tr "$1\n$2" "\n$2=" < "$img" | grep -abo "^$2"`
|
||||
do
|
||||
pos=${pos%%:*}
|
||||
tail -c+$pos "$img" | $3 > $tmp2 2> /dev/null
|
||||
dump_config $tmp2
|
||||
done
|
||||
}
|
||||
|
||||
# Check invocation:
|
||||
me=${0##*/}
|
||||
img=$1
|
||||
@@ -35,18 +47,19 @@ then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Prepare temp files:
|
||||
tmp1=/tmp/ikconfig$$.1
|
||||
tmp2=/tmp/ikconfig$$.2
|
||||
trap "rm -f $tmp1 $tmp2" 0
|
||||
|
||||
# Initial attempt for uncompressed images or objects:
|
||||
dump_config "$img"
|
||||
|
||||
# That didn't work, so decompress and try again:
|
||||
tmp=/tmp/ikconfig$$
|
||||
trap "rm -f $tmp" 0
|
||||
for pos in `tr "$gz1\n$gz2" "\n$gz2=" < "$img" | grep -abo "^$gz2"`
|
||||
do
|
||||
pos=${pos%%:*}
|
||||
tail -c+$pos "$img" | zcat 2> /dev/null > $tmp
|
||||
dump_config $tmp
|
||||
done
|
||||
# That didn't work, so retry after decompression.
|
||||
try_decompress '\037\213\010' xy gunzip
|
||||
try_decompress 'BZh' xy bunzip2
|
||||
try_decompress '\135\0\0\0' xxx unlzma
|
||||
try_decompress '\211\114\132' xy 'lzop -d'
|
||||
|
||||
# Bail out:
|
||||
echo "$me: Cannot find kernel config." >&2
|
||||
|
5
scripts/gcc-goto.sh
Normal file
5
scripts/gcc-goto.sh
Normal file
@@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
# Test for gcc 'asm goto' suport
|
||||
# Copyright (C) 2010, Jason Baron <jbaron@redhat.com>
|
||||
|
||||
echo "int main(void) { entry: asm goto (\"\"::::entry); return 0; }" | $@ -x c - -c -o /dev/null >/dev/null 2>&1 && echo "y"
|
File diff suppressed because it is too large
Load Diff
1
scripts/kconfig/.gitignore
vendored
1
scripts/kconfig/.gitignore
vendored
@@ -17,6 +17,7 @@ gconf.glade.h
|
||||
#
|
||||
conf
|
||||
mconf
|
||||
nconf
|
||||
qconf
|
||||
gconf
|
||||
kxgettext
|
||||
|
@@ -8,7 +8,7 @@ PHONY += oldconfig xconfig gconfig menuconfig config silentoldconfig update-po-c
|
||||
ifdef KBUILD_KCONFIG
|
||||
Kconfig := $(KBUILD_KCONFIG)
|
||||
else
|
||||
Kconfig := arch/$(SRCARCH)/Kconfig
|
||||
Kconfig := Kconfig
|
||||
endif
|
||||
|
||||
xconfig: $(obj)/qconf
|
||||
@@ -21,17 +21,17 @@ menuconfig: $(obj)/mconf
|
||||
$< $(Kconfig)
|
||||
|
||||
config: $(obj)/conf
|
||||
$< $(Kconfig)
|
||||
$< --oldaskconfig $(Kconfig)
|
||||
|
||||
nconfig: $(obj)/nconf
|
||||
$< $(Kconfig)
|
||||
|
||||
oldconfig: $(obj)/conf
|
||||
$< -o $(Kconfig)
|
||||
$< --$@ $(Kconfig)
|
||||
|
||||
silentoldconfig: $(obj)/conf
|
||||
$(Q)mkdir -p include/generated
|
||||
$< -s $(Kconfig)
|
||||
$< --$@ $(Kconfig)
|
||||
|
||||
# if no path is given, then use src directory to find file
|
||||
ifdef LSMOD
|
||||
@@ -44,15 +44,15 @@ endif
|
||||
localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
|
||||
$(Q)mkdir -p include/generated
|
||||
$(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
|
||||
$(Q)if [ -f .config ]; then \
|
||||
cmp -s .tmp.config .config || \
|
||||
(mv -f .config .config.old.1; \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf -s $(Kconfig); \
|
||||
mv -f .config.old.1 .config.old) \
|
||||
else \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf -s $(Kconfig); \
|
||||
$(Q)if [ -f .config ]; then \
|
||||
cmp -s .tmp.config .config || \
|
||||
(mv -f .config .config.old.1; \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf --silentoldconfig $(Kconfig); \
|
||||
mv -f .config.old.1 .config.old) \
|
||||
else \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf --silentoldconfig $(Kconfig); \
|
||||
fi
|
||||
$(Q)rm -f .tmp.config
|
||||
|
||||
@@ -60,15 +60,15 @@ localyesconfig: $(obj)/streamline_config.pl $(obj)/conf
|
||||
$(Q)mkdir -p include/generated
|
||||
$(Q)perl $< $(srctree) $(Kconfig) $(LSMOD_F) > .tmp.config
|
||||
$(Q)sed -i s/=m/=y/ .tmp.config
|
||||
$(Q)if [ -f .config ]; then \
|
||||
cmp -s .tmp.config .config || \
|
||||
(mv -f .config .config.old.1; \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf -s $(Kconfig); \
|
||||
mv -f .config.old.1 .config.old) \
|
||||
else \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf -s $(Kconfig); \
|
||||
$(Q)if [ -f .config ]; then \
|
||||
cmp -s .tmp.config .config || \
|
||||
(mv -f .config .config.old.1; \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf --silentoldconfig $(Kconfig); \
|
||||
mv -f .config.old.1 .config.old) \
|
||||
else \
|
||||
mv -f .tmp.config .config; \
|
||||
$(obj)/conf --silentoldconfig $(Kconfig); \
|
||||
fi
|
||||
$(Q)rm -f .tmp.config
|
||||
|
||||
@@ -95,30 +95,29 @@ update-po-config: $(obj)/kxgettext $(obj)/gconf.glade.h
|
||||
$(Q)rm -f arch/um/Kconfig.arch
|
||||
$(Q)rm -f $(obj)/config.pot
|
||||
|
||||
PHONY += randconfig allyesconfig allnoconfig allmodconfig defconfig
|
||||
PHONY += allnoconfig allyesconfig allmodconfig alldefconfig randconfig
|
||||
|
||||
randconfig: $(obj)/conf
|
||||
$< -r $(Kconfig)
|
||||
allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
|
||||
$< --$@ $(Kconfig)
|
||||
|
||||
allyesconfig: $(obj)/conf
|
||||
$< -y $(Kconfig)
|
||||
PHONY += listnewconfig oldnoconfig savedefconfig defconfig
|
||||
|
||||
allnoconfig: $(obj)/conf
|
||||
$< -n $(Kconfig)
|
||||
listnewconfig oldnoconfig: $(obj)/conf
|
||||
$< --$@ $(Kconfig)
|
||||
|
||||
allmodconfig: $(obj)/conf
|
||||
$< -m $(Kconfig)
|
||||
savedefconfig: $(obj)/conf
|
||||
$< --$@=defconfig $(Kconfig)
|
||||
|
||||
defconfig: $(obj)/conf
|
||||
ifeq ($(KBUILD_DEFCONFIG),)
|
||||
$< -d $(Kconfig)
|
||||
$< --defconfig $(Kconfig)
|
||||
else
|
||||
@echo "*** Default configuration is based on '$(KBUILD_DEFCONFIG)'"
|
||||
$(Q)$< -D arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
|
||||
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG) $(Kconfig)
|
||||
endif
|
||||
|
||||
%_defconfig: $(obj)/conf
|
||||
$(Q)$< -D arch/$(SRCARCH)/configs/$@ $(Kconfig)
|
||||
$(Q)$< --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
|
||||
|
||||
# Help text used by make help
|
||||
help:
|
||||
@@ -131,22 +130,23 @@ help:
|
||||
@echo ' localmodconfig - Update current config disabling modules not loaded'
|
||||
@echo ' localyesconfig - Update current config converting local mods to core'
|
||||
@echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
|
||||
@echo ' randconfig - New config with random answer to all options'
|
||||
@echo ' defconfig - New config with default answer to all options'
|
||||
@echo ' allmodconfig - New config selecting modules when possible'
|
||||
@echo ' allyesconfig - New config where all options are accepted with yes'
|
||||
@echo ' defconfig - New config with default from ARCH supplied defconfig'
|
||||
@echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
|
||||
@echo ' allnoconfig - New config where all options are answered with no'
|
||||
@echo ' allyesconfig - New config where all options are accepted with yes'
|
||||
@echo ' allmodconfig - New config selecting modules when possible'
|
||||
@echo ' alldefconfig - New config with all symbols set to default'
|
||||
@echo ' randconfig - New config with random answer to all options'
|
||||
@echo ' listnewconfig - List new options'
|
||||
@echo ' oldnoconfig - Same as silentoldconfig but set new symbols to n (unset)'
|
||||
|
||||
# lxdialog stuff
|
||||
check-lxdialog := $(srctree)/$(src)/lxdialog/check-lxdialog.sh
|
||||
|
||||
# Use recursively expanded variables so we do not call gcc unless
|
||||
# we really need to do so. (Do not call gcc as part of make mrproper)
|
||||
HOST_EXTRACFLAGS = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags)
|
||||
HOST_LOADLIBES = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
|
||||
|
||||
HOST_EXTRACFLAGS += -DLOCALE
|
||||
|
||||
HOST_EXTRACFLAGS += $(shell $(CONFIG_SHELL) $(check-lxdialog) -ccflags) \
|
||||
-DLOCALE
|
||||
|
||||
# ===========================================================================
|
||||
# Shared Makefile for the various kconfig executables:
|
||||
@@ -205,7 +205,7 @@ clean-files += config.pot linux.pot
|
||||
PHONY += $(obj)/dochecklxdialog
|
||||
$(addprefix $(obj)/,$(lxdialog)): $(obj)/dochecklxdialog
|
||||
$(obj)/dochecklxdialog:
|
||||
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOST_LOADLIBES)
|
||||
$(Q)$(CONFIG_SHELL) $(check-lxdialog) -check $(HOSTCC) $(HOST_EXTRACFLAGS) $(HOSTLOADLIBES_mconf)
|
||||
|
||||
always := dochecklxdialog
|
||||
|
||||
@@ -223,6 +223,8 @@ HOSTLOADLIBES_gconf = `pkg-config --libs gtk+-2.0 gmodule-2.0 libglade-2.0` -ldl
|
||||
HOSTCFLAGS_gconf.o = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libglade-2.0` \
|
||||
-D LKC_DIRECT_LINK
|
||||
|
||||
HOSTLOADLIBES_mconf = $(shell $(CONFIG_SHELL) $(check-lxdialog) -ldflags $(HOSTCC))
|
||||
|
||||
HOSTLOADLIBES_nconf = -lmenu -lpanel -lncurses
|
||||
$(obj)/qconf.o: $(obj)/.tmp_qtcheck
|
||||
|
||||
@@ -233,40 +235,48 @@ $(obj)/.tmp_qtcheck: $(src)/Makefile
|
||||
# QT needs some extra effort...
|
||||
$(obj)/.tmp_qtcheck:
|
||||
@set -e; echo " CHECK qt"; dir=""; pkg=""; \
|
||||
pkg-config --exists qt 2> /dev/null && pkg=qt; \
|
||||
pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
|
||||
if [ -n "$$pkg" ]; then \
|
||||
cflags="\$$(shell pkg-config $$pkg --cflags)"; \
|
||||
libs="\$$(shell pkg-config $$pkg --libs)"; \
|
||||
moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
|
||||
dir="$$(pkg-config $$pkg --variable=prefix)"; \
|
||||
if ! pkg-config --exists QtCore 2> /dev/null; then \
|
||||
echo "* Unable to find the QT4 tool qmake. Trying to use QT3"; \
|
||||
pkg-config --exists qt 2> /dev/null && pkg=qt; \
|
||||
pkg-config --exists qt-mt 2> /dev/null && pkg=qt-mt; \
|
||||
if [ -n "$$pkg" ]; then \
|
||||
cflags="\$$(shell pkg-config $$pkg --cflags)"; \
|
||||
libs="\$$(shell pkg-config $$pkg --libs)"; \
|
||||
moc="\$$(shell pkg-config $$pkg --variable=prefix)/bin/moc"; \
|
||||
dir="$$(pkg-config $$pkg --variable=prefix)"; \
|
||||
else \
|
||||
for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
|
||||
if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
|
||||
done; \
|
||||
if [ -z "$$dir" ]; then \
|
||||
echo "*"; \
|
||||
echo "* Unable to find any QT installation. Please make sure that"; \
|
||||
echo "* the QT4 or QT3 development package is correctly installed and"; \
|
||||
echo "* either qmake can be found or install pkg-config or set"; \
|
||||
echo "* the QTDIR environment variable to the correct location."; \
|
||||
echo "*"; \
|
||||
false; \
|
||||
fi; \
|
||||
libpath=$$dir/lib; lib=qt; osdir=""; \
|
||||
$(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
|
||||
osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
|
||||
test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
|
||||
test -f $$libpath/libqt-mt.so && lib=qt-mt; \
|
||||
cflags="-I$$dir/include"; \
|
||||
libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
|
||||
moc="$$dir/bin/moc"; \
|
||||
fi; \
|
||||
if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
|
||||
echo "*"; \
|
||||
echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
|
||||
echo "*"; \
|
||||
moc="/usr/bin/moc"; \
|
||||
fi; \
|
||||
else \
|
||||
for d in $$QTDIR /usr/share/qt* /usr/lib/qt*; do \
|
||||
if [ -f $$d/include/qconfig.h ]; then dir=$$d; break; fi; \
|
||||
done; \
|
||||
if [ -z "$$dir" ]; then \
|
||||
echo "*"; \
|
||||
echo "* Unable to find the QT3 installation. Please make sure that"; \
|
||||
echo "* the QT3 development package is correctly installed and"; \
|
||||
echo "* either install pkg-config or set the QTDIR environment"; \
|
||||
echo "* variable to the correct location."; \
|
||||
echo "*"; \
|
||||
false; \
|
||||
fi; \
|
||||
libpath=$$dir/lib; lib=qt; osdir=""; \
|
||||
$(HOSTCXX) -print-multi-os-directory > /dev/null 2>&1 && \
|
||||
osdir=x$$($(HOSTCXX) -print-multi-os-directory); \
|
||||
test -d $$libpath/$$osdir && libpath=$$libpath/$$osdir; \
|
||||
test -f $$libpath/libqt-mt.so && lib=qt-mt; \
|
||||
cflags="-I$$dir/include"; \
|
||||
libs="-L$$libpath -Wl,-rpath,$$libpath -l$$lib"; \
|
||||
moc="$$dir/bin/moc"; \
|
||||
fi; \
|
||||
if [ ! -x $$dir/bin/moc -a -x /usr/bin/moc ]; then \
|
||||
echo "*"; \
|
||||
echo "* Unable to find $$dir/bin/moc, using /usr/bin/moc instead."; \
|
||||
echo "*"; \
|
||||
moc="/usr/bin/moc"; \
|
||||
cflags="\$$(shell pkg-config QtCore QtGui Qt3Support --cflags)"; \
|
||||
libs="\$$(shell pkg-config QtCore QtGui Qt3Support --libs)"; \
|
||||
binpath="\$$(shell pkg-config QtCore --variable=prefix)"; \
|
||||
moc="$$binpath/bin/moc"; \
|
||||
fi; \
|
||||
echo "KC_QT_CFLAGS=$$cflags" > $@; \
|
||||
echo "KC_QT_LIBS=$$libs" >> $@; \
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
@@ -19,16 +20,21 @@
|
||||
static void conf(struct menu *menu);
|
||||
static void check_conf(struct menu *menu);
|
||||
|
||||
enum {
|
||||
ask_all,
|
||||
ask_new,
|
||||
ask_silent,
|
||||
set_default,
|
||||
set_yes,
|
||||
set_mod,
|
||||
set_no,
|
||||
set_random
|
||||
} input_mode = ask_all;
|
||||
enum input_mode {
|
||||
oldaskconfig,
|
||||
silentoldconfig,
|
||||
oldconfig,
|
||||
allnoconfig,
|
||||
allyesconfig,
|
||||
allmodconfig,
|
||||
alldefconfig,
|
||||
randconfig,
|
||||
defconfig,
|
||||
savedefconfig,
|
||||
listnewconfig,
|
||||
oldnoconfig,
|
||||
} input_mode = oldaskconfig;
|
||||
|
||||
char *defconfig_file;
|
||||
|
||||
static int indent = 1;
|
||||
@@ -93,16 +99,16 @@ static int conf_askvalue(struct symbol *sym, const char *def)
|
||||
}
|
||||
|
||||
switch (input_mode) {
|
||||
case ask_new:
|
||||
case ask_silent:
|
||||
case oldconfig:
|
||||
case silentoldconfig:
|
||||
if (sym_has_value(sym)) {
|
||||
printf("%s\n", def);
|
||||
return 0;
|
||||
}
|
||||
check_stdin();
|
||||
case ask_all:
|
||||
case oldaskconfig:
|
||||
fflush(stdout);
|
||||
fgets(line, 128, stdin);
|
||||
xfgets(line, 128, stdin);
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
@@ -156,14 +162,12 @@ static int conf_string(struct menu *menu)
|
||||
static int conf_sym(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym = menu->sym;
|
||||
int type;
|
||||
tristate oldval, newval;
|
||||
|
||||
while (1) {
|
||||
printf("%*s%s ", indent - 1, "", _(menu->prompt->text));
|
||||
if (sym->name)
|
||||
printf("(%s) ", sym->name);
|
||||
type = sym_get_type(sym);
|
||||
putchar('[');
|
||||
oldval = sym_get_tristate_value(sym);
|
||||
switch (oldval) {
|
||||
@@ -228,11 +232,9 @@ static int conf_choice(struct menu *menu)
|
||||
{
|
||||
struct symbol *sym, *def_sym;
|
||||
struct menu *child;
|
||||
int type;
|
||||
bool is_new;
|
||||
|
||||
sym = menu->sym;
|
||||
type = sym_get_type(sym);
|
||||
is_new = !sym_has_value(sym);
|
||||
if (sym_is_changable(sym)) {
|
||||
conf_sym(menu);
|
||||
@@ -294,17 +296,17 @@ static int conf_choice(struct menu *menu)
|
||||
printf("?");
|
||||
printf("]: ");
|
||||
switch (input_mode) {
|
||||
case ask_new:
|
||||
case ask_silent:
|
||||
case oldconfig:
|
||||
case silentoldconfig:
|
||||
if (!is_new) {
|
||||
cnt = def;
|
||||
printf("%d\n", cnt);
|
||||
break;
|
||||
}
|
||||
check_stdin();
|
||||
case ask_all:
|
||||
case oldaskconfig:
|
||||
fflush(stdout);
|
||||
fgets(line, 128, stdin);
|
||||
xfgets(line, 128, stdin);
|
||||
strip(line);
|
||||
if (line[0] == '?') {
|
||||
print_help(menu);
|
||||
@@ -360,7 +362,10 @@ static void conf(struct menu *menu)
|
||||
|
||||
switch (prop->type) {
|
||||
case P_MENU:
|
||||
if (input_mode == ask_silent && rootEntry != menu) {
|
||||
if ((input_mode == silentoldconfig ||
|
||||
input_mode == listnewconfig ||
|
||||
input_mode == oldnoconfig) &&
|
||||
rootEntry != menu) {
|
||||
check_conf(menu);
|
||||
return;
|
||||
}
|
||||
@@ -418,10 +423,16 @@ static void check_conf(struct menu *menu)
|
||||
if (sym && !sym_has_value(sym)) {
|
||||
if (sym_is_changable(sym) ||
|
||||
(sym_is_choice(sym) && sym_get_tristate_value(sym) == yes)) {
|
||||
if (!conf_cnt++)
|
||||
printf(_("*\n* Restart config...\n*\n"));
|
||||
rootEntry = menu_get_parent_menu(menu);
|
||||
conf(rootEntry);
|
||||
if (input_mode == listnewconfig) {
|
||||
if (sym->name && !sym_is_choice_value(sym)) {
|
||||
printf("%s%s\n", CONFIG_, sym->name);
|
||||
}
|
||||
} else if (input_mode != oldnoconfig) {
|
||||
if (!conf_cnt++)
|
||||
printf(_("*\n* Restart config...\n*\n"));
|
||||
rootEntry = menu_get_parent_menu(menu);
|
||||
conf(rootEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,6 +440,22 @@ static void check_conf(struct menu *menu)
|
||||
check_conf(child);
|
||||
}
|
||||
|
||||
static struct option long_opts[] = {
|
||||
{"oldaskconfig", no_argument, NULL, oldaskconfig},
|
||||
{"oldconfig", no_argument, NULL, oldconfig},
|
||||
{"silentoldconfig", no_argument, NULL, silentoldconfig},
|
||||
{"defconfig", optional_argument, NULL, defconfig},
|
||||
{"savedefconfig", required_argument, NULL, savedefconfig},
|
||||
{"allnoconfig", no_argument, NULL, allnoconfig},
|
||||
{"allyesconfig", no_argument, NULL, allyesconfig},
|
||||
{"allmodconfig", no_argument, NULL, allmodconfig},
|
||||
{"alldefconfig", no_argument, NULL, alldefconfig},
|
||||
{"randconfig", no_argument, NULL, randconfig},
|
||||
{"listnewconfig", no_argument, NULL, listnewconfig},
|
||||
{"oldnoconfig", no_argument, NULL, oldnoconfig},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
int main(int ac, char **av)
|
||||
{
|
||||
int opt;
|
||||
@@ -439,32 +466,17 @@ int main(int ac, char **av)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
|
||||
while ((opt = getopt_long(ac, av, "", long_opts, NULL)) != -1) {
|
||||
input_mode = (enum input_mode)opt;
|
||||
switch (opt) {
|
||||
case 'o':
|
||||
input_mode = ask_silent;
|
||||
break;
|
||||
case 's':
|
||||
input_mode = ask_silent;
|
||||
case silentoldconfig:
|
||||
sync_kconfig = 1;
|
||||
break;
|
||||
case 'd':
|
||||
input_mode = set_default;
|
||||
break;
|
||||
case 'D':
|
||||
input_mode = set_default;
|
||||
case defconfig:
|
||||
case savedefconfig:
|
||||
defconfig_file = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
input_mode = set_no;
|
||||
break;
|
||||
case 'm':
|
||||
input_mode = set_mod;
|
||||
break;
|
||||
case 'y':
|
||||
input_mode = set_yes;
|
||||
break;
|
||||
case 'r':
|
||||
case randconfig:
|
||||
{
|
||||
struct timeval now;
|
||||
unsigned int seed;
|
||||
@@ -477,17 +489,12 @@ int main(int ac, char **av)
|
||||
|
||||
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
|
||||
srand(seed);
|
||||
|
||||
input_mode = set_random;
|
||||
break;
|
||||
}
|
||||
case 'h':
|
||||
printf(_("See README for usage info\n"));
|
||||
exit(0);
|
||||
break;
|
||||
default:
|
||||
case '?':
|
||||
fprintf(stderr, _("See README for usage info\n"));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ac == optind) {
|
||||
@@ -501,8 +508,7 @@ int main(int ac, char **av)
|
||||
name = conf_get_configname();
|
||||
if (stat(name, &tmpstat)) {
|
||||
fprintf(stderr, _("***\n"
|
||||
"*** You have not yet configured your kernel!\n"
|
||||
"*** (missing kernel config file \"%s\")\n"
|
||||
"*** Configuration file \"%s\" not found!\n"
|
||||
"***\n"
|
||||
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
|
||||
"*** \"make menuconfig\" or \"make xconfig\").\n"
|
||||
@@ -512,7 +518,7 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
switch (input_mode) {
|
||||
case set_default:
|
||||
case defconfig:
|
||||
if (!defconfig_file)
|
||||
defconfig_file = conf_get_default_confname();
|
||||
if (conf_read(defconfig_file)) {
|
||||
@@ -522,25 +528,32 @@ int main(int ac, char **av)
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case ask_silent:
|
||||
case ask_all:
|
||||
case ask_new:
|
||||
case savedefconfig:
|
||||
conf_read(NULL);
|
||||
break;
|
||||
case set_no:
|
||||
case set_mod:
|
||||
case set_yes:
|
||||
case set_random:
|
||||
case silentoldconfig:
|
||||
case oldaskconfig:
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case oldnoconfig:
|
||||
conf_read(NULL);
|
||||
break;
|
||||
case allnoconfig:
|
||||
case allyesconfig:
|
||||
case allmodconfig:
|
||||
case alldefconfig:
|
||||
case randconfig:
|
||||
name = getenv("KCONFIG_ALLCONFIG");
|
||||
if (name && !stat(name, &tmpstat)) {
|
||||
conf_read_simple(name, S_DEF_USER);
|
||||
break;
|
||||
}
|
||||
switch (input_mode) {
|
||||
case set_no: name = "allno.config"; break;
|
||||
case set_mod: name = "allmod.config"; break;
|
||||
case set_yes: name = "allyes.config"; break;
|
||||
case set_random: name = "allrandom.config"; break;
|
||||
case allnoconfig: name = "allno.config"; break;
|
||||
case allyesconfig: name = "allyes.config"; break;
|
||||
case allmodconfig: name = "allmod.config"; break;
|
||||
case alldefconfig: name = "alldef.config"; break;
|
||||
case randconfig: name = "allrandom.config"; break;
|
||||
default: break;
|
||||
}
|
||||
if (!stat(name, &tmpstat))
|
||||
@@ -557,7 +570,7 @@ int main(int ac, char **av)
|
||||
name = getenv("KCONFIG_NOSILENTUPDATE");
|
||||
if (name && *name) {
|
||||
fprintf(stderr,
|
||||
_("\n*** Kernel configuration requires explicit update.\n\n"));
|
||||
_("\n*** The configuration requires explicit update.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -565,33 +578,42 @@ int main(int ac, char **av)
|
||||
}
|
||||
|
||||
switch (input_mode) {
|
||||
case set_no:
|
||||
case allnoconfig:
|
||||
conf_set_all_new_symbols(def_no);
|
||||
break;
|
||||
case set_yes:
|
||||
case allyesconfig:
|
||||
conf_set_all_new_symbols(def_yes);
|
||||
break;
|
||||
case set_mod:
|
||||
case allmodconfig:
|
||||
conf_set_all_new_symbols(def_mod);
|
||||
break;
|
||||
case set_random:
|
||||
conf_set_all_new_symbols(def_random);
|
||||
break;
|
||||
case set_default:
|
||||
case alldefconfig:
|
||||
conf_set_all_new_symbols(def_default);
|
||||
break;
|
||||
case ask_new:
|
||||
case ask_all:
|
||||
case randconfig:
|
||||
conf_set_all_new_symbols(def_random);
|
||||
break;
|
||||
case defconfig:
|
||||
conf_set_all_new_symbols(def_default);
|
||||
break;
|
||||
case savedefconfig:
|
||||
break;
|
||||
case oldaskconfig:
|
||||
rootEntry = &rootmenu;
|
||||
conf(&rootmenu);
|
||||
input_mode = ask_silent;
|
||||
input_mode = silentoldconfig;
|
||||
/* fall through */
|
||||
case ask_silent:
|
||||
case oldconfig:
|
||||
case listnewconfig:
|
||||
case oldnoconfig:
|
||||
case silentoldconfig:
|
||||
/* Update until a loop caused no more changes */
|
||||
do {
|
||||
conf_cnt = 0;
|
||||
check_conf(&rootmenu);
|
||||
} while (conf_cnt);
|
||||
} while (conf_cnt &&
|
||||
(input_mode != listnewconfig &&
|
||||
input_mode != oldnoconfig));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -600,18 +622,35 @@ int main(int ac, char **av)
|
||||
* All other commands are only used to generate a config.
|
||||
*/
|
||||
if (conf_get_changed() && conf_write(NULL)) {
|
||||
fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
|
||||
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
||||
exit(1);
|
||||
}
|
||||
if (conf_write_autoconf()) {
|
||||
fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
|
||||
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
} else if (input_mode == savedefconfig) {
|
||||
if (conf_write_defconfig(defconfig_file)) {
|
||||
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
|
||||
defconfig_file);
|
||||
return 1;
|
||||
}
|
||||
} else if (input_mode != listnewconfig) {
|
||||
if (conf_write(NULL)) {
|
||||
fprintf(stderr, _("\n*** Error during writing of the kernel configuration.\n\n"));
|
||||
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Helper function to facilitate fgets() by Jean Sacren.
|
||||
*/
|
||||
void xfgets(str, size, in)
|
||||
char *str;
|
||||
int size;
|
||||
FILE *in;
|
||||
{
|
||||
if (fgets(str, size, in) == NULL)
|
||||
fprintf(stderr, "\nError in reading or end of file.\n");
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -18,6 +19,9 @@
|
||||
static void conf_warning(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
static void conf_message(const char *fmt, ...)
|
||||
__attribute__ ((format (printf, 1, 2)));
|
||||
|
||||
static const char *conf_filename;
|
||||
static int conf_lineno, conf_warnings, conf_unsaved;
|
||||
|
||||
@@ -34,6 +38,29 @@ static void conf_warning(const char *fmt, ...)
|
||||
conf_warnings++;
|
||||
}
|
||||
|
||||
static void conf_default_message_callback(const char *fmt, va_list ap)
|
||||
{
|
||||
printf("#\n# ");
|
||||
vprintf(fmt, ap);
|
||||
printf("\n#\n");
|
||||
}
|
||||
|
||||
static void (*conf_message_callback) (const char *fmt, va_list ap) =
|
||||
conf_default_message_callback;
|
||||
void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
|
||||
{
|
||||
conf_message_callback = fn;
|
||||
}
|
||||
|
||||
static void conf_message(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (conf_message_callback)
|
||||
conf_message_callback(fmt, ap);
|
||||
}
|
||||
|
||||
const char *conf_get_configname(void)
|
||||
{
|
||||
char *name = getenv("KCONFIG_CONFIG");
|
||||
@@ -170,8 +197,11 @@ int conf_read_simple(const char *name, int def)
|
||||
if (in)
|
||||
goto load;
|
||||
sym_add_change_count(1);
|
||||
if (!sym_defconfig_list)
|
||||
if (!sym_defconfig_list) {
|
||||
if (modules_sym)
|
||||
sym_calc_value(modules_sym);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for_all_defaults(sym_defconfig_list, prop) {
|
||||
if (expr_calc_value(prop->visible.expr) == no ||
|
||||
@@ -180,9 +210,8 @@ int conf_read_simple(const char *name, int def)
|
||||
name = conf_expand_value(prop->expr->left.sym->name);
|
||||
in = zconf_fopen(name);
|
||||
if (in) {
|
||||
printf(_("#\n"
|
||||
"# using defaults found in %s\n"
|
||||
"#\n"), name);
|
||||
conf_message(_("using defaults found in %s"),
|
||||
name);
|
||||
goto load;
|
||||
}
|
||||
}
|
||||
@@ -217,24 +246,23 @@ load:
|
||||
while (fgets(line, sizeof(line), in)) {
|
||||
conf_lineno++;
|
||||
sym = NULL;
|
||||
switch (line[0]) {
|
||||
case '#':
|
||||
if (memcmp(line + 2, "CONFIG_", 7))
|
||||
if (line[0] == '#') {
|
||||
if (memcmp(line + 2, CONFIG_, strlen(CONFIG_)))
|
||||
continue;
|
||||
p = strchr(line + 9, ' ');
|
||||
p = strchr(line + 2 + strlen(CONFIG_), ' ');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
if (strncmp(p, "is not set", 10))
|
||||
continue;
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + 9);
|
||||
sym = sym_find(line + 2 + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
sym_add_change_count(1);
|
||||
break;
|
||||
goto setsym;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 9, 0);
|
||||
sym = sym_lookup(line + 2 + strlen(CONFIG_), 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_BOOLEAN;
|
||||
}
|
||||
@@ -250,13 +278,8 @@ load:
|
||||
default:
|
||||
;
|
||||
}
|
||||
break;
|
||||
case 'C':
|
||||
if (memcmp(line, "CONFIG_", 7)) {
|
||||
conf_warning("unexpected data");
|
||||
continue;
|
||||
}
|
||||
p = strchr(line + 7, '=');
|
||||
} else if (memcmp(line, CONFIG_, strlen(CONFIG_)) == 0) {
|
||||
p = strchr(line + strlen(CONFIG_), '=');
|
||||
if (!p)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
@@ -267,13 +290,13 @@ load:
|
||||
*p2 = 0;
|
||||
}
|
||||
if (def == S_DEF_USER) {
|
||||
sym = sym_find(line + 7);
|
||||
sym = sym_find(line + strlen(CONFIG_));
|
||||
if (!sym) {
|
||||
sym_add_change_count(1);
|
||||
break;
|
||||
goto setsym;
|
||||
}
|
||||
} else {
|
||||
sym = sym_lookup(line + 7, 0);
|
||||
sym = sym_lookup(line + strlen(CONFIG_), 0);
|
||||
if (sym->type == S_UNKNOWN)
|
||||
sym->type = S_OTHER;
|
||||
}
|
||||
@@ -282,14 +305,12 @@ load:
|
||||
}
|
||||
if (conf_set_sym_val(sym, def, def_flags, p))
|
||||
continue;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
break;
|
||||
default:
|
||||
conf_warning("unexpected data");
|
||||
} else {
|
||||
if (line[0] != '\r' && line[0] != '\n')
|
||||
conf_warning("unexpected data");
|
||||
continue;
|
||||
}
|
||||
setsym:
|
||||
if (sym && sym_is_choice_value(sym)) {
|
||||
struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
switch (sym->def[def].tri) {
|
||||
@@ -396,15 +417,151 @@ int conf_read(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write a S_STRING */
|
||||
static void conf_write_string(bool headerfile, const char *name,
|
||||
const char *str, FILE *out)
|
||||
{
|
||||
int l;
|
||||
if (headerfile)
|
||||
fprintf(out, "#define %s%s \"", CONFIG_, name);
|
||||
else
|
||||
fprintf(out, "%s%s=\"", CONFIG_, name);
|
||||
|
||||
while (1) {
|
||||
l = strcspn(str, "\"\\");
|
||||
if (l) {
|
||||
xfwrite(str, l, 1, out);
|
||||
str += l;
|
||||
}
|
||||
if (!*str)
|
||||
break;
|
||||
fprintf(out, "\\%c", *str++);
|
||||
}
|
||||
fputs("\"\n", out);
|
||||
}
|
||||
|
||||
static void conf_write_symbol(struct symbol *sym, enum symbol_type type,
|
||||
FILE *out, bool write_no)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (sym_get_tristate_value(sym)) {
|
||||
case no:
|
||||
if (write_no)
|
||||
fprintf(out, "# %s%s is not set\n",
|
||||
CONFIG_, sym->name);
|
||||
break;
|
||||
case mod:
|
||||
fprintf(out, "%s%s=m\n", CONFIG_, sym->name);
|
||||
break;
|
||||
case yes:
|
||||
fprintf(out, "%s%s=y\n", CONFIG_, sym->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case S_STRING:
|
||||
conf_write_string(false, sym->name, sym_get_string_value(sym), out);
|
||||
break;
|
||||
case S_HEX:
|
||||
case S_INT:
|
||||
str = sym_get_string_value(sym);
|
||||
fprintf(out, "%s%s=%s\n", CONFIG_, sym->name, str);
|
||||
break;
|
||||
case S_OTHER:
|
||||
case S_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write out a minimal config.
|
||||
* All values that has default values are skipped as this is redundant.
|
||||
*/
|
||||
int conf_write_defconfig(const char *filename)
|
||||
{
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
FILE *out;
|
||||
|
||||
out = fopen(filename, "w");
|
||||
if (!out)
|
||||
return 1;
|
||||
|
||||
sym_clear_all_valid();
|
||||
|
||||
/* Traverse all menus to find all relevant symbols */
|
||||
menu = rootmenu.list;
|
||||
|
||||
while (menu != NULL)
|
||||
{
|
||||
sym = menu->sym;
|
||||
if (sym == NULL) {
|
||||
if (!menu_is_visible(menu))
|
||||
goto next_menu;
|
||||
} else if (!sym_is_choice(sym)) {
|
||||
sym_calc_value(sym);
|
||||
if (!(sym->flags & SYMBOL_WRITE))
|
||||
goto next_menu;
|
||||
sym->flags &= ~SYMBOL_WRITE;
|
||||
/* If we cannot change the symbol - skip */
|
||||
if (!sym_is_changable(sym))
|
||||
goto next_menu;
|
||||
/* If symbol equals to default value - skip */
|
||||
if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
|
||||
goto next_menu;
|
||||
|
||||
/*
|
||||
* If symbol is a choice value and equals to the
|
||||
* default for a choice - skip.
|
||||
* But only if value is bool and equal to "y" and
|
||||
* choice is not "optional".
|
||||
* (If choice is "optional" then all values can be "n")
|
||||
*/
|
||||
if (sym_is_choice_value(sym)) {
|
||||
struct symbol *cs;
|
||||
struct symbol *ds;
|
||||
|
||||
cs = prop_get_symbol(sym_get_choice_prop(sym));
|
||||
ds = sym_choice_default(cs);
|
||||
if (!sym_is_optional(cs) && sym == ds) {
|
||||
if ((sym->type == S_BOOLEAN) &&
|
||||
sym_get_tristate_value(sym) == yes)
|
||||
goto next_menu;
|
||||
}
|
||||
}
|
||||
conf_write_symbol(sym, sym->type, out, true);
|
||||
}
|
||||
next_menu:
|
||||
if (menu->list != NULL) {
|
||||
menu = menu->list;
|
||||
}
|
||||
else if (menu->next != NULL) {
|
||||
menu = menu->next;
|
||||
} else {
|
||||
while ((menu = menu->parent)) {
|
||||
if (menu->next != NULL) {
|
||||
menu = menu->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(out);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int conf_write(const char *name)
|
||||
{
|
||||
FILE *out;
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
const char *basename;
|
||||
char dirname[128], tmpname[128], newname[128];
|
||||
int type, l;
|
||||
const char *str;
|
||||
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
|
||||
enum symbol_type type;
|
||||
time_t now;
|
||||
int use_timestamp = 1;
|
||||
char *env;
|
||||
@@ -443,8 +600,6 @@ int conf_write(const char *name)
|
||||
if (!out)
|
||||
return 1;
|
||||
|
||||
sym = sym_lookup("KERNELVERSION", 0);
|
||||
sym_calc_value(sym);
|
||||
time(&now);
|
||||
env = getenv("KCONFIG_NOTIMESTAMP");
|
||||
if (env && *env)
|
||||
@@ -452,10 +607,10 @@ int conf_write(const char *name)
|
||||
|
||||
fprintf(out, _("#\n"
|
||||
"# Automatically generated make config: don't edit\n"
|
||||
"# Linux kernel version: %s\n"
|
||||
"# %s\n"
|
||||
"%s%s"
|
||||
"#\n"),
|
||||
sym_get_string_value(sym),
|
||||
rootmenu.prompt->text,
|
||||
use_timestamp ? "# " : "",
|
||||
use_timestamp ? ctime(&now) : "");
|
||||
|
||||
@@ -484,50 +639,11 @@ int conf_write(const char *name)
|
||||
if (modules_sym->curr.tri == no)
|
||||
type = S_BOOLEAN;
|
||||
}
|
||||
switch (type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (sym_get_tristate_value(sym)) {
|
||||
case no:
|
||||
fprintf(out, "# CONFIG_%s is not set\n", sym->name);
|
||||
break;
|
||||
case mod:
|
||||
fprintf(out, "CONFIG_%s=m\n", sym->name);
|
||||
break;
|
||||
case yes:
|
||||
fprintf(out, "CONFIG_%s=y\n", sym->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case S_STRING:
|
||||
str = sym_get_string_value(sym);
|
||||
fprintf(out, "CONFIG_%s=\"", sym->name);
|
||||
while (1) {
|
||||
l = strcspn(str, "\"\\");
|
||||
if (l) {
|
||||
fwrite(str, l, 1, out);
|
||||
str += l;
|
||||
}
|
||||
if (!*str)
|
||||
break;
|
||||
fprintf(out, "\\%c", *str++);
|
||||
}
|
||||
fputs("\"\n", out);
|
||||
break;
|
||||
case S_HEX:
|
||||
str = sym_get_string_value(sym);
|
||||
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
|
||||
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
|
||||
break;
|
||||
}
|
||||
case S_INT:
|
||||
str = sym_get_string_value(sym);
|
||||
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
|
||||
break;
|
||||
}
|
||||
/* Write config symbol to file */
|
||||
conf_write_symbol(sym, type, out, true);
|
||||
}
|
||||
|
||||
next:
|
||||
next:
|
||||
if (menu->list) {
|
||||
menu = menu->list;
|
||||
continue;
|
||||
@@ -551,9 +667,7 @@ int conf_write(const char *name)
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf(_("#\n"
|
||||
"# configuration written to %s\n"
|
||||
"#\n"), newname);
|
||||
conf_message(_("configuration written to %s"), newname);
|
||||
|
||||
sym_set_change_count(0);
|
||||
|
||||
@@ -563,7 +677,7 @@ int conf_write(const char *name)
|
||||
static int conf_split_config(void)
|
||||
{
|
||||
const char *name;
|
||||
char path[128];
|
||||
char path[PATH_MAX+1];
|
||||
char *s, *d, c;
|
||||
struct symbol *sym;
|
||||
struct stat sb;
|
||||
@@ -679,7 +793,7 @@ int conf_write_autoconf(void)
|
||||
const char *name;
|
||||
FILE *out, *tristate, *out_h;
|
||||
time_t now;
|
||||
int i, l;
|
||||
int i;
|
||||
|
||||
sym_clear_all_valid();
|
||||
|
||||
@@ -705,30 +819,33 @@ int conf_write_autoconf(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
sym = sym_lookup("KERNELVERSION", 0);
|
||||
sym_calc_value(sym);
|
||||
time(&now);
|
||||
fprintf(out, "#\n"
|
||||
"# Automatically generated make config: don't edit\n"
|
||||
"# Linux kernel version: %s\n"
|
||||
"# %s\n"
|
||||
"# %s"
|
||||
"#\n",
|
||||
sym_get_string_value(sym), ctime(&now));
|
||||
rootmenu.prompt->text, ctime(&now));
|
||||
fprintf(tristate, "#\n"
|
||||
"# Automatically generated - do not edit\n"
|
||||
"\n");
|
||||
fprintf(out_h, "/*\n"
|
||||
" * Automatically generated C config: don't edit\n"
|
||||
" * Linux kernel version: %s\n"
|
||||
" * %s\n"
|
||||
" * %s"
|
||||
" */\n"
|
||||
"#define AUTOCONF_INCLUDED\n",
|
||||
sym_get_string_value(sym), ctime(&now));
|
||||
rootmenu.prompt->text, ctime(&now));
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
sym_calc_value(sym);
|
||||
if (!(sym->flags & SYMBOL_WRITE) || !sym->name)
|
||||
continue;
|
||||
|
||||
/* write symbol to config file */
|
||||
conf_write_symbol(sym, sym->type, out, false);
|
||||
|
||||
/* update autoconf and tristate files */
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
@@ -736,50 +853,34 @@ int conf_write_autoconf(void)
|
||||
case no:
|
||||
break;
|
||||
case mod:
|
||||
fprintf(out, "CONFIG_%s=m\n", sym->name);
|
||||
fprintf(tristate, "CONFIG_%s=M\n", sym->name);
|
||||
fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
|
||||
fprintf(tristate, "%s%s=M\n",
|
||||
CONFIG_, sym->name);
|
||||
fprintf(out_h, "#define %s%s_MODULE 1\n",
|
||||
CONFIG_, sym->name);
|
||||
break;
|
||||
case yes:
|
||||
fprintf(out, "CONFIG_%s=y\n", sym->name);
|
||||
if (sym->type == S_TRISTATE)
|
||||
fprintf(tristate, "CONFIG_%s=Y\n",
|
||||
sym->name);
|
||||
fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
|
||||
fprintf(tristate,"%s%s=Y\n",
|
||||
CONFIG_, sym->name);
|
||||
fprintf(out_h, "#define %s%s 1\n",
|
||||
CONFIG_, sym->name);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case S_STRING:
|
||||
str = sym_get_string_value(sym);
|
||||
fprintf(out, "CONFIG_%s=\"", sym->name);
|
||||
fprintf(out_h, "#define CONFIG_%s \"", sym->name);
|
||||
while (1) {
|
||||
l = strcspn(str, "\"\\");
|
||||
if (l) {
|
||||
fwrite(str, l, 1, out);
|
||||
fwrite(str, l, 1, out_h);
|
||||
str += l;
|
||||
}
|
||||
if (!*str)
|
||||
break;
|
||||
fprintf(out, "\\%c", *str);
|
||||
fprintf(out_h, "\\%c", *str);
|
||||
str++;
|
||||
}
|
||||
fputs("\"\n", out);
|
||||
fputs("\"\n", out_h);
|
||||
conf_write_string(true, sym->name, sym_get_string_value(sym), out_h);
|
||||
break;
|
||||
case S_HEX:
|
||||
str = sym_get_string_value(sym);
|
||||
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
|
||||
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
|
||||
fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
|
||||
fprintf(out_h, "#define %s%s 0x%s\n",
|
||||
CONFIG_, sym->name, str);
|
||||
break;
|
||||
}
|
||||
case S_INT:
|
||||
str = sym_get_string_value(sym);
|
||||
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
|
||||
fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
|
||||
fprintf(out_h, "#define %s%s %s\n",
|
||||
CONFIG_, sym->name, str);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -837,13 +938,73 @@ void conf_set_changed_callback(void (*fn)(void))
|
||||
conf_changed_callback = fn;
|
||||
}
|
||||
|
||||
static void randomize_choice_values(struct symbol *csym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *sym;
|
||||
struct expr *e;
|
||||
int cnt, def;
|
||||
|
||||
/*
|
||||
* If choice is mod then we may have more items slected
|
||||
* and if no then no-one.
|
||||
* In both cases stop.
|
||||
*/
|
||||
if (csym->curr.tri != yes)
|
||||
return;
|
||||
|
||||
prop = sym_get_choice_prop(csym);
|
||||
|
||||
/* count entries in choice block */
|
||||
cnt = 0;
|
||||
expr_list_for_each_sym(prop->expr, e, sym)
|
||||
cnt++;
|
||||
|
||||
/*
|
||||
* find a random value and set it to yes,
|
||||
* set the rest to no so we have only one set
|
||||
*/
|
||||
def = (rand() % cnt);
|
||||
|
||||
cnt = 0;
|
||||
expr_list_for_each_sym(prop->expr, e, sym) {
|
||||
if (def == cnt++) {
|
||||
sym->def[S_DEF_USER].tri = yes;
|
||||
csym->def[S_DEF_USER].val = sym;
|
||||
}
|
||||
else {
|
||||
sym->def[S_DEF_USER].tri = no;
|
||||
}
|
||||
}
|
||||
csym->flags |= SYMBOL_DEF_USER;
|
||||
/* clear VALID to get value calculated */
|
||||
csym->flags &= ~(SYMBOL_VALID);
|
||||
}
|
||||
|
||||
static void set_all_choice_values(struct symbol *csym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *sym;
|
||||
struct expr *e;
|
||||
|
||||
prop = sym_get_choice_prop(csym);
|
||||
|
||||
/*
|
||||
* Set all non-assinged choice values to no
|
||||
*/
|
||||
expr_list_for_each_sym(prop->expr, e, sym) {
|
||||
if (!sym_has_value(sym))
|
||||
sym->def[S_DEF_USER].tri = no;
|
||||
}
|
||||
csym->flags |= SYMBOL_DEF_USER;
|
||||
/* clear VALID to get value calculated */
|
||||
csym->flags &= ~(SYMBOL_VALID);
|
||||
}
|
||||
|
||||
void conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
{
|
||||
struct symbol *sym, *csym;
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
int i, cnt, def;
|
||||
int i, cnt;
|
||||
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_has_value(sym))
|
||||
@@ -862,7 +1023,8 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
sym->def[S_DEF_USER].tri = no;
|
||||
break;
|
||||
case def_random:
|
||||
sym->def[S_DEF_USER].tri = (tristate)(rand() % 3);
|
||||
cnt = sym_get_type(sym) == S_TRISTATE ? 3 : 2;
|
||||
sym->def[S_DEF_USER].tri = (tristate)(rand() % cnt);
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
@@ -878,8 +1040,6 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
|
||||
sym_clear_all_valid();
|
||||
|
||||
if (mode != def_random)
|
||||
return;
|
||||
/*
|
||||
* We have different type of choice blocks.
|
||||
* If curr.tri equal to mod then we can select several
|
||||
@@ -894,35 +1054,9 @@ void conf_set_all_new_symbols(enum conf_def_mode mode)
|
||||
continue;
|
||||
|
||||
sym_calc_value(csym);
|
||||
|
||||
if (csym->curr.tri != yes)
|
||||
continue;
|
||||
|
||||
prop = sym_get_choice_prop(csym);
|
||||
|
||||
/* count entries in choice block */
|
||||
cnt = 0;
|
||||
expr_list_for_each_sym(prop->expr, e, sym)
|
||||
cnt++;
|
||||
|
||||
/*
|
||||
* find a random value and set it to yes,
|
||||
* set the rest to no so we have only one set
|
||||
*/
|
||||
def = (rand() % cnt);
|
||||
|
||||
cnt = 0;
|
||||
expr_list_for_each_sym(prop->expr, e, sym) {
|
||||
if (def == cnt++) {
|
||||
sym->def[S_DEF_USER].tri = yes;
|
||||
csym->def[S_DEF_USER].val = sym;
|
||||
}
|
||||
else {
|
||||
sym->def[S_DEF_USER].tri = no;
|
||||
}
|
||||
}
|
||||
csym->flags |= SYMBOL_DEF_USER;
|
||||
/* clear VALID to get value calculated */
|
||||
csym->flags &= ~(SYMBOL_VALID);
|
||||
if (mode == def_random)
|
||||
randomize_choice_values(csym);
|
||||
else
|
||||
set_all_choice_values(csym);
|
||||
}
|
||||
}
|
||||
|
@@ -1087,7 +1087,7 @@ void expr_print(struct expr *e, void (*fn)(void *, struct symbol *, const char *
|
||||
|
||||
static void expr_print_file_helper(void *data, struct symbol *sym, const char *str)
|
||||
{
|
||||
fwrite(str, strlen(str), 1, data);
|
||||
xfwrite(str, strlen(str), 1, data);
|
||||
}
|
||||
|
||||
void expr_fprint(struct expr *e, FILE *out)
|
||||
@@ -1121,7 +1121,7 @@ static void expr_print_gstr_helper(void *data, struct symbol *sym, const char *s
|
||||
}
|
||||
|
||||
str_append(gs, str);
|
||||
if (sym)
|
||||
if (sym && sym->type != S_UNKNOWN)
|
||||
str_printf(gs, " [=%s]", sym_str);
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,7 @@ extern "C" {
|
||||
struct file {
|
||||
struct file *next;
|
||||
struct file *parent;
|
||||
char *name;
|
||||
const char *name;
|
||||
int lineno;
|
||||
int flags;
|
||||
};
|
||||
@@ -83,6 +83,7 @@ struct symbol {
|
||||
tristate visible;
|
||||
int flags;
|
||||
struct property *prop;
|
||||
struct expr_value dir_dep;
|
||||
struct expr_value rev_dep;
|
||||
};
|
||||
|
||||
@@ -131,6 +132,7 @@ enum prop_type {
|
||||
P_SELECT, /* select BAR */
|
||||
P_RANGE, /* range 7..100 (for a symbol) */
|
||||
P_ENV, /* value from environment variable */
|
||||
P_SYMBOL, /* where a symbol is defined */
|
||||
};
|
||||
|
||||
struct property {
|
||||
|
@@ -133,7 +133,6 @@ void init_main_window(const gchar * glade_file)
|
||||
GladeXML *xml;
|
||||
GtkWidget *widget;
|
||||
GtkTextBuffer *txtbuf;
|
||||
char title[256];
|
||||
GtkStyle *style;
|
||||
|
||||
xml = glade_xml_new(glade_file, "window1", NULL);
|
||||
@@ -210,9 +209,7 @@ void init_main_window(const gchar * glade_file)
|
||||
/*"style", PANGO_STYLE_OBLIQUE, */
|
||||
NULL);
|
||||
|
||||
sprintf(title, _("Linux Kernel v%s Configuration"),
|
||||
getenv("KERNELVERSION"));
|
||||
gtk_window_set_title(GTK_WINDOW(main_wnd), title);
|
||||
gtk_window_set_title(GTK_WINDOW(main_wnd), rootmenu.prompt->text);
|
||||
|
||||
gtk_widget_show(main_wnd);
|
||||
}
|
||||
@@ -671,8 +668,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
const gchar *intro_text = _(
|
||||
"Welcome to gkc, the GTK+ graphical kernel configuration tool\n"
|
||||
"for Linux.\n"
|
||||
"Welcome to gkc, the GTK+ graphical configuration tool\n"
|
||||
"For each option, a blank box indicates the feature is disabled, a\n"
|
||||
"check indicates it is enabled, and a dot indicates that it is to\n"
|
||||
"be compiled as a module. Clicking on the box will cycle through the three states.\n"
|
||||
@@ -1114,7 +1110,7 @@ static gchar **fill_row(struct menu *menu)
|
||||
|
||||
row[COL_OPTION] =
|
||||
g_strdup_printf("%s %s", _(menu_get_prompt(menu)),
|
||||
sym && sym_has_value(sym) ? "(NEW)" : "");
|
||||
sym && !sym_has_value(sym) ? "(NEW)" : "");
|
||||
|
||||
if (opt_mode == OPT_ALL && !menu_is_visible(menu))
|
||||
row[COL_COLOR] = g_strdup("DarkGray");
|
||||
@@ -1343,7 +1339,8 @@ static void update_tree(struct menu *src, GtkTreeIter * dst)
|
||||
#endif
|
||||
|
||||
if ((opt_mode == OPT_NORMAL && !menu_is_visible(child1)) ||
|
||||
(opt_mode == OPT_PROMPT && !menu_has_prompt(child1))) {
|
||||
(opt_mode == OPT_PROMPT && !menu_has_prompt(child1)) ||
|
||||
(opt_mode == OPT_ALL && !menu_get_prompt(child1))) {
|
||||
|
||||
/* remove node */
|
||||
if (gtktree_iter_find_node(dst, menu1) != NULL) {
|
||||
@@ -1425,7 +1422,7 @@ static void display_tree(struct menu *menu)
|
||||
|
||||
if ((opt_mode == OPT_NORMAL && menu_is_visible(child)) ||
|
||||
(opt_mode == OPT_PROMPT && menu_has_prompt(child)) ||
|
||||
(opt_mode == OPT_ALL))
|
||||
(opt_mode == OPT_ALL && menu_get_prompt(child)))
|
||||
place_node(child, fill_row(child));
|
||||
#ifdef DEBUG
|
||||
printf("%*c%s: ", indent, ' ', menu_get_prompt(child));
|
||||
@@ -1530,12 +1527,6 @@ int main(int ac, char *av[])
|
||||
else
|
||||
glade_file = g_strconcat(g_get_current_dir(), "/", av[0], ".glade", NULL);
|
||||
|
||||
/* Load the interface and connect signals */
|
||||
init_main_window(glade_file);
|
||||
init_tree_model();
|
||||
init_left_tree();
|
||||
init_right_tree();
|
||||
|
||||
/* Conf stuffs */
|
||||
if (ac > 1 && av[1][0] == '-') {
|
||||
switch (av[1][1]) {
|
||||
@@ -1555,6 +1546,12 @@ int main(int ac, char *av[])
|
||||
fixup_rootmenu(&rootmenu);
|
||||
conf_read(NULL);
|
||||
|
||||
/* Load the interface and connect signals */
|
||||
init_main_window(glade_file);
|
||||
init_tree_model();
|
||||
init_left_tree();
|
||||
init_right_tree();
|
||||
|
||||
switch (view_mode) {
|
||||
case SINGLE_VIEW:
|
||||
display_tree_part();
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
||||
|
||||
<glade-interface>
|
||||
|
||||
|
@@ -63,11 +63,11 @@ next:
|
||||
|
||||
struct file_line {
|
||||
struct file_line *next;
|
||||
char* file;
|
||||
int lineno;
|
||||
const char *file;
|
||||
int lineno;
|
||||
};
|
||||
|
||||
static struct file_line *file_line__new(char *file, int lineno)
|
||||
static struct file_line *file_line__new(const char *file, int lineno)
|
||||
{
|
||||
struct file_line *self = malloc(sizeof(*self));
|
||||
|
||||
@@ -90,7 +90,8 @@ struct message {
|
||||
|
||||
static struct message *message__list;
|
||||
|
||||
static struct message *message__new(const char *msg, char *option, char *file, int lineno)
|
||||
static struct message *message__new(const char *msg, char *option,
|
||||
const char *file, int lineno)
|
||||
{
|
||||
struct message *self = malloc(sizeof(*self));
|
||||
|
||||
@@ -130,7 +131,8 @@ static struct message *mesage__find(const char *msg)
|
||||
return m;
|
||||
}
|
||||
|
||||
static int message__add_file_line(struct message *self, char *file, int lineno)
|
||||
static int message__add_file_line(struct message *self, const char *file,
|
||||
int lineno)
|
||||
{
|
||||
int rc = -1;
|
||||
struct file_line *fl = file_line__new(file, lineno);
|
||||
@@ -145,7 +147,8 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int message__add(const char *msg, char *option, char *file, int lineno)
|
||||
static int message__add(const char *msg, char *option, const char *file,
|
||||
int lineno)
|
||||
{
|
||||
int rc = 0;
|
||||
char bf[16384];
|
||||
|
@@ -2373,9 +2373,10 @@ void zconf_nextfile(const char *name)
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
||||
current_buf->state = YY_CURRENT_BUFFER;
|
||||
zconfin = zconf_fopen(name);
|
||||
zconfin = zconf_fopen(file->name);
|
||||
if (!zconfin) {
|
||||
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
|
||||
printf("%s:%d: can't open file \"%s\"\n",
|
||||
zconf_curname(), zconf_lineno(), file->name);
|
||||
exit(1);
|
||||
}
|
||||
zconf_switch_to_buffer(zconf_create_buffer(zconfin,YY_BUF_SIZE));
|
||||
@@ -2422,7 +2423,7 @@ int zconf_lineno(void)
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
char *zconf_curname(void)
|
||||
const char *zconf_curname(void)
|
||||
{
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
||||
|
@@ -31,12 +31,18 @@ extern "C" {
|
||||
|
||||
#define SRCTREE "srctree"
|
||||
|
||||
#ifndef PACKAGE
|
||||
#define PACKAGE "linux"
|
||||
#endif
|
||||
|
||||
#define LOCALEDIR "/usr/share/locale"
|
||||
|
||||
#define _(text) gettext(text)
|
||||
#define N_(text) (text)
|
||||
|
||||
#ifndef CONFIG_
|
||||
#define CONFIG_ "CONFIG_"
|
||||
#endif
|
||||
|
||||
#define TF_COMMAND 0x0001
|
||||
#define TF_PARAM 0x0002
|
||||
@@ -70,7 +76,10 @@ FILE *zconf_fopen(const char *name);
|
||||
void zconf_initscan(const char *name);
|
||||
void zconf_nextfile(const char *name);
|
||||
int zconf_lineno(void);
|
||||
char *zconf_curname(void);
|
||||
const char *zconf_curname(void);
|
||||
|
||||
/* conf.c */
|
||||
void xfgets(char *str, int size, FILE *in);
|
||||
|
||||
/* confdata.c */
|
||||
const char *conf_get_configname(void);
|
||||
@@ -80,6 +89,13 @@ void sym_set_change_count(int count);
|
||||
void sym_add_change_count(int count);
|
||||
void conf_set_all_new_symbols(enum conf_def_mode mode);
|
||||
|
||||
/* confdata.c and expr.c */
|
||||
static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out)
|
||||
{
|
||||
if (fwrite(str, len, count, out) < count)
|
||||
fprintf(stderr, "\nError in writing or end of file.\n");
|
||||
}
|
||||
|
||||
/* kconfig_load.c */
|
||||
void kconfig_load(void);
|
||||
|
||||
@@ -126,6 +142,8 @@ void sym_init(void);
|
||||
void sym_clear_all_valid(void);
|
||||
void sym_set_all_changed(void);
|
||||
void sym_set_changed(struct symbol *sym);
|
||||
struct symbol *sym_choice_default(struct symbol *sym);
|
||||
const char *sym_get_string_default(struct symbol *sym);
|
||||
struct symbol *sym_check_deps(struct symbol *sym);
|
||||
struct property *prop_alloc(enum prop_type type, struct symbol *sym);
|
||||
struct symbol *prop_get_symbol(struct property *prop);
|
||||
|
@@ -1,12 +1,15 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
/* confdata.c */
|
||||
P(conf_parse,void,(const char *name));
|
||||
P(conf_read,int,(const char *name));
|
||||
P(conf_read_simple,int,(const char *name, int));
|
||||
P(conf_write_defconfig,int,(const char *name));
|
||||
P(conf_write,int,(const char *name));
|
||||
P(conf_write_autoconf,int,(void));
|
||||
P(conf_get_changed,bool,(void));
|
||||
P(conf_set_changed_callback, void,(void (*fn)(void)));
|
||||
P(conf_set_message_callback, void,(void (*fn)(const char *fmt, va_list ap)));
|
||||
|
||||
/* menu.c */
|
||||
P(rootmenu,struct menu,);
|
||||
@@ -27,6 +30,7 @@ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]);
|
||||
|
||||
P(sym_lookup,struct symbol *,(const char *name, int flags));
|
||||
P(sym_find,struct symbol *,(const char *name));
|
||||
P(sym_expand_string_value,const char *,(const char *in));
|
||||
P(sym_re_search,struct symbol **,(const char *pattern));
|
||||
P(sym_type_name,const char *,(enum symbol_type type));
|
||||
P(sym_calc_value,void,(struct symbol *sym));
|
||||
|
@@ -23,6 +23,8 @@ ccflags()
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses.h>"'
|
||||
elif [ -f /usr/include/ncurses/curses.h ]; then
|
||||
echo '-I/usr/include/ncurses -DCURSES_LOC="<ncurses/curses.h>"'
|
||||
elif [ -f /usr/include/ncursesw/curses.h ]; then
|
||||
echo '-I/usr/include/ncursesw -DCURSES_LOC="<ncursesw/curses.h>"'
|
||||
elif [ -f /usr/include/ncurses.h ]; then
|
||||
echo '-DCURSES_LOC="<ncurses.h>"'
|
||||
else
|
||||
|
@@ -31,6 +31,10 @@ static int list_width, check_x, item_x;
|
||||
static void print_item(WINDOW * win, int choice, int selected)
|
||||
{
|
||||
int i;
|
||||
char *list_item = malloc(list_width + 1);
|
||||
|
||||
strncpy(list_item, item_str(), list_width - item_x);
|
||||
list_item[list_width - item_x] = '\0';
|
||||
|
||||
/* Clear 'residue' of last item */
|
||||
wattrset(win, dlg.menubox.atr);
|
||||
@@ -45,13 +49,14 @@ static void print_item(WINDOW * win, int choice, int selected)
|
||||
wprintw(win, "(%c)", item_is_tag('X') ? 'X' : ' ');
|
||||
|
||||
wattrset(win, selected ? dlg.tag_selected.atr : dlg.tag.atr);
|
||||
mvwaddch(win, choice, item_x, item_str()[0]);
|
||||
mvwaddch(win, choice, item_x, list_item[0]);
|
||||
wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
|
||||
waddstr(win, (char *)item_str() + 1);
|
||||
waddstr(win, list_item + 1);
|
||||
if (selected) {
|
||||
wmove(win, choice, check_x + 1);
|
||||
wrefresh(win);
|
||||
}
|
||||
free(list_item);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -175,6 +180,7 @@ do_resize:
|
||||
check_x = 0;
|
||||
item_foreach()
|
||||
check_x = MAX(check_x, strlen(item_str()) + 4);
|
||||
check_x = MIN(check_x, list_width);
|
||||
|
||||
check_x = (list_width - check_x) / 2;
|
||||
item_x = check_x + 4;
|
||||
|
@@ -25,11 +25,9 @@
|
||||
static const char mconf_readme[] = N_(
|
||||
"Overview\n"
|
||||
"--------\n"
|
||||
"Some kernel features may be built directly into the kernel.\n"
|
||||
"Some may be made into loadable runtime modules. Some features\n"
|
||||
"may be completely removed altogether. There are also certain\n"
|
||||
"kernel parameters which are not really features, but must be\n"
|
||||
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||
"This interface let you select features and parameters for the build.\n"
|
||||
"Features can either be built-in, modularized, or ignored. Parameters\n"
|
||||
"must be entered in as decimal or hexadecimal numbers or text.\n"
|
||||
"\n"
|
||||
"Menu items beginning with following braces represent features that\n"
|
||||
" [ ] can be built in or removed\n"
|
||||
@@ -74,7 +72,7 @@ static const char mconf_readme[] = N_(
|
||||
"\n"
|
||||
" Shortcut: Press <H> or <?>.\n"
|
||||
"\n"
|
||||
"o To show hidden options, press <Z>.\n"
|
||||
"o To toggle the display of hidden options, press <Z>.\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"Radiolists (Choice lists)\n"
|
||||
@@ -117,7 +115,7 @@ static const char mconf_readme[] = N_(
|
||||
"-----------------------------\n"
|
||||
"Menuconfig supports the use of alternate configuration files for\n"
|
||||
"those who, for various reasons, find it necessary to switch\n"
|
||||
"between different kernel configurations.\n"
|
||||
"between different configurations.\n"
|
||||
"\n"
|
||||
"At the end of the main menu you will find two options. One is\n"
|
||||
"for saving the current configuration to a file of your choosing.\n"
|
||||
@@ -150,9 +148,9 @@ static const char mconf_readme[] = N_(
|
||||
"\n"
|
||||
"Optional personality available\n"
|
||||
"------------------------------\n"
|
||||
"If you prefer to have all of the kernel options listed in a single\n"
|
||||
"menu, rather than the default multimenu hierarchy, run the menuconfig\n"
|
||||
"with MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
|
||||
"If you prefer to have all of the options listed in a single menu, rather\n"
|
||||
"than the default multimenu hierarchy, run the menuconfig with\n"
|
||||
"MENUCONFIG_MODE environment variable set to single_menu. Example:\n"
|
||||
"\n"
|
||||
"make MENUCONFIG_MODE=single_menu menuconfig\n"
|
||||
"\n"
|
||||
@@ -207,12 +205,12 @@ load_config_text[] = N_(
|
||||
"last retrieved. Leave blank to abort."),
|
||||
load_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep several different kernel\n"
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"\n"
|
||||
"If you have saved a previous configuration in a file other than the\n"
|
||||
"kernel's default, entering the name of the file here will allow you\n"
|
||||
"to modify that configuration.\n"
|
||||
"default one, entering its name here will allow you to modify that\n"
|
||||
"configuration.\n"
|
||||
"\n"
|
||||
"If you are uncertain, then you have probably never used alternate\n"
|
||||
"configuration files. You should therefore leave this blank to abort.\n"),
|
||||
@@ -221,8 +219,8 @@ save_config_text[] = N_(
|
||||
"as an alternate. Leave blank to abort."),
|
||||
save_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep different kernel\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"For various reasons, one may wish to keep different configurations\n"
|
||||
"available on a single machine.\n"
|
||||
"\n"
|
||||
"Entering a file name here will allow you to later retrieve, modify\n"
|
||||
"and use the current configuration as an alternate to whatever\n"
|
||||
@@ -232,7 +230,7 @@ save_config_help[] = N_(
|
||||
"leave this blank.\n"),
|
||||
search_help[] = N_(
|
||||
"\n"
|
||||
"Search for CONFIG_ symbols and display their relations.\n"
|
||||
"Search for symbols and display their relations.\n"
|
||||
"Regular expressions are allowed.\n"
|
||||
"Example: search for \"^FOO\"\n"
|
||||
"Result:\n"
|
||||
@@ -249,7 +247,7 @@ search_help[] = N_(
|
||||
"Selected by: BAR\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||
" this CONFIG_ symbol\n"
|
||||
" this symbol\n"
|
||||
"o The 'Defined at' line tell at what file / line number the symbol\n"
|
||||
" is defined\n"
|
||||
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
|
||||
@@ -265,9 +263,9 @@ search_help[] = N_(
|
||||
"Only relevant lines are shown.\n"
|
||||
"\n\n"
|
||||
"Search examples:\n"
|
||||
"Examples: USB => find all CONFIG_ symbols containing USB\n"
|
||||
" ^USB => find all CONFIG_ symbols starting with USB\n"
|
||||
" USB$ => find all CONFIG_ symbols ending with USB\n"
|
||||
"Examples: USB => find all symbols containing USB\n"
|
||||
" ^USB => find all symbols starting with USB\n"
|
||||
" USB$ => find all symbols ending with USB\n"
|
||||
"\n");
|
||||
|
||||
static int indent;
|
||||
@@ -290,13 +288,9 @@ static void set_config_filename(const char *config_filename)
|
||||
{
|
||||
static char menu_backtitle[PATH_MAX+128];
|
||||
int size;
|
||||
struct symbol *sym;
|
||||
|
||||
sym = sym_lookup("KERNELVERSION", 0);
|
||||
sym_calc_value(sym);
|
||||
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
|
||||
_("%s - Linux Kernel v%s Configuration"),
|
||||
config_filename, sym_get_string_value(sym));
|
||||
"%s - %s", config_filename, rootmenu.prompt->text);
|
||||
if (size >= sizeof(menu_backtitle))
|
||||
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
|
||||
set_dialog_backtitle(menu_backtitle);
|
||||
@@ -316,8 +310,8 @@ static void search_conf(void)
|
||||
again:
|
||||
dialog_clear();
|
||||
dres = dialog_inputbox(_("Search Configuration Parameter"),
|
||||
_("Enter CONFIG_ (sub)string to search for "
|
||||
"(with or without \"CONFIG\")"),
|
||||
_("Enter " CONFIG_ " (sub)string to search for "
|
||||
"(with or without \"" CONFIG_ "\")"),
|
||||
10, 75, "");
|
||||
switch (dres) {
|
||||
case 0:
|
||||
@@ -329,10 +323,10 @@ again:
|
||||
return;
|
||||
}
|
||||
|
||||
/* strip CONFIG_ if necessary */
|
||||
/* strip the prefix if necessary */
|
||||
dialog_input = dialog_input_result;
|
||||
if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
|
||||
dialog_input += 7;
|
||||
if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
|
||||
dialog_input += strlen(CONFIG_);
|
||||
|
||||
sym_arr = sym_re_search(dialog_input);
|
||||
res = get_relations_str(sym_arr);
|
||||
@@ -834,7 +828,7 @@ int main(int ac, char **av)
|
||||
if (conf_get_changed())
|
||||
res = dialog_yesno(NULL,
|
||||
_("Do you wish to save your "
|
||||
"new kernel configuration?\n"
|
||||
"new configuration?\n"
|
||||
"<ESC><ESC> to continue."),
|
||||
6, 60);
|
||||
else
|
||||
@@ -846,20 +840,20 @@ int main(int ac, char **av)
|
||||
case 0:
|
||||
if (conf_write(filename)) {
|
||||
fprintf(stderr, _("\n\n"
|
||||
"Error during writing of the kernel configuration.\n"
|
||||
"Your kernel configuration changes were NOT saved."
|
||||
"Error while writing of the configuration.\n"
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
return 1;
|
||||
}
|
||||
case -1:
|
||||
printf(_("\n\n"
|
||||
"*** End of Linux kernel configuration.\n"
|
||||
"*** Execute 'make' to build the kernel or try 'make help'."
|
||||
"*** End of the configuration.\n"
|
||||
"*** Execute 'make' to start the build or try 'make help'."
|
||||
"\n\n"));
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, _("\n\n"
|
||||
"Your kernel configuration changes were NOT saved."
|
||||
"Your configuration changes were NOT saved."
|
||||
"\n\n"));
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#include "lkc.h"
|
||||
|
||||
static const char nohelp_text[] = N_(
|
||||
"There is no help available for this kernel option.\n");
|
||||
"There is no help available for this option.\n");
|
||||
|
||||
struct menu rootmenu;
|
||||
static struct menu **last_entry_ptr;
|
||||
@@ -58,6 +58,8 @@ void menu_add_entry(struct symbol *sym)
|
||||
*last_entry_ptr = menu;
|
||||
last_entry_ptr = &menu->next;
|
||||
current_entry = menu;
|
||||
if (sym)
|
||||
menu_add_symbol(P_SYMBOL, sym, NULL);
|
||||
}
|
||||
|
||||
void menu_end_entry(void)
|
||||
@@ -136,7 +138,7 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
|
||||
while (isspace(*prompt))
|
||||
prompt++;
|
||||
}
|
||||
if (current_entry->prompt)
|
||||
if (current_entry->prompt && current_entry != &rootmenu)
|
||||
prop_warn(prop, "prompt redefined");
|
||||
current_entry->prompt = prop;
|
||||
}
|
||||
@@ -318,6 +320,8 @@ void menu_finalize(struct menu *parent)
|
||||
parent->next = last_menu->next;
|
||||
last_menu->next = NULL;
|
||||
}
|
||||
|
||||
sym->dir_dep.expr = parent->dep;
|
||||
}
|
||||
for (menu = parent->list; menu; menu = menu->next) {
|
||||
if (sym && sym_is_choice(sym) &&
|
||||
@@ -419,9 +423,13 @@ bool menu_is_visible(struct menu *menu)
|
||||
if (!sym || sym_get_tristate_value(menu->sym) == no)
|
||||
return false;
|
||||
|
||||
for (child = menu->list; child; child = child->next)
|
||||
if (menu_is_visible(child))
|
||||
for (child = menu->list; child; child = child->next) {
|
||||
if (menu_is_visible(child)) {
|
||||
if (sym)
|
||||
sym->flags |= SYMBOL_DEF_USER;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -501,9 +509,19 @@ void get_symbol_str(struct gstr *r, struct symbol *sym)
|
||||
bool hit;
|
||||
struct property *prop;
|
||||
|
||||
if (sym && sym->name)
|
||||
if (sym && sym->name) {
|
||||
str_printf(r, "Symbol: %s [=%s]\n", sym->name,
|
||||
sym_get_string_value(sym));
|
||||
str_printf(r, "Type : %s\n", sym_type_name(sym->type));
|
||||
if (sym->type == S_INT || sym->type == S_HEX) {
|
||||
prop = sym_get_range_prop(sym);
|
||||
if (prop) {
|
||||
str_printf(r, "Range : ");
|
||||
expr_gstr_print(prop->expr, r);
|
||||
str_append(r, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
for_all_prompts(sym, prop)
|
||||
get_prompt_str(r, prop);
|
||||
hit = false;
|
||||
@@ -545,7 +563,7 @@ void menu_get_ext_help(struct menu *menu, struct gstr *help)
|
||||
|
||||
if (menu_has_help(menu)) {
|
||||
if (sym->name) {
|
||||
str_printf(help, "CONFIG_%s:\n\n", sym->name);
|
||||
str_printf(help, "%s%s:\n\n", CONFIG_, sym->name);
|
||||
str_append(help, _(menu_get_help(menu)));
|
||||
str_append(help, "\n");
|
||||
}
|
||||
|
@@ -5,25 +5,26 @@
|
||||
* Derived from menuconfig.
|
||||
*
|
||||
*/
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#define LKC_DIRECT_LINK
|
||||
#include "lkc.h"
|
||||
#include "nconf.h"
|
||||
#include <ctype.h>
|
||||
|
||||
static const char nconf_readme[] = N_(
|
||||
"Overview\n"
|
||||
"--------\n"
|
||||
"Some kernel features may be built directly into the kernel.\n"
|
||||
"Some may be made into loadable runtime modules. Some features\n"
|
||||
"may be completely removed altogether. There are also certain\n"
|
||||
"kernel parameters which are not really features, but must be\n"
|
||||
"entered in as decimal or hexadecimal numbers or possibly text.\n"
|
||||
"This interface let you select features and parameters for the build.\n"
|
||||
"Features can either be built-in, modularized, or ignored. Parameters\n"
|
||||
"must be entered in as decimal or hexadecimal numbers or text.\n"
|
||||
"\n"
|
||||
"Menu items beginning with following braces represent features that\n"
|
||||
" [ ] can be built in or removed\n"
|
||||
" < > can be built in, modularized or removed\n"
|
||||
" { } can be built in or modularized (selected by other feature)\n"
|
||||
" - - are selected by other feature,\n"
|
||||
" XXX cannot be selected. use Symbol Info to find out why,\n"
|
||||
" XXX cannot be selected. Use Symbol Info to find out why,\n"
|
||||
"while *, M or whitespace inside braces means to build in, build as\n"
|
||||
"a module or to exclude the feature respectively.\n"
|
||||
"\n"
|
||||
@@ -41,9 +42,13 @@ static const char nconf_readme[] = N_(
|
||||
" pressing <Enter> of <right-arrow>. Use <Esc> or <left-arrow> to go back.\n"
|
||||
" Submenus are designated by \"--->\".\n"
|
||||
"\n"
|
||||
" Shortcut: Press the option's highlighted letter (hotkey).\n"
|
||||
" Pressing a hotkey more than once will sequence\n"
|
||||
" through all visible items which use that hotkey.\n"
|
||||
" Searching: pressing '/' triggers interactive search mode.\n"
|
||||
" nconfig performs a case insensitive search for the string\n"
|
||||
" in the menu prompts (no regex support).\n"
|
||||
" Pressing the up/down keys highlights the previous/next\n"
|
||||
" matching item. Backspace removes one character from the\n"
|
||||
" match string. Pressing either '/' again or ESC exits\n"
|
||||
" search mode. All other keys behave normally.\n"
|
||||
"\n"
|
||||
" You may also use the <PAGE UP> and <PAGE DOWN> keys to scroll\n"
|
||||
" unseen options into view.\n"
|
||||
@@ -88,7 +93,7 @@ static const char nconf_readme[] = N_(
|
||||
"-----------------------------\n"
|
||||
"nconfig supports the use of alternate configuration files for\n"
|
||||
"those who, for various reasons, find it necessary to switch\n"
|
||||
"between different kernel configurations.\n"
|
||||
"between different configurations.\n"
|
||||
"\n"
|
||||
"At the end of the main menu you will find two options. One is\n"
|
||||
"for saving the current configuration to a file of your choosing.\n"
|
||||
@@ -121,9 +126,9 @@ static const char nconf_readme[] = N_(
|
||||
"\n"
|
||||
"Optional personality available\n"
|
||||
"------------------------------\n"
|
||||
"If you prefer to have all of the kernel options listed in a single\n"
|
||||
"menu, rather than the default multimenu hierarchy, run the nconfig\n"
|
||||
"with NCONFIG_MODE environment variable set to single_menu. Example:\n"
|
||||
"If you prefer to have all of the options listed in a single menu, rather\n"
|
||||
"than the default multimenu hierarchy, run the nconfig with NCONFIG_MODE\n"
|
||||
"environment variable set to single_menu. Example:\n"
|
||||
"\n"
|
||||
"make NCONFIG_MODE=single_menu nconfig\n"
|
||||
"\n"
|
||||
@@ -141,21 +146,21 @@ menu_no_f_instructions[] = N_(
|
||||
" <Enter> or <right-arrow> selects submenus --->.\n"
|
||||
" Capital Letters are hotkeys.\n"
|
||||
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
||||
" Pressing SpaceBar toggles between the above options\n"
|
||||
" Press <Esc> or <left-arrow> to go back one menu, \n"
|
||||
" Pressing SpaceBar toggles between the above options.\n"
|
||||
" Press <Esc> or <left-arrow> to go back one menu,\n"
|
||||
" <?> or <h> for Help, </> for Search.\n"
|
||||
" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
|
||||
" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
|
||||
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
||||
" <Esc> always leaves the current window\n"),
|
||||
" <Esc> always leaves the current window.\n"),
|
||||
menu_instructions[] = N_(
|
||||
" Arrow keys navigate the menu.\n"
|
||||
" <Enter> or <right-arrow> selects submenus --->.\n"
|
||||
" Capital Letters are hotkeys.\n"
|
||||
" Pressing <Y> includes, <N> excludes, <M> modularizes features.\n"
|
||||
" Pressing SpaceBar toggles between the above options\n"
|
||||
" Press <Esc>, <F3> or <left-arrow> to go back one menu, \n"
|
||||
" Press <Esc>, <F5> or <left-arrow> to go back one menu,\n"
|
||||
" <?>, <F1> or <h> for Help, </> for Search.\n"
|
||||
" <1> is interchangable with <F1>, <2> with <F2>, etc.\n"
|
||||
" <1> is interchangeable with <F1>, <2> with <F2>, etc.\n"
|
||||
" Legend: [*] built-in [ ] excluded <M> module < > module capable.\n"
|
||||
" <Esc> always leaves the current window\n"),
|
||||
radiolist_instructions[] = N_(
|
||||
@@ -178,19 +183,19 @@ setmod_text[] = N_(
|
||||
"has been configured as a module.\n"
|
||||
"As a result, this feature will be built as a module."),
|
||||
nohelp_text[] = N_(
|
||||
"There is no help available for this kernel option.\n"),
|
||||
"There is no help available for this option.\n"),
|
||||
load_config_text[] = N_(
|
||||
"Enter the name of the configuration file you wish to load.\n"
|
||||
"Accept the name shown to restore the configuration you\n"
|
||||
"last retrieved. Leave blank to abort."),
|
||||
load_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep several different kernel\n"
|
||||
"For various reasons, one may wish to keep several different\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"\n"
|
||||
"If you have saved a previous configuration in a file other than the\n"
|
||||
"kernel's default, entering the name of the file here will allow you\n"
|
||||
"to modify that configuration.\n"
|
||||
"default one, entering its name here will allow you to modify that\n"
|
||||
"configuration.\n"
|
||||
"\n"
|
||||
"If you are uncertain, then you have probably never used alternate\n"
|
||||
"configuration files. You should therefor leave this blank to abort.\n"),
|
||||
@@ -199,8 +204,8 @@ save_config_text[] = N_(
|
||||
"as an alternate. Leave blank to abort."),
|
||||
save_config_help[] = N_(
|
||||
"\n"
|
||||
"For various reasons, one may wish to keep different kernel\n"
|
||||
"configurations available on a single machine.\n"
|
||||
"For various reasons, one may wish to keep different configurations\n"
|
||||
"available on a single machine.\n"
|
||||
"\n"
|
||||
"Entering a file name here will allow you to later retrieve, modify\n"
|
||||
"and use the current configuration as an alternate to whatever\n"
|
||||
@@ -210,8 +215,8 @@ save_config_help[] = N_(
|
||||
"leave this blank.\n"),
|
||||
search_help[] = N_(
|
||||
"\n"
|
||||
"Search for CONFIG_ symbols and display their relations.\n"
|
||||
"Regular expressions are allowed.\n"
|
||||
"Search for symbols and display their relations. Regular expressions\n"
|
||||
"are allowed.\n"
|
||||
"Example: search for \"^FOO\"\n"
|
||||
"Result:\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
@@ -227,7 +232,7 @@ search_help[] = N_(
|
||||
"Selected by: BAR\n"
|
||||
"-----------------------------------------------------------------\n"
|
||||
"o The line 'Prompt:' shows the text used in the menu structure for\n"
|
||||
" this CONFIG_ symbol\n"
|
||||
" this symbol\n"
|
||||
"o The 'Defined at' line tell at what file / line number the symbol\n"
|
||||
" is defined\n"
|
||||
"o The 'Depends on:' line tell what symbols needs to be defined for\n"
|
||||
@@ -243,16 +248,15 @@ search_help[] = N_(
|
||||
"Only relevant lines are shown.\n"
|
||||
"\n\n"
|
||||
"Search examples:\n"
|
||||
"Examples: USB = > find all CONFIG_ symbols containing USB\n"
|
||||
" ^USB => find all CONFIG_ symbols starting with USB\n"
|
||||
" USB$ => find all CONFIG_ symbols ending with USB\n"
|
||||
"Examples: USB = > find all symbols containing USB\n"
|
||||
" ^USB => find all symbols starting with USB\n"
|
||||
" USB$ => find all symbols ending with USB\n"
|
||||
"\n");
|
||||
|
||||
struct mitem {
|
||||
char str[256];
|
||||
char tag;
|
||||
void *usrptr;
|
||||
int is_hot;
|
||||
int is_visible;
|
||||
};
|
||||
|
||||
@@ -275,14 +279,6 @@ static int items_num;
|
||||
static int global_exit;
|
||||
/* the currently selected button */
|
||||
const char *current_instructions = menu_instructions;
|
||||
/* this array is used to implement hot keys. it is updated in item_make and
|
||||
* resetted in clean_items. It would be better to use a hash, but lets keep it
|
||||
* simple... */
|
||||
#define MAX_SAME_KEY MAX_MENU_ITEMS
|
||||
struct {
|
||||
int count;
|
||||
int ptrs[MAX_MENU_ITEMS];
|
||||
} hotkeys[1<<(sizeof(char)*8)];
|
||||
|
||||
static void conf(struct menu *menu);
|
||||
static void conf_choice(struct menu *menu);
|
||||
@@ -292,6 +288,7 @@ static void conf_save(void);
|
||||
static void show_help(struct menu *menu);
|
||||
static int do_exit(void);
|
||||
static void setup_windows(void);
|
||||
static void search_conf(void);
|
||||
|
||||
typedef void (*function_key_handler_t)(int *key, struct menu *menu);
|
||||
static void handle_f1(int *key, struct menu *current_item);
|
||||
@@ -302,6 +299,7 @@ static void handle_f5(int *key, struct menu *current_item);
|
||||
static void handle_f6(int *key, struct menu *current_item);
|
||||
static void handle_f7(int *key, struct menu *current_item);
|
||||
static void handle_f8(int *key, struct menu *current_item);
|
||||
static void handle_f9(int *key, struct menu *current_item);
|
||||
|
||||
struct function_keys {
|
||||
const char *key_str;
|
||||
@@ -310,7 +308,7 @@ struct function_keys {
|
||||
function_key_handler_t handler;
|
||||
};
|
||||
|
||||
static const int function_keys_num = 8;
|
||||
static const int function_keys_num = 9;
|
||||
struct function_keys function_keys[] = {
|
||||
{
|
||||
.key_str = "F1",
|
||||
@@ -320,13 +318,13 @@ struct function_keys function_keys[] = {
|
||||
},
|
||||
{
|
||||
.key_str = "F2",
|
||||
.func = "Symbol Info",
|
||||
.func = "Sym Info",
|
||||
.key = F_SYMBOL,
|
||||
.handler = handle_f2,
|
||||
},
|
||||
{
|
||||
.key_str = "F3",
|
||||
.func = "Instructions",
|
||||
.func = "Insts",
|
||||
.key = F_INSTS,
|
||||
.handler = handle_f3,
|
||||
},
|
||||
@@ -356,9 +354,15 @@ struct function_keys function_keys[] = {
|
||||
},
|
||||
{
|
||||
.key_str = "F8",
|
||||
.func = "Sym Search",
|
||||
.key = F_SEARCH,
|
||||
.handler = handle_f8,
|
||||
},
|
||||
{
|
||||
.key_str = "F9",
|
||||
.func = "Exit",
|
||||
.key = F_EXIT,
|
||||
.handler = handle_f8,
|
||||
.handler = handle_f9,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -444,8 +448,15 @@ static void handle_f7(int *key, struct menu *current_item)
|
||||
return;
|
||||
}
|
||||
|
||||
/* exit */
|
||||
/* search */
|
||||
static void handle_f8(int *key, struct menu *current_item)
|
||||
{
|
||||
search_conf();
|
||||
return;
|
||||
}
|
||||
|
||||
/* exit */
|
||||
static void handle_f9(int *key, struct menu *current_item)
|
||||
{
|
||||
do_exit();
|
||||
return;
|
||||
@@ -479,110 +490,44 @@ static void clean_items(void)
|
||||
free_item(curses_menu_items[i]);
|
||||
bzero(curses_menu_items, sizeof(curses_menu_items));
|
||||
bzero(k_menu_items, sizeof(k_menu_items));
|
||||
bzero(hotkeys, sizeof(hotkeys));
|
||||
items_num = 0;
|
||||
}
|
||||
|
||||
/* return the index of the next hot item, or -1 if no such item exists */
|
||||
static int get_next_hot(int c)
|
||||
typedef enum {MATCH_TINKER_PATTERN_UP, MATCH_TINKER_PATTERN_DOWN,
|
||||
FIND_NEXT_MATCH_DOWN, FIND_NEXT_MATCH_UP} match_f;
|
||||
|
||||
/* return the index of the matched item, or -1 if no such item exists */
|
||||
static int get_mext_match(const char *match_str, match_f flag)
|
||||
{
|
||||
static int hot_index;
|
||||
static int hot_char;
|
||||
int match_start = item_index(current_item(curses_menu));
|
||||
int index;
|
||||
|
||||
if (c < 0 || c > 255 || hotkeys[c].count <= 0)
|
||||
return -1;
|
||||
if (flag == FIND_NEXT_MATCH_DOWN)
|
||||
++match_start;
|
||||
else if (flag == FIND_NEXT_MATCH_UP)
|
||||
--match_start;
|
||||
|
||||
if (hot_char == c) {
|
||||
hot_index = (hot_index+1)%hotkeys[c].count;
|
||||
return hotkeys[c].ptrs[hot_index];
|
||||
} else {
|
||||
hot_char = c;
|
||||
hot_index = 0;
|
||||
return hotkeys[c].ptrs[0];
|
||||
index = match_start;
|
||||
index = (index + items_num) % items_num;
|
||||
while (true) {
|
||||
char *str = k_menu_items[index].str;
|
||||
if (strcasestr(str, match_str) != 0)
|
||||
return index;
|
||||
if (flag == FIND_NEXT_MATCH_UP ||
|
||||
flag == MATCH_TINKER_PATTERN_UP)
|
||||
--index;
|
||||
else
|
||||
++index;
|
||||
index = (index + items_num) % items_num;
|
||||
if (index == match_start)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* can the char c be a hot key? no, if c is a common shortcut used elsewhere */
|
||||
static int canbhot(char c)
|
||||
{
|
||||
c = tolower(c);
|
||||
return isalnum(c) && c != 'y' && c != 'm' && c != 'h' &&
|
||||
c != 'n' && c != '?';
|
||||
}
|
||||
|
||||
/* check if str already contains a hot key. */
|
||||
static int is_hot(int index)
|
||||
{
|
||||
return k_menu_items[index].is_hot;
|
||||
}
|
||||
|
||||
/* find the first possible hot key, and mark it.
|
||||
* index is the index of the item in the menu
|
||||
* return 0 on success*/
|
||||
static int make_hot(char *dest, int len, const char *org, int index)
|
||||
{
|
||||
int position = -1;
|
||||
int i;
|
||||
int tmp;
|
||||
int c;
|
||||
int org_len = strlen(org);
|
||||
|
||||
if (org == NULL || is_hot(index))
|
||||
return 1;
|
||||
|
||||
/* make sure not to make hot keys out of markers.
|
||||
* find where to start looking for a hot key
|
||||
*/
|
||||
i = 0;
|
||||
/* skip white space */
|
||||
while (i < org_len && org[i] == ' ')
|
||||
i++;
|
||||
if (i == org_len)
|
||||
return -1;
|
||||
/* if encountering '(' or '<' or '[', find the match and look from there
|
||||
**/
|
||||
if (org[i] == '[' || org[i] == '<' || org[i] == '(') {
|
||||
i++;
|
||||
for (; i < org_len; i++)
|
||||
if (org[i] == ']' || org[i] == '>' || org[i] == ')')
|
||||
break;
|
||||
}
|
||||
if (i == org_len)
|
||||
return -1;
|
||||
for (; i < org_len; i++) {
|
||||
if (canbhot(org[i]) && org[i-1] != '<' && org[i-1] != '(') {
|
||||
position = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (position == -1)
|
||||
return 1;
|
||||
|
||||
/* ok, char at org[position] should be a hot key to this item */
|
||||
c = tolower(org[position]);
|
||||
tmp = hotkeys[c].count;
|
||||
hotkeys[c].ptrs[tmp] = index;
|
||||
hotkeys[c].count++;
|
||||
/*
|
||||
snprintf(dest, len, "%.*s(%c)%s", position, org, org[position],
|
||||
&org[position+1]);
|
||||
*/
|
||||
/* make org[position] uppercase, and all leading letter small case */
|
||||
strncpy(dest, org, len);
|
||||
for (i = 0; i < position; i++)
|
||||
dest[i] = tolower(dest[i]);
|
||||
dest[position] = toupper(dest[position]);
|
||||
k_menu_items[index].is_hot = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Make a new item. Add a hotkey mark in the first possible letter.
|
||||
* As ncurses does not allow any attributes inside menue item, we mark the
|
||||
* hot key as the first capitalized letter in the string */
|
||||
/* Make a new item. */
|
||||
static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char tmp_str[256];
|
||||
|
||||
if (items_num > MAX_MENU_ITEMS-1)
|
||||
return;
|
||||
@@ -597,16 +542,13 @@ static void item_make(struct menu *menu, char tag, const char *fmt, ...)
|
||||
k_menu_items[items_num].is_visible = 1;
|
||||
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(tmp_str, sizeof(tmp_str), fmt, ap);
|
||||
if (!k_menu_items[items_num].is_visible)
|
||||
memcpy(tmp_str, "XXX", 3);
|
||||
vsnprintf(k_menu_items[items_num].str,
|
||||
sizeof(k_menu_items[items_num].str),
|
||||
fmt, ap);
|
||||
va_end(ap);
|
||||
if (make_hot(
|
||||
k_menu_items[items_num].str,
|
||||
sizeof(k_menu_items[items_num].str), tmp_str, items_num) != 0)
|
||||
strncpy(k_menu_items[items_num].str,
|
||||
tmp_str,
|
||||
sizeof(k_menu_items[items_num].str));
|
||||
|
||||
if (!k_menu_items[items_num].is_visible)
|
||||
memcpy(k_menu_items[items_num].str, "XXX", 3);
|
||||
|
||||
curses_menu_items[items_num] = new_item(
|
||||
k_menu_items[items_num].str,
|
||||
@@ -638,11 +580,9 @@ static void item_add_str(const char *fmt, ...)
|
||||
va_end(ap);
|
||||
snprintf(tmp_str, sizeof(tmp_str), "%s%s",
|
||||
k_menu_items[index].str, new_str);
|
||||
if (make_hot(k_menu_items[index].str,
|
||||
sizeof(k_menu_items[index].str), tmp_str, index) != 0)
|
||||
strncpy(k_menu_items[index].str,
|
||||
tmp_str,
|
||||
sizeof(k_menu_items[index].str));
|
||||
strncpy(k_menu_items[index].str,
|
||||
tmp_str,
|
||||
sizeof(k_menu_items[index].str));
|
||||
|
||||
free_item(curses_menu_items[index]);
|
||||
curses_menu_items[index] = new_item(
|
||||
@@ -676,6 +616,8 @@ static void *item_data(void)
|
||||
struct mitem *mcur;
|
||||
|
||||
cur = current_item(curses_menu);
|
||||
if (!cur)
|
||||
return NULL;
|
||||
mcur = (struct mitem *) item_userptr(cur);
|
||||
return mcur->usrptr;
|
||||
|
||||
@@ -691,13 +633,9 @@ static char menu_backtitle[PATH_MAX+128];
|
||||
static const char *set_config_filename(const char *config_filename)
|
||||
{
|
||||
int size;
|
||||
struct symbol *sym;
|
||||
|
||||
sym = sym_lookup("KERNELVERSION", 0);
|
||||
sym_calc_value(sym);
|
||||
size = snprintf(menu_backtitle, sizeof(menu_backtitle),
|
||||
_("%s - Linux Kernel v%s Configuration"),
|
||||
config_filename, sym_get_string_value(sym));
|
||||
"%s - %s", config_filename, rootmenu.prompt->text);
|
||||
if (size >= sizeof(menu_backtitle))
|
||||
menu_backtitle[sizeof(menu_backtitle)-1] = '\0';
|
||||
|
||||
@@ -707,25 +645,6 @@ static const char *set_config_filename(const char *config_filename)
|
||||
return menu_backtitle;
|
||||
}
|
||||
|
||||
/* command = 0 is supress, 1 is restore */
|
||||
static void supress_stdout(int command)
|
||||
{
|
||||
static FILE *org_stdout;
|
||||
static FILE *org_stderr;
|
||||
|
||||
if (command == 0) {
|
||||
org_stdout = stdout;
|
||||
org_stderr = stderr;
|
||||
stdout = fopen("/dev/null", "a");
|
||||
stderr = fopen("/dev/null", "a");
|
||||
} else {
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
stdout = org_stdout;
|
||||
stderr = org_stderr;
|
||||
}
|
||||
}
|
||||
|
||||
/* return = 0 means we are successful.
|
||||
* -1 means go on doing what you were doing
|
||||
*/
|
||||
@@ -737,8 +656,7 @@ static int do_exit(void)
|
||||
return 0;
|
||||
}
|
||||
res = btn_dialog(main_window,
|
||||
_("Do you wish to save your "
|
||||
"new kernel configuration?\n"
|
||||
_("Do you wish to save your new configuration?\n"
|
||||
"<ESC> to cancel and resume nconfig."),
|
||||
2,
|
||||
" <save> ",
|
||||
@@ -751,36 +669,19 @@ static int do_exit(void)
|
||||
/* if we got here, the user really wants to exit */
|
||||
switch (res) {
|
||||
case 0:
|
||||
supress_stdout(0);
|
||||
res = conf_write(filename);
|
||||
supress_stdout(1);
|
||||
if (res)
|
||||
btn_dialog(
|
||||
main_window,
|
||||
_("Error during writing of the kernel "
|
||||
"configuration.\n"
|
||||
"Your kernel configuration "
|
||||
"changes were NOT saved."),
|
||||
_("Error during writing of configuration.\n"
|
||||
"Your configuration changes were NOT saved."),
|
||||
1,
|
||||
"<OK>");
|
||||
else {
|
||||
char buf[1024];
|
||||
snprintf(buf, 1024,
|
||||
_("Configuration written to %s\n"
|
||||
"End of Linux kernel configuration.\n"
|
||||
"Execute 'make' to build the kernel or try"
|
||||
" 'make help'."), filename);
|
||||
btn_dialog(
|
||||
main_window,
|
||||
buf,
|
||||
1,
|
||||
"<OK>");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
btn_dialog(
|
||||
main_window,
|
||||
_("Your kernel configuration changes were NOT saved."),
|
||||
_("Your configuration changes were NOT saved."),
|
||||
1,
|
||||
"<OK>");
|
||||
break;
|
||||
@@ -800,8 +701,8 @@ static void search_conf(void)
|
||||
again:
|
||||
dres = dialog_inputbox(main_window,
|
||||
_("Search Configuration Parameter"),
|
||||
_("Enter CONFIG_ (sub)string to search for "
|
||||
"(with or without \"CONFIG\")"),
|
||||
_("Enter " CONFIG_ " (sub)string to search for "
|
||||
"(with or without \"" CONFIG_ "\")"),
|
||||
"", dialog_input_result, 99);
|
||||
switch (dres) {
|
||||
case 0:
|
||||
@@ -814,10 +715,10 @@ again:
|
||||
return;
|
||||
}
|
||||
|
||||
/* strip CONFIG_ if necessary */
|
||||
/* strip the prefix if necessary */
|
||||
dialog_input = dialog_input_result;
|
||||
if (strncasecmp(dialog_input_result, "CONFIG_", 7) == 0)
|
||||
dialog_input += 7;
|
||||
if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0)
|
||||
dialog_input += strlen(CONFIG_);
|
||||
|
||||
sym_arr = sym_re_search(dialog_input);
|
||||
res = get_relations_str(sym_arr);
|
||||
@@ -1025,23 +926,18 @@ static void reset_menu(void)
|
||||
static void center_item(int selected_index, int *last_top_row)
|
||||
{
|
||||
int toprow;
|
||||
int maxy, maxx;
|
||||
|
||||
scale_menu(curses_menu, &maxy, &maxx);
|
||||
set_top_row(curses_menu, *last_top_row);
|
||||
toprow = top_row(curses_menu);
|
||||
if (selected_index >= toprow && selected_index < toprow+maxy) {
|
||||
/* we can only move the selected item. no need to scroll */
|
||||
set_current_item(curses_menu,
|
||||
curses_menu_items[selected_index]);
|
||||
} else {
|
||||
toprow = max(selected_index-maxy/2, 0);
|
||||
if (toprow >= item_count(curses_menu)-maxy)
|
||||
if (selected_index < toprow ||
|
||||
selected_index >= toprow+mwin_max_lines) {
|
||||
toprow = max(selected_index-mwin_max_lines/2, 0);
|
||||
if (toprow >= item_count(curses_menu)-mwin_max_lines)
|
||||
toprow = item_count(curses_menu)-mwin_max_lines;
|
||||
set_top_row(curses_menu, toprow);
|
||||
set_current_item(curses_menu,
|
||||
curses_menu_items[selected_index]);
|
||||
}
|
||||
set_current_item(curses_menu,
|
||||
curses_menu_items[selected_index]);
|
||||
*last_top_row = toprow;
|
||||
post_menu(curses_menu);
|
||||
refresh_all_windows(main_window);
|
||||
@@ -1073,7 +969,7 @@ static void show_menu(const char *prompt, const char *instructions,
|
||||
/* position the menu at the middle of the screen */
|
||||
scale_menu(curses_menu, &maxy, &maxx);
|
||||
maxx = min(maxx, mwin_max_cols-2);
|
||||
maxy = mwin_max_lines-2;
|
||||
maxy = mwin_max_lines;
|
||||
menu_window = derwin(main_window,
|
||||
maxy,
|
||||
maxx,
|
||||
@@ -1097,10 +993,77 @@ static void show_menu(const char *prompt, const char *instructions,
|
||||
refresh_all_windows(main_window);
|
||||
}
|
||||
|
||||
static void adj_match_dir(match_f *match_direction)
|
||||
{
|
||||
if (*match_direction == FIND_NEXT_MATCH_DOWN)
|
||||
*match_direction =
|
||||
MATCH_TINKER_PATTERN_DOWN;
|
||||
else if (*match_direction == FIND_NEXT_MATCH_UP)
|
||||
*match_direction =
|
||||
MATCH_TINKER_PATTERN_UP;
|
||||
/* else, do no change.. */
|
||||
}
|
||||
|
||||
struct match_state
|
||||
{
|
||||
int in_search;
|
||||
match_f match_direction;
|
||||
char pattern[256];
|
||||
};
|
||||
|
||||
/* Return 0 means I have handled the key. In such a case, ans should hold the
|
||||
* item to center, or -1 otherwise.
|
||||
* Else return -1 .
|
||||
*/
|
||||
static int do_match(int key, struct match_state *state, int *ans)
|
||||
{
|
||||
char c = (char) key;
|
||||
int terminate_search = 0;
|
||||
*ans = -1;
|
||||
if (key == '/' || (state->in_search && key == 27)) {
|
||||
move(0, 0);
|
||||
refresh();
|
||||
clrtoeol();
|
||||
state->in_search = 1-state->in_search;
|
||||
bzero(state->pattern, sizeof(state->pattern));
|
||||
state->match_direction = MATCH_TINKER_PATTERN_DOWN;
|
||||
return 0;
|
||||
} else if (!state->in_search)
|
||||
return 1;
|
||||
|
||||
if (isalnum(c) || isgraph(c) || c == ' ') {
|
||||
state->pattern[strlen(state->pattern)] = c;
|
||||
state->pattern[strlen(state->pattern)] = '\0';
|
||||
adj_match_dir(&state->match_direction);
|
||||
*ans = get_mext_match(state->pattern,
|
||||
state->match_direction);
|
||||
} else if (key == KEY_DOWN) {
|
||||
state->match_direction = FIND_NEXT_MATCH_DOWN;
|
||||
*ans = get_mext_match(state->pattern,
|
||||
state->match_direction);
|
||||
} else if (key == KEY_UP) {
|
||||
state->match_direction = FIND_NEXT_MATCH_UP;
|
||||
*ans = get_mext_match(state->pattern,
|
||||
state->match_direction);
|
||||
} else if (key == KEY_BACKSPACE || key == 127) {
|
||||
state->pattern[strlen(state->pattern)-1] = '\0';
|
||||
adj_match_dir(&state->match_direction);
|
||||
} else
|
||||
terminate_search = 1;
|
||||
|
||||
if (terminate_search) {
|
||||
state->in_search = 0;
|
||||
bzero(state->pattern, sizeof(state->pattern));
|
||||
move(0, 0);
|
||||
refresh();
|
||||
clrtoeol();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void conf(struct menu *menu)
|
||||
{
|
||||
char pattern[256];
|
||||
struct menu *submenu = 0;
|
||||
const char *prompt = menu_get_prompt(menu);
|
||||
struct symbol *sym;
|
||||
@@ -1108,8 +1071,11 @@ static void conf(struct menu *menu)
|
||||
int res;
|
||||
int current_index = 0;
|
||||
int last_top_row = 0;
|
||||
|
||||
bzero(pattern, sizeof(pattern));
|
||||
struct match_state match_state = {
|
||||
.in_search = 0,
|
||||
.match_direction = MATCH_TINKER_PATTERN_DOWN,
|
||||
.pattern = "",
|
||||
};
|
||||
|
||||
while (!global_exit) {
|
||||
reset_menu();
|
||||
@@ -1122,7 +1088,22 @@ static void conf(struct menu *menu)
|
||||
_(menu_instructions),
|
||||
current_index, &last_top_row);
|
||||
keypad((menu_win(curses_menu)), TRUE);
|
||||
while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
|
||||
while (!global_exit) {
|
||||
if (match_state.in_search) {
|
||||
mvprintw(0, 0,
|
||||
"searching: %s", match_state.pattern);
|
||||
clrtoeol();
|
||||
}
|
||||
refresh_all_windows(main_window);
|
||||
res = wgetch(menu_win(curses_menu));
|
||||
if (!res)
|
||||
break;
|
||||
if (do_match(res, &match_state, ¤t_index) == 0) {
|
||||
if (current_index != -1)
|
||||
center_item(current_index,
|
||||
&last_top_row);
|
||||
continue;
|
||||
}
|
||||
if (process_special_keys(&res,
|
||||
(struct menu *) item_data()))
|
||||
break;
|
||||
@@ -1153,19 +1134,13 @@ static void conf(struct menu *menu)
|
||||
if (res == 10 || res == 27 ||
|
||||
res == 32 || res == 'n' || res == 'y' ||
|
||||
res == KEY_LEFT || res == KEY_RIGHT ||
|
||||
res == 'm' || res == '/')
|
||||
res == 'm')
|
||||
break;
|
||||
else if (canbhot(res)) {
|
||||
/* check for hot keys: */
|
||||
int tmp = get_next_hot(res);
|
||||
if (tmp != -1)
|
||||
center_item(tmp, &last_top_row);
|
||||
}
|
||||
refresh_all_windows(main_window);
|
||||
}
|
||||
|
||||
refresh_all_windows(main_window);
|
||||
/* if ESC or left*/
|
||||
/* if ESC or left*/
|
||||
if (res == 27 || (menu != &rootmenu && res == KEY_LEFT))
|
||||
break;
|
||||
|
||||
@@ -1233,23 +1208,30 @@ static void conf(struct menu *menu)
|
||||
if (item_is_tag('t'))
|
||||
sym_set_tristate_value(sym, mod);
|
||||
break;
|
||||
case '/':
|
||||
search_conf();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void conf_message_callback(const char *fmt, va_list ap)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
btn_dialog(main_window, buf, 1, "<OK>");
|
||||
}
|
||||
|
||||
static void show_help(struct menu *menu)
|
||||
{
|
||||
struct gstr help = str_new();
|
||||
|
||||
if (menu && menu->sym && menu_has_help(menu)) {
|
||||
if (menu->sym->name) {
|
||||
str_printf(&help, "CONFIG_%s:\n\n", menu->sym->name);
|
||||
str_printf(&help, "%s%s:\n\n", CONFIG_, menu->sym->name);
|
||||
str_append(&help, _(menu_get_help(menu)));
|
||||
str_append(&help, "\n");
|
||||
get_symbol_str(&help, menu->sym);
|
||||
} else {
|
||||
str_append(&help, _(menu_get_help(menu)));
|
||||
}
|
||||
} else {
|
||||
str_append(&help, nohelp_text);
|
||||
@@ -1266,6 +1248,11 @@ static void conf_choice(struct menu *menu)
|
||||
int selected_index = 0;
|
||||
int last_top_row = 0;
|
||||
int res, i = 0;
|
||||
struct match_state match_state = {
|
||||
.in_search = 0,
|
||||
.match_direction = MATCH_TINKER_PATTERN_DOWN,
|
||||
.pattern = "",
|
||||
};
|
||||
|
||||
active = sym_get_choice_value(menu->sym);
|
||||
/* this is mostly duplicated from the conf() function. */
|
||||
@@ -1292,7 +1279,22 @@ static void conf_choice(struct menu *menu)
|
||||
_(radiolist_instructions),
|
||||
selected_index,
|
||||
&last_top_row);
|
||||
while (!global_exit && (res = wgetch(menu_win(curses_menu)))) {
|
||||
while (!global_exit) {
|
||||
if (match_state.in_search) {
|
||||
mvprintw(0, 0, "searching: %s",
|
||||
match_state.pattern);
|
||||
clrtoeol();
|
||||
}
|
||||
refresh_all_windows(main_window);
|
||||
res = wgetch(menu_win(curses_menu));
|
||||
if (!res)
|
||||
break;
|
||||
if (do_match(res, &match_state, &selected_index) == 0) {
|
||||
if (selected_index != -1)
|
||||
center_item(selected_index,
|
||||
&last_top_row);
|
||||
continue;
|
||||
}
|
||||
if (process_special_keys(
|
||||
&res,
|
||||
(struct menu *) item_data()))
|
||||
@@ -1322,13 +1324,8 @@ static void conf_choice(struct menu *menu)
|
||||
break;
|
||||
}
|
||||
if (res == 10 || res == 27 || res == ' ' ||
|
||||
res == KEY_LEFT)
|
||||
res == KEY_LEFT){
|
||||
break;
|
||||
else if (canbhot(res)) {
|
||||
/* check for hot keys: */
|
||||
int tmp = get_next_hot(res);
|
||||
if (tmp != -1)
|
||||
center_item(tmp, &last_top_row);
|
||||
}
|
||||
refresh_all_windows(main_window);
|
||||
}
|
||||
@@ -1447,16 +1444,8 @@ static void conf_save(void)
|
||||
case 0:
|
||||
if (!dialog_input_result[0])
|
||||
return;
|
||||
supress_stdout(0);
|
||||
res = conf_write(dialog_input_result);
|
||||
supress_stdout(1);
|
||||
if (!res) {
|
||||
char buf[1024];
|
||||
sprintf(buf, "%s %s",
|
||||
_("configuration file saved to: "),
|
||||
dialog_input_result);
|
||||
btn_dialog(main_window,
|
||||
buf, 1, "<OK>");
|
||||
set_config_filename(dialog_input_result);
|
||||
return;
|
||||
}
|
||||
@@ -1483,7 +1472,7 @@ void setup_windows(void)
|
||||
/* set up the menu and menu window */
|
||||
main_window = newwin(LINES-2, COLS-2, 2, 1);
|
||||
keypad(main_window, TRUE);
|
||||
mwin_max_lines = LINES-6;
|
||||
mwin_max_lines = LINES-7;
|
||||
mwin_max_cols = COLS-6;
|
||||
|
||||
/* panels order is from bottom to top */
|
||||
@@ -1530,9 +1519,10 @@ int main(int ac, char **av)
|
||||
/* set btns menu */
|
||||
curses_menu = new_menu(curses_menu_items);
|
||||
menu_opts_off(curses_menu, O_SHOWDESC);
|
||||
menu_opts_off(curses_menu, O_SHOWMATCH);
|
||||
menu_opts_on(curses_menu, O_SHOWMATCH);
|
||||
menu_opts_on(curses_menu, O_ONEVALUE);
|
||||
menu_opts_on(curses_menu, O_NONCYCLIC);
|
||||
menu_opts_on(curses_menu, O_IGNORECASE);
|
||||
set_menu_mark(curses_menu, " ");
|
||||
set_menu_fore(curses_menu, attributes[MAIN_MENU_FORE]);
|
||||
set_menu_back(curses_menu, attributes[MAIN_MENU_BACK]);
|
||||
@@ -1548,8 +1538,7 @@ int main(int ac, char **av)
|
||||
_(menu_no_f_instructions));
|
||||
}
|
||||
|
||||
|
||||
|
||||
conf_set_message_callback(conf_message_callback);
|
||||
/* do the work */
|
||||
while (!global_exit) {
|
||||
conf(&rootmenu);
|
||||
|
@@ -137,7 +137,7 @@ void set_colors()
|
||||
if (has_colors()) {
|
||||
normal_color_theme();
|
||||
} else {
|
||||
/* give deafults */
|
||||
/* give defaults */
|
||||
no_colors_theme();
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ void print_in_middle(WINDOW *win,
|
||||
length = strlen(string);
|
||||
temp = (width - length) / 2;
|
||||
x = startx + (int)temp;
|
||||
wattrset(win, color);
|
||||
(void) wattrset(win, color);
|
||||
mvwprintw(win, y, x, "%s", string);
|
||||
refresh();
|
||||
}
|
||||
@@ -297,11 +297,11 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
|
||||
set_menu_fore(menu, attributes[DIALOG_MENU_FORE]);
|
||||
set_menu_back(menu, attributes[DIALOG_MENU_BACK]);
|
||||
|
||||
wattrset(win, attributes[DIALOG_BOX]);
|
||||
(void) wattrset(win, attributes[DIALOG_BOX]);
|
||||
box(win, 0, 0);
|
||||
|
||||
/* print message */
|
||||
wattrset(msg_win, attributes[DIALOG_TEXT]);
|
||||
(void) wattrset(msg_win, attributes[DIALOG_TEXT]);
|
||||
fill_window(msg_win, msg);
|
||||
|
||||
set_menu_win(menu, win);
|
||||
@@ -392,16 +392,16 @@ int dialog_inputbox(WINDOW *main_window,
|
||||
form_win = derwin(win, 1, prompt_width, prompt_lines+3, 2);
|
||||
keypad(form_win, TRUE);
|
||||
|
||||
wattrset(form_win, attributes[INPUT_FIELD]);
|
||||
(void) wattrset(form_win, attributes[INPUT_FIELD]);
|
||||
|
||||
wattrset(win, attributes[INPUT_BOX]);
|
||||
(void) wattrset(win, attributes[INPUT_BOX]);
|
||||
box(win, 0, 0);
|
||||
wattrset(win, attributes[INPUT_HEADING]);
|
||||
(void) wattrset(win, attributes[INPUT_HEADING]);
|
||||
if (title)
|
||||
mvwprintw(win, 0, 3, "%s", title);
|
||||
|
||||
/* print message */
|
||||
wattrset(prompt_win, attributes[INPUT_TEXT]);
|
||||
(void) wattrset(prompt_win, attributes[INPUT_TEXT]);
|
||||
fill_window(prompt_win, prompt);
|
||||
|
||||
mvwprintw(form_win, 0, 0, "%*s", prompt_width, " ");
|
||||
@@ -531,7 +531,7 @@ void show_scroll_win(WINDOW *main_window,
|
||||
|
||||
/* create the pad */
|
||||
pad = newpad(total_lines+10, total_cols+10);
|
||||
wattrset(pad, attributes[SCROLLWIN_TEXT]);
|
||||
(void) wattrset(pad, attributes[SCROLLWIN_TEXT]);
|
||||
fill_window(pad, text);
|
||||
|
||||
win_lines = min(total_lines+4, LINES-2);
|
||||
@@ -546,9 +546,9 @@ void show_scroll_win(WINDOW *main_window,
|
||||
win = newwin(win_lines, win_cols, y, x);
|
||||
keypad(win, TRUE);
|
||||
/* show the help in the help window, and show the help panel */
|
||||
wattrset(win, attributes[SCROLLWIN_BOX]);
|
||||
(void) wattrset(win, attributes[SCROLLWIN_BOX]);
|
||||
box(win, 0, 0);
|
||||
wattrset(win, attributes[SCROLLWIN_HEADING]);
|
||||
(void) wattrset(win, attributes[SCROLLWIN_HEADING]);
|
||||
mvwprintw(win, 0, 3, " %s ", title);
|
||||
panel = new_panel(win);
|
||||
|
||||
|
@@ -69,7 +69,8 @@ typedef enum {
|
||||
F_BACK = 5,
|
||||
F_SAVE = 6,
|
||||
F_LOAD = 7,
|
||||
F_EXIT = 8
|
||||
F_SEARCH = 8,
|
||||
F_EXIT = 9,
|
||||
} function_key;
|
||||
|
||||
void set_colors(void);
|
||||
|
@@ -3,25 +3,42 @@
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qglobal.h>
|
||||
|
||||
#if QT_VERSION < 0x040000
|
||||
#include <qmainwindow.h>
|
||||
#include <qvbox.h>
|
||||
#include <qvaluelist.h>
|
||||
#include <qtextbrowser.h>
|
||||
#include <qaction.h>
|
||||
#include <qheader.h>
|
||||
#include <qfiledialog.h>
|
||||
#include <qdragobject.h>
|
||||
#include <qpopupmenu.h>
|
||||
#else
|
||||
#include <q3mainwindow.h>
|
||||
#include <q3vbox.h>
|
||||
#include <q3valuelist.h>
|
||||
#include <q3textbrowser.h>
|
||||
#include <q3action.h>
|
||||
#include <q3header.h>
|
||||
#include <q3filedialog.h>
|
||||
#include <q3dragobject.h>
|
||||
#include <q3popupmenu.h>
|
||||
#endif
|
||||
|
||||
#include <qapplication.h>
|
||||
#include <qdesktopwidget.h>
|
||||
#include <qtoolbar.h>
|
||||
#include <qlayout.h>
|
||||
#include <qvbox.h>
|
||||
#include <qsplitter.h>
|
||||
#include <qlistview.h>
|
||||
#include <qtextbrowser.h>
|
||||
#include <qlineedit.h>
|
||||
#include <qlabel.h>
|
||||
#include <qpushbutton.h>
|
||||
#include <qmenubar.h>
|
||||
#include <qmessagebox.h>
|
||||
#include <qaction.h>
|
||||
#include <qheader.h>
|
||||
#include <qfiledialog.h>
|
||||
#include <qdragobject.h>
|
||||
#include <qregexp.h>
|
||||
#include <qevent.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -39,7 +56,7 @@
|
||||
static QApplication *configApp;
|
||||
static ConfigSettings *configSettings;
|
||||
|
||||
QAction *ConfigMainWindow::saveAction;
|
||||
Q3Action *ConfigMainWindow::saveAction;
|
||||
|
||||
static inline QString qgettext(const char* str)
|
||||
{
|
||||
@@ -54,15 +71,14 @@ static inline QString qgettext(const QString& str)
|
||||
/**
|
||||
* Reads a list of integer values from the application settings.
|
||||
*/
|
||||
QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
|
||||
Q3ValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
|
||||
{
|
||||
QValueList<int> result;
|
||||
Q3ValueList<int> result;
|
||||
QStringList entryList = readListEntry(key, ok);
|
||||
if (ok) {
|
||||
QStringList::Iterator it;
|
||||
for (it = entryList.begin(); it != entryList.end(); ++it)
|
||||
result.push_back((*it).toInt());
|
||||
}
|
||||
QStringList::Iterator it;
|
||||
|
||||
for (it = entryList.begin(); it != entryList.end(); ++it)
|
||||
result.push_back((*it).toInt());
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -70,10 +86,10 @@ QValueList<int> ConfigSettings::readSizes(const QString& key, bool *ok)
|
||||
/**
|
||||
* Writes a list of integer values to the application settings.
|
||||
*/
|
||||
bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value)
|
||||
bool ConfigSettings::writeSizes(const QString& key, const Q3ValueList<int>& value)
|
||||
{
|
||||
QStringList stringList;
|
||||
QValueList<int>::ConstIterator it;
|
||||
Q3ValueList<int>::ConstIterator it;
|
||||
|
||||
for (it = value.begin(); it != value.end(); ++it)
|
||||
stringList.push_back(QString::number(*it));
|
||||
@@ -81,7 +97,6 @@ bool ConfigSettings::writeSizes(const QString& key, const QValueList<int>& value
|
||||
}
|
||||
|
||||
|
||||
#if QT_VERSION >= 300
|
||||
/*
|
||||
* set the new data
|
||||
* TODO check the value
|
||||
@@ -92,7 +107,6 @@ void ConfigItem::okRename(int col)
|
||||
sym_set_string_value(menu->sym, text(dataColIdx).latin1());
|
||||
listView()->updateList(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* update the displayed of a menu entry
|
||||
@@ -149,7 +163,7 @@ void ConfigItem::updateMenu(void)
|
||||
case S_TRISTATE:
|
||||
char ch;
|
||||
|
||||
if (!sym_is_changable(sym) && !list->showAll) {
|
||||
if (!sym_is_changable(sym) && list->optMode == normalOpt) {
|
||||
setPixmap(promptColIdx, 0);
|
||||
setText(noColIdx, QString::null);
|
||||
setText(modColIdx, QString::null);
|
||||
@@ -196,11 +210,9 @@ void ConfigItem::updateMenu(void)
|
||||
|
||||
data = sym_get_string_value(sym);
|
||||
|
||||
#if QT_VERSION >= 300
|
||||
int i = list->mapIdx(dataColIdx);
|
||||
if (i >= 0)
|
||||
setRenameEnabled(i, TRUE);
|
||||
#endif
|
||||
setText(dataColIdx, data);
|
||||
if (type == S_STRING)
|
||||
prompt = QString("%1: %2").arg(prompt).arg(data);
|
||||
@@ -320,7 +332,7 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
|
||||
symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no),
|
||||
choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no),
|
||||
menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void),
|
||||
showAll(false), showName(false), showRange(false), showData(false),
|
||||
showName(false), showRange(false), showData(false), optMode(normalOpt),
|
||||
rootEntry(0), headerPopup(0)
|
||||
{
|
||||
int i;
|
||||
@@ -337,10 +349,10 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
|
||||
|
||||
if (name) {
|
||||
configSettings->beginGroup(name);
|
||||
showAll = configSettings->readBoolEntry("/showAll", false);
|
||||
showName = configSettings->readBoolEntry("/showName", false);
|
||||
showRange = configSettings->readBoolEntry("/showRange", false);
|
||||
showData = configSettings->readBoolEntry("/showData", false);
|
||||
optMode = (enum optionMode)configSettings->readNumEntry("/optionMode", false);
|
||||
configSettings->endGroup();
|
||||
connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings()));
|
||||
}
|
||||
@@ -352,6 +364,17 @@ ConfigList::ConfigList(ConfigView* p, const char *name)
|
||||
reinit();
|
||||
}
|
||||
|
||||
bool ConfigList::menuSkip(struct menu *menu)
|
||||
{
|
||||
if (optMode == normalOpt && menu_is_visible(menu))
|
||||
return false;
|
||||
if (optMode == promptOpt && menu_has_prompt(menu))
|
||||
return false;
|
||||
if (optMode == allOpt)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigList::reinit(void)
|
||||
{
|
||||
removeColumn(dataColIdx);
|
||||
@@ -380,7 +403,7 @@ void ConfigList::saveSettings(void)
|
||||
configSettings->writeEntry("/showName", showName);
|
||||
configSettings->writeEntry("/showRange", showRange);
|
||||
configSettings->writeEntry("/showData", showData);
|
||||
configSettings->writeEntry("/showAll", showAll);
|
||||
configSettings->writeEntry("/optionMode", (int)optMode);
|
||||
configSettings->endGroup();
|
||||
}
|
||||
}
|
||||
@@ -422,7 +445,7 @@ void ConfigList::updateList(ConfigItem* item)
|
||||
if (!rootEntry) {
|
||||
if (mode != listMode)
|
||||
goto update;
|
||||
QListViewItemIterator it(this);
|
||||
Q3ListViewItemIterator it(this);
|
||||
ConfigItem* item;
|
||||
|
||||
for (; it.current(); ++it) {
|
||||
@@ -517,11 +540,9 @@ void ConfigList::changeValue(ConfigItem* item)
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
case S_STRING:
|
||||
#if QT_VERSION >= 300
|
||||
if (colMap[dataColIdx] >= 0)
|
||||
item->startRename(colMap[dataColIdx]);
|
||||
else
|
||||
#endif
|
||||
parent()->lineEdit->show(item);
|
||||
break;
|
||||
}
|
||||
@@ -553,7 +574,7 @@ void ConfigList::setParentMenu(void)
|
||||
return;
|
||||
setRootMenu(menu_get_parent_menu(rootEntry->parent));
|
||||
|
||||
QListViewItemIterator it(this);
|
||||
Q3ListViewItemIterator it(this);
|
||||
for (; (item = (ConfigItem*)it.current()); it++) {
|
||||
if (item->menu == oldroot) {
|
||||
setCurrentItem(item);
|
||||
@@ -606,7 +627,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
|
||||
}
|
||||
|
||||
visible = menu_is_visible(child);
|
||||
if (showAll || visible) {
|
||||
if (!menuSkip(child)) {
|
||||
if (!child->sym && !child->list && !child->prompt)
|
||||
continue;
|
||||
if (!item || item->menu != child)
|
||||
@@ -635,7 +656,7 @@ void ConfigList::updateMenuList(P* parent, struct menu* menu)
|
||||
|
||||
void ConfigList::keyPressEvent(QKeyEvent* ev)
|
||||
{
|
||||
QListViewItem* i = currentItem();
|
||||
Q3ListViewItem* i = currentItem();
|
||||
ConfigItem* item;
|
||||
struct menu *menu;
|
||||
enum prop_type type;
|
||||
@@ -801,10 +822,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
|
||||
{
|
||||
if (e->y() <= header()->geometry().bottom()) {
|
||||
if (!headerPopup) {
|
||||
QAction *action;
|
||||
Q3Action *action;
|
||||
|
||||
headerPopup = new QPopupMenu(this);
|
||||
action = new QAction(NULL, _("Show Name"), 0, this);
|
||||
headerPopup = new Q3PopupMenu(this);
|
||||
action = new Q3Action(NULL, _("Show Name"), 0, this);
|
||||
action->setToggleAction(TRUE);
|
||||
connect(action, SIGNAL(toggled(bool)),
|
||||
parent(), SLOT(setShowName(bool)));
|
||||
@@ -812,7 +833,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
|
||||
action, SLOT(setOn(bool)));
|
||||
action->setOn(showName);
|
||||
action->addTo(headerPopup);
|
||||
action = new QAction(NULL, _("Show Range"), 0, this);
|
||||
action = new Q3Action(NULL, _("Show Range"), 0, this);
|
||||
action->setToggleAction(TRUE);
|
||||
connect(action, SIGNAL(toggled(bool)),
|
||||
parent(), SLOT(setShowRange(bool)));
|
||||
@@ -820,7 +841,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
|
||||
action, SLOT(setOn(bool)));
|
||||
action->setOn(showRange);
|
||||
action->addTo(headerPopup);
|
||||
action = new QAction(NULL, _("Show Data"), 0, this);
|
||||
action = new Q3Action(NULL, _("Show Data"), 0, this);
|
||||
action->setToggleAction(TRUE);
|
||||
connect(action, SIGNAL(toggled(bool)),
|
||||
parent(), SLOT(setShowData(bool)));
|
||||
@@ -835,7 +856,10 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e)
|
||||
e->ignore();
|
||||
}
|
||||
|
||||
ConfigView* ConfigView::viewList;
|
||||
ConfigView*ConfigView::viewList;
|
||||
QAction *ConfigView::showNormalAction;
|
||||
QAction *ConfigView::showAllAction;
|
||||
QAction *ConfigView::showPromptAction;
|
||||
|
||||
ConfigView::ConfigView(QWidget* parent, const char *name)
|
||||
: Parent(parent, name)
|
||||
@@ -860,13 +884,16 @@ ConfigView::~ConfigView(void)
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigView::setShowAll(bool b)
|
||||
void ConfigView::setOptionMode(QAction *act)
|
||||
{
|
||||
if (list->showAll != b) {
|
||||
list->showAll = b;
|
||||
list->updateListAll();
|
||||
emit showAllChanged(b);
|
||||
}
|
||||
if (act == showNormalAction)
|
||||
list->optMode = normalOpt;
|
||||
else if (act == showAllAction)
|
||||
list->optMode = allOpt;
|
||||
else
|
||||
list->optMode = promptOpt;
|
||||
|
||||
list->updateListAll();
|
||||
}
|
||||
|
||||
void ConfigView::setShowName(bool b)
|
||||
@@ -898,7 +925,7 @@ void ConfigView::setShowData(bool b)
|
||||
|
||||
void ConfigList::setAllOpen(bool open)
|
||||
{
|
||||
QListViewItemIterator it(this);
|
||||
Q3ListViewItemIterator it(this);
|
||||
|
||||
for (; it.current(); it++)
|
||||
it.current()->setOpen(open);
|
||||
@@ -921,7 +948,7 @@ void ConfigView::updateListAll(void)
|
||||
}
|
||||
|
||||
ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name)
|
||||
: Parent(parent, name), sym(0), menu(0)
|
||||
: Parent(parent, name), sym(0), _menu(0)
|
||||
{
|
||||
if (name) {
|
||||
configSettings->beginGroup(name);
|
||||
@@ -944,7 +971,7 @@ void ConfigInfoView::setShowDebug(bool b)
|
||||
{
|
||||
if (_showDebug != b) {
|
||||
_showDebug = b;
|
||||
if (menu)
|
||||
if (_menu)
|
||||
menuInfo();
|
||||
else if (sym)
|
||||
symbolInfo();
|
||||
@@ -954,44 +981,16 @@ void ConfigInfoView::setShowDebug(bool b)
|
||||
|
||||
void ConfigInfoView::setInfo(struct menu *m)
|
||||
{
|
||||
if (menu == m)
|
||||
if (_menu == m)
|
||||
return;
|
||||
menu = m;
|
||||
_menu = m;
|
||||
sym = NULL;
|
||||
if (!menu)
|
||||
if (!_menu)
|
||||
clear();
|
||||
else
|
||||
menuInfo();
|
||||
}
|
||||
|
||||
void ConfigInfoView::setSource(const QString& name)
|
||||
{
|
||||
const char *p = name.latin1();
|
||||
|
||||
menu = NULL;
|
||||
sym = NULL;
|
||||
|
||||
switch (p[0]) {
|
||||
case 'm':
|
||||
struct menu *m;
|
||||
|
||||
if (sscanf(p, "m%p", &m) == 1 && menu != m) {
|
||||
menu = m;
|
||||
menuInfo();
|
||||
emit menuSelected(menu);
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
struct symbol *s;
|
||||
|
||||
if (sscanf(p, "s%p", &s) == 1 && sym != s) {
|
||||
sym = s;
|
||||
symbolInfo();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigInfoView::symbolInfo(void)
|
||||
{
|
||||
QString str;
|
||||
@@ -1013,11 +1012,11 @@ void ConfigInfoView::menuInfo(void)
|
||||
struct symbol* sym;
|
||||
QString head, debug, help;
|
||||
|
||||
sym = menu->sym;
|
||||
sym = _menu->sym;
|
||||
if (sym) {
|
||||
if (menu->prompt) {
|
||||
if (_menu->prompt) {
|
||||
head += "<big><b>";
|
||||
head += print_filter(_(menu->prompt->text));
|
||||
head += print_filter(_(_menu->prompt->text));
|
||||
head += "</b></big>";
|
||||
if (sym->name) {
|
||||
head += " (";
|
||||
@@ -1043,23 +1042,23 @@ void ConfigInfoView::menuInfo(void)
|
||||
debug = debug_info(sym);
|
||||
|
||||
struct gstr help_gstr = str_new();
|
||||
menu_get_ext_help(menu, &help_gstr);
|
||||
menu_get_ext_help(_menu, &help_gstr);
|
||||
help = print_filter(str_get(&help_gstr));
|
||||
str_free(&help_gstr);
|
||||
} else if (menu->prompt) {
|
||||
} else if (_menu->prompt) {
|
||||
head += "<big><b>";
|
||||
head += print_filter(_(menu->prompt->text));
|
||||
head += print_filter(_(_menu->prompt->text));
|
||||
head += "</b></big><br><br>";
|
||||
if (showDebug()) {
|
||||
if (menu->prompt->visible.expr) {
|
||||
if (_menu->prompt->visible.expr) {
|
||||
debug += " dep: ";
|
||||
expr_print(menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
|
||||
expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE);
|
||||
debug += "<br><br>";
|
||||
}
|
||||
}
|
||||
}
|
||||
if (showDebug())
|
||||
debug += QString().sprintf("defined at %s:%d<br><br>", menu->file->name, menu->lineno);
|
||||
debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno);
|
||||
|
||||
setText(head + debug + help);
|
||||
}
|
||||
@@ -1162,10 +1161,10 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
|
||||
*text += str2;
|
||||
}
|
||||
|
||||
QPopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
|
||||
Q3PopupMenu* ConfigInfoView::createPopupMenu(const QPoint& pos)
|
||||
{
|
||||
QPopupMenu* popup = Parent::createPopupMenu(pos);
|
||||
QAction* action = new QAction(NULL, _("Show Debug Info"), 0, popup);
|
||||
Q3PopupMenu* popup = Parent::createPopupMenu(pos);
|
||||
Q3Action* action = new Q3Action(NULL, _("Show Debug Info"), 0, popup);
|
||||
action->setToggleAction(TRUE);
|
||||
connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool)));
|
||||
connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool)));
|
||||
@@ -1222,7 +1221,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *nam
|
||||
y = configSettings->readNumEntry("/window y", 0, &ok);
|
||||
if (ok)
|
||||
move(x, y);
|
||||
QValueList<int> sizes = configSettings->readSizes("/split", &ok);
|
||||
Q3ValueList<int> sizes = configSettings->readSizes("/split", &ok);
|
||||
if (ok)
|
||||
split->setSizes(sizes);
|
||||
configSettings->endGroup();
|
||||
@@ -1275,8 +1274,14 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
char title[256];
|
||||
|
||||
QDesktopWidget *d = configApp->desktop();
|
||||
snprintf(title, sizeof(title), _("Linux Kernel v%s Configuration"),
|
||||
getenv("KERNELVERSION"));
|
||||
snprintf(title, sizeof(title), "%s%s",
|
||||
rootmenu.prompt->text,
|
||||
#if QT_VERSION < 0x040000
|
||||
" (Qt3)"
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
setCaption(title);
|
||||
|
||||
width = configSettings->readNumEntry("/window width", d->width() - 64);
|
||||
@@ -1309,60 +1314,79 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
configList->setFocus();
|
||||
|
||||
menu = menuBar();
|
||||
toolBar = new QToolBar("Tools", this);
|
||||
toolBar = new Q3ToolBar("Tools", this);
|
||||
|
||||
backAction = new QAction("Back", QPixmap(xpm_back), _("Back"), 0, this);
|
||||
backAction = new Q3Action("Back", QPixmap(xpm_back), _("Back"), 0, this);
|
||||
connect(backAction, SIGNAL(activated()), SLOT(goBack()));
|
||||
backAction->setEnabled(FALSE);
|
||||
QAction *quitAction = new QAction("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
|
||||
Q3Action *quitAction = new Q3Action("Quit", _("&Quit"), Qt::CTRL + Qt::Key_Q, this);
|
||||
connect(quitAction, SIGNAL(activated()), SLOT(close()));
|
||||
QAction *loadAction = new QAction("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
|
||||
Q3Action *loadAction = new Q3Action("Load", QPixmap(xpm_load), _("&Load"), Qt::CTRL + Qt::Key_L, this);
|
||||
connect(loadAction, SIGNAL(activated()), SLOT(loadConfig()));
|
||||
saveAction = new QAction("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
|
||||
saveAction = new Q3Action("Save", QPixmap(xpm_save), _("&Save"), Qt::CTRL + Qt::Key_S, this);
|
||||
connect(saveAction, SIGNAL(activated()), SLOT(saveConfig()));
|
||||
conf_set_changed_callback(conf_changed);
|
||||
// Set saveAction's initial state
|
||||
conf_changed();
|
||||
QAction *saveAsAction = new QAction("Save As...", _("Save &As..."), 0, this);
|
||||
Q3Action *saveAsAction = new Q3Action("Save As...", _("Save &As..."), 0, this);
|
||||
connect(saveAsAction, SIGNAL(activated()), SLOT(saveConfigAs()));
|
||||
QAction *searchAction = new QAction("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
|
||||
Q3Action *searchAction = new Q3Action("Find", _("&Find"), Qt::CTRL + Qt::Key_F, this);
|
||||
connect(searchAction, SIGNAL(activated()), SLOT(searchConfig()));
|
||||
QAction *singleViewAction = new QAction("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
|
||||
Q3Action *singleViewAction = new Q3Action("Single View", QPixmap(xpm_single_view), _("Single View"), 0, this);
|
||||
connect(singleViewAction, SIGNAL(activated()), SLOT(showSingleView()));
|
||||
QAction *splitViewAction = new QAction("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
|
||||
Q3Action *splitViewAction = new Q3Action("Split View", QPixmap(xpm_split_view), _("Split View"), 0, this);
|
||||
connect(splitViewAction, SIGNAL(activated()), SLOT(showSplitView()));
|
||||
QAction *fullViewAction = new QAction("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
|
||||
Q3Action *fullViewAction = new Q3Action("Full View", QPixmap(xpm_tree_view), _("Full View"), 0, this);
|
||||
connect(fullViewAction, SIGNAL(activated()), SLOT(showFullView()));
|
||||
|
||||
QAction *showNameAction = new QAction(NULL, _("Show Name"), 0, this);
|
||||
Q3Action *showNameAction = new Q3Action(NULL, _("Show Name"), 0, this);
|
||||
showNameAction->setToggleAction(TRUE);
|
||||
connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool)));
|
||||
connect(configView, SIGNAL(showNameChanged(bool)), showNameAction, SLOT(setOn(bool)));
|
||||
showNameAction->setOn(configView->showName());
|
||||
QAction *showRangeAction = new QAction(NULL, _("Show Range"), 0, this);
|
||||
Q3Action *showRangeAction = new Q3Action(NULL, _("Show Range"), 0, this);
|
||||
showRangeAction->setToggleAction(TRUE);
|
||||
connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool)));
|
||||
connect(configView, SIGNAL(showRangeChanged(bool)), showRangeAction, SLOT(setOn(bool)));
|
||||
showRangeAction->setOn(configList->showRange);
|
||||
QAction *showDataAction = new QAction(NULL, _("Show Data"), 0, this);
|
||||
Q3Action *showDataAction = new Q3Action(NULL, _("Show Data"), 0, this);
|
||||
showDataAction->setToggleAction(TRUE);
|
||||
connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool)));
|
||||
connect(configView, SIGNAL(showDataChanged(bool)), showDataAction, SLOT(setOn(bool)));
|
||||
showDataAction->setOn(configList->showData);
|
||||
QAction *showAllAction = new QAction(NULL, _("Show All Options"), 0, this);
|
||||
showAllAction->setToggleAction(TRUE);
|
||||
connect(showAllAction, SIGNAL(toggled(bool)), configView, SLOT(setShowAll(bool)));
|
||||
connect(showAllAction, SIGNAL(toggled(bool)), menuView, SLOT(setShowAll(bool)));
|
||||
showAllAction->setOn(configList->showAll);
|
||||
QAction *showDebugAction = new QAction(NULL, _("Show Debug Info"), 0, this);
|
||||
|
||||
QActionGroup *optGroup = new QActionGroup(this);
|
||||
optGroup->setExclusive(TRUE);
|
||||
connect(optGroup, SIGNAL(selected(QAction *)), configView,
|
||||
SLOT(setOptionMode(QAction *)));
|
||||
connect(optGroup, SIGNAL(selected(QAction *)), menuView,
|
||||
SLOT(setOptionMode(QAction *)));
|
||||
|
||||
#if QT_VERSION >= 0x040000
|
||||
configView->showNormalAction = new QAction(_("Show Normal Options"), optGroup);
|
||||
configView->showAllAction = new QAction(_("Show All Options"), optGroup);
|
||||
configView->showPromptAction = new QAction(_("Show Prompt Options"), optGroup);
|
||||
#else
|
||||
configView->showNormalAction = new QAction(_("Show Normal Options"), 0, optGroup);
|
||||
configView->showAllAction = new QAction(_("Show All Options"), 0, optGroup);
|
||||
configView->showPromptAction = new QAction(_("Show Prompt Options"), 0, optGroup);
|
||||
#endif
|
||||
configView->showNormalAction->setToggleAction(TRUE);
|
||||
configView->showNormalAction->setOn(configList->optMode == normalOpt);
|
||||
configView->showAllAction->setToggleAction(TRUE);
|
||||
configView->showAllAction->setOn(configList->optMode == allOpt);
|
||||
configView->showPromptAction->setToggleAction(TRUE);
|
||||
configView->showPromptAction->setOn(configList->optMode == promptOpt);
|
||||
|
||||
Q3Action *showDebugAction = new Q3Action(NULL, _("Show Debug Info"), 0, this);
|
||||
showDebugAction->setToggleAction(TRUE);
|
||||
connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool)));
|
||||
connect(helpText, SIGNAL(showDebugChanged(bool)), showDebugAction, SLOT(setOn(bool)));
|
||||
showDebugAction->setOn(helpText->showDebug());
|
||||
|
||||
QAction *showIntroAction = new QAction(NULL, _("Introduction"), 0, this);
|
||||
Q3Action *showIntroAction = new Q3Action(NULL, _("Introduction"), 0, this);
|
||||
connect(showIntroAction, SIGNAL(activated()), SLOT(showIntro()));
|
||||
QAction *showAboutAction = new QAction(NULL, _("About"), 0, this);
|
||||
Q3Action *showAboutAction = new Q3Action(NULL, _("About"), 0, this);
|
||||
connect(showAboutAction, SIGNAL(activated()), SLOT(showAbout()));
|
||||
|
||||
// init tool bar
|
||||
@@ -1376,7 +1400,7 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
fullViewAction->addTo(toolBar);
|
||||
|
||||
// create config menu
|
||||
QPopupMenu* config = new QPopupMenu(this);
|
||||
Q3PopupMenu* config = new Q3PopupMenu(this);
|
||||
menu->insertItem(_("&File"), config);
|
||||
loadAction->addTo(config);
|
||||
saveAction->addTo(config);
|
||||
@@ -1385,22 +1409,22 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
quitAction->addTo(config);
|
||||
|
||||
// create edit menu
|
||||
QPopupMenu* editMenu = new QPopupMenu(this);
|
||||
Q3PopupMenu* editMenu = new Q3PopupMenu(this);
|
||||
menu->insertItem(_("&Edit"), editMenu);
|
||||
searchAction->addTo(editMenu);
|
||||
|
||||
// create options menu
|
||||
QPopupMenu* optionMenu = new QPopupMenu(this);
|
||||
Q3PopupMenu* optionMenu = new Q3PopupMenu(this);
|
||||
menu->insertItem(_("&Option"), optionMenu);
|
||||
showNameAction->addTo(optionMenu);
|
||||
showRangeAction->addTo(optionMenu);
|
||||
showDataAction->addTo(optionMenu);
|
||||
optionMenu->insertSeparator();
|
||||
showAllAction->addTo(optionMenu);
|
||||
showDebugAction->addTo(optionMenu);
|
||||
optGroup->addTo(optionMenu);
|
||||
optionMenu->insertSeparator();
|
||||
|
||||
// create help menu
|
||||
QPopupMenu* helpMenu = new QPopupMenu(this);
|
||||
Q3PopupMenu* helpMenu = new Q3PopupMenu(this);
|
||||
menu->insertSeparator();
|
||||
menu->insertItem(_("&Help"), helpMenu);
|
||||
showIntroAction->addTo(helpMenu);
|
||||
@@ -1435,7 +1459,7 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
showSplitView();
|
||||
|
||||
// UI setup done, restore splitter positions
|
||||
QValueList<int> sizes = configSettings->readSizes("/split1", &ok);
|
||||
Q3ValueList<int> sizes = configSettings->readSizes("/split1", &ok);
|
||||
if (ok)
|
||||
split1->setSizes(sizes);
|
||||
|
||||
@@ -1446,7 +1470,7 @@ ConfigMainWindow::ConfigMainWindow(void)
|
||||
|
||||
void ConfigMainWindow::loadConfig(void)
|
||||
{
|
||||
QString s = QFileDialog::getOpenFileName(conf_get_configname(), NULL, this);
|
||||
QString s = Q3FileDialog::getOpenFileName(conf_get_configname(), NULL, this);
|
||||
if (s.isNull())
|
||||
return;
|
||||
if (conf_read(QFile::encodeName(s)))
|
||||
@@ -1462,7 +1486,7 @@ void ConfigMainWindow::saveConfig(void)
|
||||
|
||||
void ConfigMainWindow::saveConfigAs(void)
|
||||
{
|
||||
QString s = QFileDialog::getSaveFileName(conf_get_configname(), NULL, this);
|
||||
QString s = Q3FileDialog::getSaveFileName(conf_get_configname(), NULL, this);
|
||||
if (s.isNull())
|
||||
return;
|
||||
if (conf_write(QFile::encodeName(s)))
|
||||
@@ -1491,7 +1515,7 @@ void ConfigMainWindow::setMenuLink(struct menu *menu)
|
||||
ConfigList* list = NULL;
|
||||
ConfigItem* item;
|
||||
|
||||
if (!menu_is_visible(menu) && !configView->showAll())
|
||||
if (configList->menuSkip(menu))
|
||||
return;
|
||||
|
||||
switch (configList->mode) {
|
||||
@@ -1631,7 +1655,7 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e)
|
||||
|
||||
void ConfigMainWindow::showIntro(void)
|
||||
{
|
||||
static const QString str = _("Welcome to the qconf graphical kernel configuration tool for Linux.\n\n"
|
||||
static const QString str = _("Welcome to the qconf graphical configuration tool.\n\n"
|
||||
"For each option, a blank box indicates the feature is disabled, a check\n"
|
||||
"indicates it is enabled, and a dot indicates that it is to be compiled\n"
|
||||
"as a module. Clicking on the box will cycle through the three states.\n\n"
|
||||
|
@@ -3,26 +3,25 @@
|
||||
* Released under the terms of the GNU GPL v2.0.
|
||||
*/
|
||||
|
||||
#if QT_VERSION < 0x040000
|
||||
#include <qlistview.h>
|
||||
#if QT_VERSION >= 300
|
||||
#include <qsettings.h>
|
||||
#else
|
||||
class QSettings {
|
||||
public:
|
||||
void beginGroup(const QString& group) { }
|
||||
void endGroup(void) { }
|
||||
bool readBoolEntry(const QString& key, bool def = FALSE, bool* ok = 0) const
|
||||
{ if (ok) *ok = FALSE; return def; }
|
||||
int readNumEntry(const QString& key, int def = 0, bool* ok = 0) const
|
||||
{ if (ok) *ok = FALSE; return def; }
|
||||
QString readEntry(const QString& key, const QString& def = QString::null, bool* ok = 0) const
|
||||
{ if (ok) *ok = FALSE; return def; }
|
||||
QStringList readListEntry(const QString& key, bool* ok = 0) const
|
||||
{ if (ok) *ok = FALSE; return QStringList(); }
|
||||
template <class t>
|
||||
bool writeEntry(const QString& key, t value)
|
||||
{ return TRUE; }
|
||||
};
|
||||
#include <q3listview.h>
|
||||
#endif
|
||||
#include <qsettings.h>
|
||||
|
||||
#if QT_VERSION < 0x040000
|
||||
#define Q3ValueList QValueList
|
||||
#define Q3PopupMenu QPopupMenu
|
||||
#define Q3ListView QListView
|
||||
#define Q3ListViewItem QListViewItem
|
||||
#define Q3VBox QVBox
|
||||
#define Q3TextBrowser QTextBrowser
|
||||
#define Q3MainWindow QMainWindow
|
||||
#define Q3Action QAction
|
||||
#define Q3ToolBar QToolBar
|
||||
#define Q3ListViewItemIterator QListViewItemIterator
|
||||
#define Q3FileDialog QFileDialog
|
||||
#endif
|
||||
|
||||
class ConfigView;
|
||||
@@ -31,11 +30,10 @@ class ConfigItem;
|
||||
class ConfigLineEdit;
|
||||
class ConfigMainWindow;
|
||||
|
||||
|
||||
class ConfigSettings : public QSettings {
|
||||
public:
|
||||
QValueList<int> readSizes(const QString& key, bool *ok);
|
||||
bool writeSizes(const QString& key, const QValueList<int>& value);
|
||||
Q3ValueList<int> readSizes(const QString& key, bool *ok);
|
||||
bool writeSizes(const QString& key, const Q3ValueList<int>& value);
|
||||
};
|
||||
|
||||
enum colIdx {
|
||||
@@ -44,10 +42,13 @@ enum colIdx {
|
||||
enum listMode {
|
||||
singleMode, menuMode, symbolMode, fullMode, listMode
|
||||
};
|
||||
enum optionMode {
|
||||
normalOpt = 0, allOpt, promptOpt
|
||||
};
|
||||
|
||||
class ConfigList : public QListView {
|
||||
class ConfigList : public Q3ListView {
|
||||
Q_OBJECT
|
||||
typedef class QListView Parent;
|
||||
typedef class Q3ListView Parent;
|
||||
public:
|
||||
ConfigList(ConfigView* p, const char *name = 0);
|
||||
void reinit(void);
|
||||
@@ -115,6 +116,8 @@ public:
|
||||
void setAllOpen(bool open);
|
||||
void setParentMenu(void);
|
||||
|
||||
bool menuSkip(struct menu *);
|
||||
|
||||
template <class P>
|
||||
void updateMenuList(P*, struct menu*);
|
||||
|
||||
@@ -124,22 +127,23 @@ public:
|
||||
QPixmap choiceYesPix, choiceNoPix;
|
||||
QPixmap menuPix, menuInvPix, menuBackPix, voidPix;
|
||||
|
||||
bool showAll, showName, showRange, showData;
|
||||
bool showName, showRange, showData;
|
||||
enum listMode mode;
|
||||
enum optionMode optMode;
|
||||
struct menu *rootEntry;
|
||||
QColorGroup disabledColorGroup;
|
||||
QColorGroup inactivedColorGroup;
|
||||
QPopupMenu* headerPopup;
|
||||
Q3PopupMenu* headerPopup;
|
||||
|
||||
private:
|
||||
int colMap[colNr];
|
||||
int colRevMap[colNr];
|
||||
};
|
||||
|
||||
class ConfigItem : public QListViewItem {
|
||||
typedef class QListViewItem Parent;
|
||||
class ConfigItem : public Q3ListViewItem {
|
||||
typedef class Q3ListViewItem Parent;
|
||||
public:
|
||||
ConfigItem(QListView *parent, ConfigItem *after, struct menu *m, bool v)
|
||||
ConfigItem(Q3ListView *parent, ConfigItem *after, struct menu *m, bool v)
|
||||
: Parent(parent, after), menu(m), visible(v), goParent(false)
|
||||
{
|
||||
init();
|
||||
@@ -149,16 +153,14 @@ public:
|
||||
{
|
||||
init();
|
||||
}
|
||||
ConfigItem(QListView *parent, ConfigItem *after, bool v)
|
||||
ConfigItem(Q3ListView *parent, ConfigItem *after, bool v)
|
||||
: Parent(parent, after), menu(0), visible(v), goParent(true)
|
||||
{
|
||||
init();
|
||||
}
|
||||
~ConfigItem(void);
|
||||
void init(void);
|
||||
#if QT_VERSION >= 300
|
||||
void okRename(int col);
|
||||
#endif
|
||||
void updateMenu(void);
|
||||
void testUpdateMenu(bool v);
|
||||
ConfigList* listView() const
|
||||
@@ -213,26 +215,24 @@ public:
|
||||
ConfigItem *item;
|
||||
};
|
||||
|
||||
class ConfigView : public QVBox {
|
||||
class ConfigView : public Q3VBox {
|
||||
Q_OBJECT
|
||||
typedef class QVBox Parent;
|
||||
typedef class Q3VBox Parent;
|
||||
public:
|
||||
ConfigView(QWidget* parent, const char *name = 0);
|
||||
~ConfigView(void);
|
||||
static void updateList(ConfigItem* item);
|
||||
static void updateListAll(void);
|
||||
|
||||
bool showAll(void) const { return list->showAll; }
|
||||
bool showName(void) const { return list->showName; }
|
||||
bool showRange(void) const { return list->showRange; }
|
||||
bool showData(void) const { return list->showData; }
|
||||
public slots:
|
||||
void setShowAll(bool);
|
||||
void setShowName(bool);
|
||||
void setShowRange(bool);
|
||||
void setShowData(bool);
|
||||
void setOptionMode(QAction *);
|
||||
signals:
|
||||
void showAllChanged(bool);
|
||||
void showNameChanged(bool);
|
||||
void showRangeChanged(bool);
|
||||
void showDataChanged(bool);
|
||||
@@ -242,11 +242,15 @@ public:
|
||||
|
||||
static ConfigView* viewList;
|
||||
ConfigView* nextView;
|
||||
|
||||
static QAction *showNormalAction;
|
||||
static QAction *showAllAction;
|
||||
static QAction *showPromptAction;
|
||||
};
|
||||
|
||||
class ConfigInfoView : public QTextBrowser {
|
||||
class ConfigInfoView : public Q3TextBrowser {
|
||||
Q_OBJECT
|
||||
typedef class QTextBrowser Parent;
|
||||
typedef class Q3TextBrowser Parent;
|
||||
public:
|
||||
ConfigInfoView(QWidget* parent, const char *name = 0);
|
||||
bool showDebug(void) const { return _showDebug; }
|
||||
@@ -254,7 +258,6 @@ public:
|
||||
public slots:
|
||||
void setInfo(struct menu *menu);
|
||||
void saveSettings(void);
|
||||
void setSource(const QString& name);
|
||||
void setShowDebug(bool);
|
||||
|
||||
signals:
|
||||
@@ -267,11 +270,11 @@ protected:
|
||||
QString debug_info(struct symbol *sym);
|
||||
static QString print_filter(const QString &str);
|
||||
static void expr_print_help(void *data, struct symbol *sym, const char *str);
|
||||
QPopupMenu* createPopupMenu(const QPoint& pos);
|
||||
Q3PopupMenu* createPopupMenu(const QPoint& pos);
|
||||
void contentsContextMenuEvent(QContextMenuEvent *e);
|
||||
|
||||
struct symbol *sym;
|
||||
struct menu *menu;
|
||||
struct menu *_menu;
|
||||
bool _showDebug;
|
||||
};
|
||||
|
||||
@@ -295,10 +298,10 @@ protected:
|
||||
struct symbol **result;
|
||||
};
|
||||
|
||||
class ConfigMainWindow : public QMainWindow {
|
||||
class ConfigMainWindow : public Q3MainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
static QAction *saveAction;
|
||||
static Q3Action *saveAction;
|
||||
static void conf_changed(void);
|
||||
public:
|
||||
ConfigMainWindow(void);
|
||||
@@ -327,8 +330,8 @@ protected:
|
||||
ConfigView *configView;
|
||||
ConfigList *configList;
|
||||
ConfigInfoView *helpText;
|
||||
QToolBar *toolBar;
|
||||
QAction *backAction;
|
||||
Q3ToolBar *toolBar;
|
||||
Q3Action *backAction;
|
||||
QSplitter* split1;
|
||||
QSplitter* split2;
|
||||
};
|
||||
|
@@ -42,6 +42,8 @@
|
||||
# mv config_strip .config
|
||||
# make oldconfig
|
||||
#
|
||||
use strict;
|
||||
|
||||
my $config = ".config";
|
||||
|
||||
my $uname = `uname -r`;
|
||||
@@ -123,7 +125,6 @@ my %selects;
|
||||
my %prompts;
|
||||
my %objects;
|
||||
my $var;
|
||||
my $cont = 0;
|
||||
my $iflevel = 0;
|
||||
my @ifdeps;
|
||||
|
||||
@@ -137,19 +138,45 @@ sub read_kconfig {
|
||||
my $config;
|
||||
my @kconfigs;
|
||||
|
||||
open(KIN, "$ksource/$kconfig") || die "Can't open $kconfig";
|
||||
my $cont = 0;
|
||||
my $line;
|
||||
|
||||
my $source = "$ksource/$kconfig";
|
||||
my $last_source = "";
|
||||
|
||||
# Check for any environment variables used
|
||||
while ($source =~ /\$(\w+)/ && $last_source ne $source) {
|
||||
my $env = $1;
|
||||
$last_source = $source;
|
||||
$source =~ s/\$$env/$ENV{$env}/;
|
||||
}
|
||||
|
||||
open(KIN, "$source") || die "Can't open $kconfig";
|
||||
while (<KIN>) {
|
||||
chomp;
|
||||
|
||||
# Make sure that lines ending with \ continue
|
||||
if ($cont) {
|
||||
$_ = $line . " " . $_;
|
||||
}
|
||||
|
||||
if (s/\\$//) {
|
||||
$cont = 1;
|
||||
$line = $_;
|
||||
next;
|
||||
}
|
||||
|
||||
$cont = 0;
|
||||
|
||||
# collect any Kconfig sources
|
||||
if (/^source\s*"(.*)"/) {
|
||||
$kconfigs[$#kconfigs+1] = $1;
|
||||
}
|
||||
|
||||
# configs found
|
||||
if (/^\s*config\s+(\S+)\s*$/) {
|
||||
if (/^\s*(menu)?config\s+(\S+)\s*$/) {
|
||||
$state = "NEW";
|
||||
$config = $1;
|
||||
$config = $2;
|
||||
|
||||
for (my $i = 0; $i < $iflevel; $i++) {
|
||||
if ($i) {
|
||||
@@ -178,7 +205,7 @@ sub read_kconfig {
|
||||
# configs without prompts must be selected
|
||||
} elsif ($state ne "NONE" && /^\s*tristate\s\S/) {
|
||||
# note if the config has a prompt
|
||||
$prompt{$config} = 1;
|
||||
$prompts{$config} = 1;
|
||||
|
||||
# Check for if statements
|
||||
} elsif (/^if\s+(.*\S)\s*$/) {
|
||||
@@ -218,6 +245,8 @@ if ($kconfig) {
|
||||
# Read all Makefiles to map the configs to the objects
|
||||
foreach my $makefile (@makefiles) {
|
||||
|
||||
my $cont = 0;
|
||||
|
||||
open(MIN,$makefile) || die "Can't open $makefile";
|
||||
while (<MIN>) {
|
||||
my $objs;
|
||||
@@ -281,7 +310,7 @@ if (defined($lsmod_file)) {
|
||||
# see what modules are loaded on this system
|
||||
my $lsmod;
|
||||
|
||||
foreach $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
|
||||
foreach my $dir ( ("/sbin", "/bin", "/usr/sbin", "/usr/bin") ) {
|
||||
if ( -x "$dir/lsmod" ) {
|
||||
$lsmod = "$dir/lsmod";
|
||||
last;
|
||||
@@ -363,7 +392,7 @@ while ($repeat) {
|
||||
parse_config_dep_select $depends{$config};
|
||||
}
|
||||
|
||||
if (defined($prompt{$config}) || !defined($selects{$config})) {
|
||||
if (defined($prompts{$config}) || !defined($selects{$config})) {
|
||||
next;
|
||||
}
|
||||
|
||||
|
@@ -205,6 +205,16 @@ static void sym_calc_visibility(struct symbol *sym)
|
||||
}
|
||||
if (sym_is_choice_value(sym))
|
||||
return;
|
||||
/* defaulting to "yes" if no explicit "depends on" are given */
|
||||
tri = yes;
|
||||
if (sym->dir_dep.expr)
|
||||
tri = expr_calc_value(sym->dir_dep.expr);
|
||||
if (tri == mod)
|
||||
tri = yes;
|
||||
if (sym->dir_dep.tri != tri) {
|
||||
sym->dir_dep.tri = tri;
|
||||
sym_set_changed(sym);
|
||||
}
|
||||
tri = no;
|
||||
if (sym->rev_dep.expr)
|
||||
tri = expr_calc_value(sym->rev_dep.expr);
|
||||
@@ -216,44 +226,63 @@ static void sym_calc_visibility(struct symbol *sym)
|
||||
}
|
||||
}
|
||||
|
||||
static struct symbol *sym_calc_choice(struct symbol *sym)
|
||||
/*
|
||||
* Find the default symbol for a choice.
|
||||
* First try the default values for the choice symbol
|
||||
* Next locate the first visible choice value
|
||||
* Return NULL if none was found
|
||||
*/
|
||||
struct symbol *sym_choice_default(struct symbol *sym)
|
||||
{
|
||||
struct symbol *def_sym;
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
|
||||
/* is the user choice visible? */
|
||||
def_sym = sym->def[S_DEF_USER].val;
|
||||
if (def_sym) {
|
||||
sym_calc_visibility(def_sym);
|
||||
if (def_sym->visible != no)
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
/* any of the defaults visible? */
|
||||
for_all_defaults(sym, prop) {
|
||||
prop->visible.tri = expr_calc_value(prop->visible.expr);
|
||||
if (prop->visible.tri == no)
|
||||
continue;
|
||||
def_sym = prop_get_symbol(prop);
|
||||
sym_calc_visibility(def_sym);
|
||||
if (def_sym->visible != no)
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
/* just get the first visible value */
|
||||
prop = sym_get_choice_prop(sym);
|
||||
expr_list_for_each_sym(prop->expr, e, def_sym) {
|
||||
sym_calc_visibility(def_sym);
|
||||
expr_list_for_each_sym(prop->expr, e, def_sym)
|
||||
if (def_sym->visible != no)
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
/* no choice? reset tristate value */
|
||||
sym->curr.tri = no;
|
||||
/* failed to locate any defaults */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct symbol *sym_calc_choice(struct symbol *sym)
|
||||
{
|
||||
struct symbol *def_sym;
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
|
||||
/* first calculate all choice values' visibilities */
|
||||
prop = sym_get_choice_prop(sym);
|
||||
expr_list_for_each_sym(prop->expr, e, def_sym)
|
||||
sym_calc_visibility(def_sym);
|
||||
|
||||
/* is the user choice visible? */
|
||||
def_sym = sym->def[S_DEF_USER].val;
|
||||
if (def_sym && def_sym->visible != no)
|
||||
return def_sym;
|
||||
|
||||
def_sym = sym_choice_default(sym);
|
||||
|
||||
if (def_sym == NULL)
|
||||
/* no choice? reset tristate value */
|
||||
sym->curr.tri = no;
|
||||
|
||||
return def_sym;
|
||||
}
|
||||
|
||||
void sym_calc_value(struct symbol *sym)
|
||||
{
|
||||
struct symbol_value newval, oldval;
|
||||
@@ -321,6 +350,14 @@ void sym_calc_value(struct symbol *sym)
|
||||
}
|
||||
}
|
||||
calc_newval:
|
||||
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
|
||||
fprintf(stderr, "warning: (");
|
||||
expr_fprint(sym->rev_dep.expr, stderr);
|
||||
fprintf(stderr, ") selects %s which has unmet direct dependencies (",
|
||||
sym->name);
|
||||
expr_fprint(sym->dir_dep.expr, stderr);
|
||||
fprintf(stderr, ")\n");
|
||||
}
|
||||
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
|
||||
}
|
||||
if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
|
||||
@@ -365,12 +402,13 @@ void sym_calc_value(struct symbol *sym)
|
||||
|
||||
if (sym_is_choice(sym)) {
|
||||
struct symbol *choice_sym;
|
||||
int flags = sym->flags & (SYMBOL_CHANGED | SYMBOL_WRITE);
|
||||
|
||||
prop = sym_get_choice_prop(sym);
|
||||
expr_list_for_each_sym(prop->expr, e, choice_sym) {
|
||||
choice_sym->flags |= flags;
|
||||
if (flags & SYMBOL_CHANGED)
|
||||
if ((sym->flags & SYMBOL_WRITE) &&
|
||||
choice_sym->visible != no)
|
||||
choice_sym->flags |= SYMBOL_WRITE;
|
||||
if (sym->flags & SYMBOL_CHANGED)
|
||||
sym_set_changed(choice_sym);
|
||||
}
|
||||
}
|
||||
@@ -623,6 +661,80 @@ bool sym_set_string_value(struct symbol *sym, const char *newval)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the default value associated to a symbol.
|
||||
* For tristate symbol handle the modules=n case
|
||||
* in which case "m" becomes "y".
|
||||
* If the symbol does not have any default then fallback
|
||||
* to the fixed default values.
|
||||
*/
|
||||
const char *sym_get_string_default(struct symbol *sym)
|
||||
{
|
||||
struct property *prop;
|
||||
struct symbol *ds;
|
||||
const char *str;
|
||||
tristate val;
|
||||
|
||||
sym_calc_visibility(sym);
|
||||
sym_calc_value(modules_sym);
|
||||
val = symbol_no.curr.tri;
|
||||
str = symbol_empty.curr.val;
|
||||
|
||||
/* If symbol has a default value look it up */
|
||||
prop = sym_get_default_prop(sym);
|
||||
if (prop != NULL) {
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
/* The visibility imay limit the value from yes => mod */
|
||||
val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* The following fails to handle the situation
|
||||
* where a default value is further limited by
|
||||
* the valid range.
|
||||
*/
|
||||
ds = prop_get_symbol(prop);
|
||||
if (ds != NULL) {
|
||||
sym_calc_value(ds);
|
||||
str = (const char *)ds->curr.val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle select statements */
|
||||
val = EXPR_OR(val, sym->rev_dep.tri);
|
||||
|
||||
/* transpose mod to yes if modules are not enabled */
|
||||
if (val == mod)
|
||||
if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
|
||||
val = yes;
|
||||
|
||||
/* transpose mod to yes if type is bool */
|
||||
if (sym->type == S_BOOLEAN && val == mod)
|
||||
val = yes;
|
||||
|
||||
switch (sym->type) {
|
||||
case S_BOOLEAN:
|
||||
case S_TRISTATE:
|
||||
switch (val) {
|
||||
case no: return "n";
|
||||
case mod: return "m";
|
||||
case yes: return "y";
|
||||
}
|
||||
case S_INT:
|
||||
case S_HEX:
|
||||
return str;
|
||||
case S_STRING:
|
||||
return str;
|
||||
case S_OTHER:
|
||||
case S_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *sym_get_string_value(struct symbol *sym)
|
||||
{
|
||||
tristate val;
|
||||
@@ -728,6 +840,55 @@ struct symbol *sym_find(const char *name)
|
||||
return symbol;
|
||||
}
|
||||
|
||||
/*
|
||||
* Expand symbol's names embedded in the string given in argument. Symbols'
|
||||
* name to be expanded shall be prefixed by a '$'. Unknown symbol expands to
|
||||
* the empty string.
|
||||
*/
|
||||
const char *sym_expand_string_value(const char *in)
|
||||
{
|
||||
const char *src;
|
||||
char *res;
|
||||
size_t reslen;
|
||||
|
||||
reslen = strlen(in) + 1;
|
||||
res = malloc(reslen);
|
||||
res[0] = '\0';
|
||||
|
||||
while ((src = strchr(in, '$'))) {
|
||||
char *p, name[SYMBOL_MAXLENGTH];
|
||||
const char *symval = "";
|
||||
struct symbol *sym;
|
||||
size_t newlen;
|
||||
|
||||
strncat(res, in, src - in);
|
||||
src++;
|
||||
|
||||
p = name;
|
||||
while (isalnum(*src) || *src == '_')
|
||||
*p++ = *src++;
|
||||
*p = '\0';
|
||||
|
||||
sym = sym_find(name);
|
||||
if (sym != NULL) {
|
||||
sym_calc_value(sym);
|
||||
symval = sym_get_string_value(sym);
|
||||
}
|
||||
|
||||
newlen = strlen(res) + strlen(symval) + strlen(src);
|
||||
if (newlen > reslen) {
|
||||
reslen = newlen;
|
||||
res = realloc(res, reslen);
|
||||
}
|
||||
|
||||
strcat(res, symval);
|
||||
in = src;
|
||||
}
|
||||
strcat(res, in);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct symbol **sym_re_search(const char *pattern)
|
||||
{
|
||||
struct symbol *sym, **sym_arr = NULL;
|
||||
@@ -765,6 +926,112 @@ struct symbol **sym_re_search(const char *pattern)
|
||||
return sym_arr;
|
||||
}
|
||||
|
||||
/*
|
||||
* When we check for recursive dependencies we use a stack to save
|
||||
* current state so we can print out relevant info to user.
|
||||
* The entries are located on the call stack so no need to free memory.
|
||||
* Note inser() remove() must always match to properly clear the stack.
|
||||
*/
|
||||
static struct dep_stack {
|
||||
struct dep_stack *prev, *next;
|
||||
struct symbol *sym;
|
||||
struct property *prop;
|
||||
struct expr *expr;
|
||||
} *check_top;
|
||||
|
||||
static void dep_stack_insert(struct dep_stack *stack, struct symbol *sym)
|
||||
{
|
||||
memset(stack, 0, sizeof(*stack));
|
||||
if (check_top)
|
||||
check_top->next = stack;
|
||||
stack->prev = check_top;
|
||||
stack->sym = sym;
|
||||
check_top = stack;
|
||||
}
|
||||
|
||||
static void dep_stack_remove(void)
|
||||
{
|
||||
check_top = check_top->prev;
|
||||
if (check_top)
|
||||
check_top->next = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when we have detected a recursive dependency.
|
||||
* check_top point to the top of the stact so we use
|
||||
* the ->prev pointer to locate the bottom of the stack.
|
||||
*/
|
||||
static void sym_check_print_recursive(struct symbol *last_sym)
|
||||
{
|
||||
struct dep_stack *stack;
|
||||
struct symbol *sym, *next_sym;
|
||||
struct menu *menu = NULL;
|
||||
struct property *prop;
|
||||
struct dep_stack cv_stack;
|
||||
|
||||
if (sym_is_choice_value(last_sym)) {
|
||||
dep_stack_insert(&cv_stack, last_sym);
|
||||
last_sym = prop_get_symbol(sym_get_choice_prop(last_sym));
|
||||
}
|
||||
|
||||
for (stack = check_top; stack != NULL; stack = stack->prev)
|
||||
if (stack->sym == last_sym)
|
||||
break;
|
||||
if (!stack) {
|
||||
fprintf(stderr, "unexpected recursive dependency error\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (; stack; stack = stack->next) {
|
||||
sym = stack->sym;
|
||||
next_sym = stack->next ? stack->next->sym : last_sym;
|
||||
prop = stack->prop;
|
||||
if (prop == NULL)
|
||||
prop = stack->sym->prop;
|
||||
|
||||
/* for choice values find the menu entry (used below) */
|
||||
if (sym_is_choice(sym) || sym_is_choice_value(sym)) {
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
menu = prop->menu;
|
||||
if (prop->menu)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stack->sym == last_sym)
|
||||
fprintf(stderr, "%s:%d:error: recursive dependency detected!\n",
|
||||
prop->file->name, prop->lineno);
|
||||
if (stack->expr) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s %s value contains %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
prop_get_type_name(prop->type),
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (stack->prop) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s depends on %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (sym_is_choice(sym)) {
|
||||
fprintf(stderr, "%s:%d:\tchoice %s contains symbol %s\n",
|
||||
menu->file->name, menu->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else if (sym_is_choice_value(sym)) {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s is part of choice %s\n",
|
||||
menu->file->name, menu->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
} else {
|
||||
fprintf(stderr, "%s:%d:\tsymbol %s is selected by %s\n",
|
||||
prop->file->name, prop->lineno,
|
||||
sym->name ? sym->name : "<choice>",
|
||||
next_sym->name ? next_sym->name : "<choice>");
|
||||
}
|
||||
}
|
||||
|
||||
if (check_top == &cv_stack)
|
||||
dep_stack_remove();
|
||||
}
|
||||
|
||||
static struct symbol *sym_check_expr_deps(struct expr *e)
|
||||
{
|
||||
@@ -801,24 +1068,33 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
|
||||
{
|
||||
struct symbol *sym2;
|
||||
struct property *prop;
|
||||
struct dep_stack stack;
|
||||
|
||||
dep_stack_insert(&stack, sym);
|
||||
|
||||
sym2 = sym_check_expr_deps(sym->rev_dep.expr);
|
||||
if (sym2)
|
||||
return sym2;
|
||||
goto out;
|
||||
|
||||
for (prop = sym->prop; prop; prop = prop->next) {
|
||||
if (prop->type == P_CHOICE || prop->type == P_SELECT)
|
||||
continue;
|
||||
stack.prop = prop;
|
||||
sym2 = sym_check_expr_deps(prop->visible.expr);
|
||||
if (sym2)
|
||||
break;
|
||||
if (prop->type != P_DEFAULT || sym_is_choice(sym))
|
||||
continue;
|
||||
stack.expr = prop->expr;
|
||||
sym2 = sym_check_expr_deps(prop->expr);
|
||||
if (sym2)
|
||||
break;
|
||||
stack.expr = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
dep_stack_remove();
|
||||
|
||||
return sym2;
|
||||
}
|
||||
|
||||
@@ -827,6 +1103,9 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
||||
struct symbol *sym, *sym2;
|
||||
struct property *prop;
|
||||
struct expr *e;
|
||||
struct dep_stack stack;
|
||||
|
||||
dep_stack_insert(&stack, choice);
|
||||
|
||||
prop = sym_get_choice_prop(choice);
|
||||
expr_list_for_each_sym(prop->expr, e, sym)
|
||||
@@ -840,10 +1119,8 @@ static struct symbol *sym_check_choice_deps(struct symbol *choice)
|
||||
|
||||
expr_list_for_each_sym(prop->expr, e, sym) {
|
||||
sym2 = sym_check_sym_deps(sym);
|
||||
if (sym2) {
|
||||
fprintf(stderr, " -> %s", sym->name);
|
||||
if (sym2)
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
expr_list_for_each_sym(prop->expr, e, sym)
|
||||
@@ -853,6 +1130,8 @@ out:
|
||||
prop_get_symbol(sym_get_choice_prop(sym2)) == choice)
|
||||
sym2 = choice;
|
||||
|
||||
dep_stack_remove();
|
||||
|
||||
return sym2;
|
||||
}
|
||||
|
||||
@@ -862,18 +1141,20 @@ struct symbol *sym_check_deps(struct symbol *sym)
|
||||
struct property *prop;
|
||||
|
||||
if (sym->flags & SYMBOL_CHECK) {
|
||||
fprintf(stderr, "%s:%d:error: found recursive dependency: %s",
|
||||
sym->prop->file->name, sym->prop->lineno,
|
||||
sym->name ? sym->name : "<choice>");
|
||||
sym_check_print_recursive(sym);
|
||||
return sym;
|
||||
}
|
||||
if (sym->flags & SYMBOL_CHECKED)
|
||||
return NULL;
|
||||
|
||||
if (sym_is_choice_value(sym)) {
|
||||
struct dep_stack stack;
|
||||
|
||||
/* for choice groups start the check with main choice symbol */
|
||||
dep_stack_insert(&stack, sym);
|
||||
prop = sym_get_choice_prop(sym);
|
||||
sym2 = sym_check_deps(prop_get_symbol(prop));
|
||||
dep_stack_remove();
|
||||
} else if (sym_is_choice(sym)) {
|
||||
sym2 = sym_check_choice_deps(sym);
|
||||
} else {
|
||||
@@ -882,14 +1163,8 @@ struct symbol *sym_check_deps(struct symbol *sym)
|
||||
sym->flags &= ~SYMBOL_CHECK;
|
||||
}
|
||||
|
||||
if (sym2) {
|
||||
fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>");
|
||||
if (sym2 == sym) {
|
||||
fprintf(stderr, "\n");
|
||||
zconfnerrs++;
|
||||
sym2 = NULL;
|
||||
}
|
||||
}
|
||||
if (sym2 && sym2 == sym)
|
||||
sym2 = NULL;
|
||||
|
||||
return sym2;
|
||||
}
|
||||
@@ -943,6 +1218,8 @@ const char *prop_get_type_name(enum prop_type type)
|
||||
return "select";
|
||||
case P_RANGE:
|
||||
return "range";
|
||||
case P_SYMBOL:
|
||||
return "symbol";
|
||||
case P_UNKNOWN:
|
||||
break;
|
||||
}
|
||||
|
@@ -12,15 +12,18 @@
|
||||
struct file *file_lookup(const char *name)
|
||||
{
|
||||
struct file *file;
|
||||
const char *file_name = sym_expand_string_value(name);
|
||||
|
||||
for (file = file_list; file; file = file->next) {
|
||||
if (!strcmp(name, file->name))
|
||||
if (!strcmp(name, file->name)) {
|
||||
free((void *)file_name);
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
file = malloc(sizeof(*file));
|
||||
memset(file, 0, sizeof(*file));
|
||||
file->name = strdup(name);
|
||||
file->name = file_name;
|
||||
file->next = file_list;
|
||||
file_list = file;
|
||||
return file;
|
||||
|
@@ -304,9 +304,10 @@ void zconf_nextfile(const char *name)
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
|
||||
current_buf->state = YY_CURRENT_BUFFER;
|
||||
yyin = zconf_fopen(name);
|
||||
yyin = zconf_fopen(file->name);
|
||||
if (!yyin) {
|
||||
printf("%s:%d: can't open file \"%s\"\n", zconf_curname(), zconf_lineno(), name);
|
||||
printf("%s:%d: can't open file \"%s\"\n",
|
||||
zconf_curname(), zconf_lineno(), file->name);
|
||||
exit(1);
|
||||
}
|
||||
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
@@ -353,7 +354,7 @@ int zconf_lineno(void)
|
||||
return current_pos.lineno;
|
||||
}
|
||||
|
||||
char *zconf_curname(void)
|
||||
const char *zconf_curname(void)
|
||||
{
|
||||
return current_pos.file ? current_pos.file->name : "<none>";
|
||||
}
|
||||
|
@@ -417,18 +417,18 @@ union yyalloc
|
||||
#endif
|
||||
|
||||
/* YYFINAL -- State number of the termination state. */
|
||||
#define YYFINAL 3
|
||||
#define YYFINAL 11
|
||||
/* YYLAST -- Last index in YYTABLE. */
|
||||
#define YYLAST 259
|
||||
#define YYLAST 277
|
||||
|
||||
/* YYNTOKENS -- Number of terminals. */
|
||||
#define YYNTOKENS 35
|
||||
/* YYNNTS -- Number of nonterminals. */
|
||||
#define YYNNTS 46
|
||||
#define YYNNTS 48
|
||||
/* YYNRULES -- Number of rules. */
|
||||
#define YYNRULES 110
|
||||
#define YYNRULES 113
|
||||
/* YYNRULES -- Number of states. */
|
||||
#define YYNSTATES 180
|
||||
#define YYNSTATES 185
|
||||
|
||||
/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
|
||||
#define YYUNDEFTOK 2
|
||||
@@ -476,73 +476,74 @@ static const yytype_uint8 yytranslate[] =
|
||||
YYRHS. */
|
||||
static const yytype_uint16 yyprhs[] =
|
||||
{
|
||||
0, 0, 3, 5, 6, 9, 12, 15, 20, 23,
|
||||
28, 33, 37, 39, 41, 43, 45, 47, 49, 51,
|
||||
53, 55, 57, 59, 61, 63, 67, 70, 74, 77,
|
||||
81, 84, 85, 88, 91, 94, 97, 100, 103, 107,
|
||||
112, 117, 122, 128, 132, 133, 137, 138, 141, 145,
|
||||
148, 150, 154, 155, 158, 161, 164, 167, 170, 175,
|
||||
179, 182, 187, 188, 191, 195, 197, 201, 202, 205,
|
||||
208, 211, 215, 218, 220, 224, 225, 228, 231, 234,
|
||||
238, 242, 245, 248, 251, 252, 255, 258, 261, 266,
|
||||
267, 270, 272, 274, 277, 280, 283, 285, 288, 289,
|
||||
292, 294, 298, 302, 306, 309, 313, 317, 319, 321,
|
||||
322
|
||||
0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
|
||||
23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
|
||||
52, 54, 56, 58, 60, 62, 64, 66, 70, 73,
|
||||
77, 80, 84, 87, 88, 91, 94, 97, 100, 103,
|
||||
106, 110, 115, 120, 125, 131, 135, 136, 140, 141,
|
||||
144, 148, 151, 153, 157, 158, 161, 164, 167, 170,
|
||||
173, 178, 182, 185, 190, 191, 194, 198, 200, 204,
|
||||
205, 208, 211, 214, 218, 222, 225, 227, 231, 232,
|
||||
235, 238, 241, 245, 249, 252, 255, 258, 259, 262,
|
||||
265, 268, 273, 274, 277, 279, 281, 284, 287, 290,
|
||||
292, 295, 296, 299, 301, 305, 309, 313, 316, 320,
|
||||
324, 326, 328, 329
|
||||
};
|
||||
|
||||
/* YYRHS -- A `-1'-separated list of the rules' RHS. */
|
||||
static const yytype_int8 yyrhs[] =
|
||||
{
|
||||
36, 0, -1, 37, -1, -1, 37, 39, -1, 37,
|
||||
53, -1, 37, 64, -1, 37, 3, 74, 76, -1,
|
||||
37, 75, -1, 37, 25, 1, 30, -1, 37, 38,
|
||||
1, 30, -1, 37, 1, 30, -1, 16, -1, 18,
|
||||
-1, 19, -1, 21, -1, 17, -1, 22, -1, 20,
|
||||
-1, 30, -1, 59, -1, 68, -1, 42, -1, 44,
|
||||
-1, 66, -1, 25, 1, 30, -1, 1, 30, -1,
|
||||
10, 25, 30, -1, 41, 45, -1, 11, 25, 30,
|
||||
-1, 43, 45, -1, -1, 45, 46, -1, 45, 47,
|
||||
-1, 45, 72, -1, 45, 70, -1, 45, 40, -1,
|
||||
45, 30, -1, 19, 73, 30, -1, 18, 74, 77,
|
||||
30, -1, 20, 78, 77, 30, -1, 21, 25, 77,
|
||||
30, -1, 22, 79, 79, 77, 30, -1, 23, 48,
|
||||
30, -1, -1, 48, 25, 49, -1, -1, 33, 74,
|
||||
-1, 7, 80, 30, -1, 50, 54, -1, 75, -1,
|
||||
51, 56, 52, -1, -1, 54, 55, -1, 54, 72,
|
||||
-1, 54, 70, -1, 54, 30, -1, 54, 40, -1,
|
||||
18, 74, 77, 30, -1, 19, 73, 30, -1, 17,
|
||||
30, -1, 20, 25, 77, 30, -1, -1, 56, 39,
|
||||
-1, 14, 78, 76, -1, 75, -1, 57, 60, 58,
|
||||
-1, -1, 60, 39, -1, 60, 64, -1, 60, 53,
|
||||
-1, 4, 74, 30, -1, 61, 71, -1, 75, -1,
|
||||
62, 65, 63, -1, -1, 65, 39, -1, 65, 64,
|
||||
-1, 65, 53, -1, 6, 74, 30, -1, 9, 74,
|
||||
30, -1, 67, 71, -1, 12, 30, -1, 69, 13,
|
||||
-1, -1, 71, 72, -1, 71, 30, -1, 71, 40,
|
||||
-1, 16, 24, 78, 30, -1, -1, 74, 77, -1,
|
||||
25, -1, 26, -1, 5, 30, -1, 8, 30, -1,
|
||||
15, 30, -1, 30, -1, 76, 30, -1, -1, 14,
|
||||
78, -1, 79, -1, 79, 33, 79, -1, 79, 27,
|
||||
79, -1, 29, 78, 28, -1, 34, 78, -1, 78,
|
||||
31, 78, -1, 78, 32, 78, -1, 25, -1, 26,
|
||||
-1, -1, 25, -1
|
||||
36, 0, -1, 78, 37, -1, 37, -1, 62, 38,
|
||||
-1, 38, -1, -1, 38, 40, -1, 38, 54, -1,
|
||||
38, 66, -1, 38, 77, -1, 38, 25, 1, 30,
|
||||
-1, 38, 39, 1, 30, -1, 38, 1, 30, -1,
|
||||
16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
|
||||
22, -1, 20, -1, 30, -1, 60, -1, 70, -1,
|
||||
43, -1, 45, -1, 68, -1, 25, 1, 30, -1,
|
||||
1, 30, -1, 10, 25, 30, -1, 42, 46, -1,
|
||||
11, 25, 30, -1, 44, 46, -1, -1, 46, 47,
|
||||
-1, 46, 48, -1, 46, 74, -1, 46, 72, -1,
|
||||
46, 41, -1, 46, 30, -1, 19, 75, 30, -1,
|
||||
18, 76, 79, 30, -1, 20, 80, 79, 30, -1,
|
||||
21, 25, 79, 30, -1, 22, 81, 81, 79, 30,
|
||||
-1, 23, 49, 30, -1, -1, 49, 25, 50, -1,
|
||||
-1, 33, 76, -1, 7, 82, 30, -1, 51, 55,
|
||||
-1, 77, -1, 52, 57, 53, -1, -1, 55, 56,
|
||||
-1, 55, 74, -1, 55, 72, -1, 55, 30, -1,
|
||||
55, 41, -1, 18, 76, 79, 30, -1, 19, 75,
|
||||
30, -1, 17, 30, -1, 20, 25, 79, 30, -1,
|
||||
-1, 57, 40, -1, 14, 80, 78, -1, 77, -1,
|
||||
58, 61, 59, -1, -1, 61, 40, -1, 61, 66,
|
||||
-1, 61, 54, -1, 3, 76, 78, -1, 4, 76,
|
||||
30, -1, 63, 73, -1, 77, -1, 64, 67, 65,
|
||||
-1, -1, 67, 40, -1, 67, 66, -1, 67, 54,
|
||||
-1, 6, 76, 30, -1, 9, 76, 30, -1, 69,
|
||||
73, -1, 12, 30, -1, 71, 13, -1, -1, 73,
|
||||
74, -1, 73, 30, -1, 73, 41, -1, 16, 24,
|
||||
80, 30, -1, -1, 76, 79, -1, 25, -1, 26,
|
||||
-1, 5, 30, -1, 8, 30, -1, 15, 30, -1,
|
||||
30, -1, 78, 30, -1, -1, 14, 80, -1, 81,
|
||||
-1, 81, 33, 81, -1, 81, 27, 81, -1, 29,
|
||||
80, 28, -1, 34, 80, -1, 80, 31, 80, -1,
|
||||
80, 32, 80, -1, 25, -1, 26, -1, -1, 25,
|
||||
-1
|
||||
};
|
||||
|
||||
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
|
||||
static const yytype_uint16 yyrline[] =
|
||||
{
|
||||
0, 107, 107, 109, 111, 112, 113, 114, 115, 116,
|
||||
117, 121, 125, 125, 125, 125, 125, 125, 125, 129,
|
||||
130, 131, 132, 133, 134, 138, 139, 145, 153, 159,
|
||||
167, 177, 179, 180, 181, 182, 183, 184, 187, 195,
|
||||
201, 211, 217, 223, 226, 228, 239, 240, 245, 254,
|
||||
259, 267, 270, 272, 273, 274, 275, 276, 279, 285,
|
||||
296, 302, 312, 314, 319, 327, 335, 338, 340, 341,
|
||||
342, 347, 354, 359, 367, 370, 372, 373, 374, 377,
|
||||
385, 392, 399, 405, 412, 414, 415, 416, 419, 427,
|
||||
429, 434, 435, 438, 439, 440, 444, 445, 448, 449,
|
||||
452, 453, 454, 455, 456, 457, 458, 461, 462, 465,
|
||||
466
|
||||
0, 107, 107, 107, 109, 109, 111, 113, 114, 115,
|
||||
116, 117, 118, 122, 126, 126, 126, 126, 126, 126,
|
||||
126, 130, 131, 132, 133, 134, 135, 139, 140, 146,
|
||||
154, 160, 168, 178, 180, 181, 182, 183, 184, 185,
|
||||
188, 196, 202, 212, 218, 224, 227, 229, 240, 241,
|
||||
246, 255, 260, 268, 271, 273, 274, 275, 276, 277,
|
||||
280, 286, 297, 303, 313, 315, 320, 328, 336, 339,
|
||||
341, 342, 343, 348, 355, 362, 367, 375, 378, 380,
|
||||
381, 382, 385, 393, 400, 407, 413, 420, 422, 423,
|
||||
424, 427, 435, 437, 442, 443, 446, 447, 448, 452,
|
||||
453, 456, 457, 460, 461, 462, 463, 464, 465, 466,
|
||||
469, 470, 473, 474
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -557,17 +558,17 @@ static const char *const yytname[] =
|
||||
"T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
|
||||
"T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
|
||||
"T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
|
||||
"T_NOT", "$accept", "input", "stmt_list", "option_name", "common_stmt",
|
||||
"option_error", "config_entry_start", "config_stmt",
|
||||
"T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
|
||||
"common_stmt", "option_error", "config_entry_start", "config_stmt",
|
||||
"menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
|
||||
"config_option", "symbol_option", "symbol_option_list",
|
||||
"symbol_option_arg", "choice", "choice_entry", "choice_end",
|
||||
"choice_stmt", "choice_option_list", "choice_option", "choice_block",
|
||||
"if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry",
|
||||
"menu_end", "menu_stmt", "menu_block", "source_stmt", "comment",
|
||||
"comment_stmt", "help_start", "help", "depends_list", "depends",
|
||||
"prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
|
||||
"word_opt", 0
|
||||
"if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
|
||||
"menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
|
||||
"comment", "comment_stmt", "help_start", "help", "depends_list",
|
||||
"depends", "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr",
|
||||
"symbol", "word_opt", 0
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -586,35 +587,35 @@ static const yytype_uint16 yytoknum[] =
|
||||
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
|
||||
static const yytype_uint8 yyr1[] =
|
||||
{
|
||||
0, 35, 36, 37, 37, 37, 37, 37, 37, 37,
|
||||
37, 37, 38, 38, 38, 38, 38, 38, 38, 39,
|
||||
39, 39, 39, 39, 39, 40, 40, 41, 42, 43,
|
||||
44, 45, 45, 45, 45, 45, 45, 45, 46, 46,
|
||||
46, 46, 46, 47, 48, 48, 49, 49, 50, 51,
|
||||
52, 53, 54, 54, 54, 54, 54, 54, 55, 55,
|
||||
55, 55, 56, 56, 57, 58, 59, 60, 60, 60,
|
||||
60, 61, 62, 63, 64, 65, 65, 65, 65, 66,
|
||||
67, 68, 69, 70, 71, 71, 71, 71, 72, 73,
|
||||
73, 74, 74, 75, 75, 75, 76, 76, 77, 77,
|
||||
78, 78, 78, 78, 78, 78, 78, 79, 79, 80,
|
||||
80
|
||||
0, 35, 36, 36, 37, 37, 38, 38, 38, 38,
|
||||
38, 38, 38, 38, 39, 39, 39, 39, 39, 39,
|
||||
39, 40, 40, 40, 40, 40, 40, 41, 41, 42,
|
||||
43, 44, 45, 46, 46, 46, 46, 46, 46, 46,
|
||||
47, 47, 47, 47, 47, 48, 49, 49, 50, 50,
|
||||
51, 52, 53, 54, 55, 55, 55, 55, 55, 55,
|
||||
56, 56, 56, 56, 57, 57, 58, 59, 60, 61,
|
||||
61, 61, 61, 62, 63, 64, 65, 66, 67, 67,
|
||||
67, 67, 68, 69, 70, 71, 72, 73, 73, 73,
|
||||
73, 74, 75, 75, 76, 76, 77, 77, 77, 78,
|
||||
78, 79, 79, 80, 80, 80, 80, 80, 80, 80,
|
||||
81, 81, 82, 82
|
||||
};
|
||||
|
||||
/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
|
||||
static const yytype_uint8 yyr2[] =
|
||||
{
|
||||
0, 2, 1, 0, 2, 2, 2, 4, 2, 4,
|
||||
4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 3, 2, 3, 2, 3,
|
||||
2, 0, 2, 2, 2, 2, 2, 2, 3, 4,
|
||||
4, 4, 5, 3, 0, 3, 0, 2, 3, 2,
|
||||
1, 3, 0, 2, 2, 2, 2, 2, 4, 3,
|
||||
2, 4, 0, 2, 3, 1, 3, 0, 2, 2,
|
||||
2, 3, 2, 1, 3, 0, 2, 2, 2, 3,
|
||||
3, 2, 2, 2, 0, 2, 2, 2, 4, 0,
|
||||
2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
|
||||
1, 3, 3, 3, 2, 3, 3, 1, 1, 0,
|
||||
1
|
||||
0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
|
||||
2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 3, 2, 3,
|
||||
2, 3, 2, 0, 2, 2, 2, 2, 2, 2,
|
||||
3, 4, 4, 4, 5, 3, 0, 3, 0, 2,
|
||||
3, 2, 1, 3, 0, 2, 2, 2, 2, 2,
|
||||
4, 3, 2, 4, 0, 2, 3, 1, 3, 0,
|
||||
2, 2, 2, 3, 3, 2, 1, 3, 0, 2,
|
||||
2, 2, 3, 3, 2, 2, 2, 0, 2, 2,
|
||||
2, 4, 0, 2, 1, 1, 2, 2, 2, 1,
|
||||
2, 0, 2, 1, 3, 3, 3, 2, 3, 3,
|
||||
1, 1, 0, 1
|
||||
};
|
||||
|
||||
/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
|
||||
@@ -622,158 +623,165 @@ static const yytype_uint8 yyr2[] =
|
||||
means the default is an error. */
|
||||
static const yytype_uint8 yydefact[] =
|
||||
{
|
||||
3, 0, 0, 1, 0, 0, 0, 0, 0, 109,
|
||||
0, 0, 0, 0, 0, 0, 12, 16, 13, 14,
|
||||
18, 15, 17, 0, 19, 0, 4, 31, 22, 31,
|
||||
23, 52, 62, 5, 67, 20, 84, 75, 6, 24,
|
||||
84, 21, 8, 11, 91, 92, 0, 0, 93, 0,
|
||||
110, 0, 94, 0, 0, 0, 107, 108, 0, 0,
|
||||
0, 100, 95, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 96, 7, 71, 79, 48, 80, 27,
|
||||
29, 0, 104, 0, 0, 64, 0, 0, 9, 10,
|
||||
0, 0, 0, 0, 89, 0, 0, 0, 44, 0,
|
||||
37, 36, 32, 33, 0, 35, 34, 0, 0, 89,
|
||||
0, 56, 57, 53, 55, 54, 63, 51, 50, 68,
|
||||
70, 66, 69, 65, 86, 87, 85, 76, 78, 74,
|
||||
77, 73, 97, 103, 105, 106, 102, 101, 26, 82,
|
||||
0, 98, 0, 98, 98, 98, 0, 0, 0, 83,
|
||||
60, 98, 0, 98, 0, 0, 0, 38, 90, 0,
|
||||
0, 98, 46, 43, 25, 0, 59, 0, 88, 99,
|
||||
39, 40, 41, 0, 0, 45, 58, 61, 42, 47
|
||||
6, 0, 99, 0, 3, 0, 6, 6, 94, 95,
|
||||
0, 1, 0, 0, 0, 0, 112, 0, 0, 0,
|
||||
0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
|
||||
0, 21, 0, 7, 33, 24, 33, 25, 54, 64,
|
||||
8, 69, 22, 87, 78, 9, 26, 87, 23, 10,
|
||||
0, 100, 2, 73, 13, 0, 96, 0, 113, 0,
|
||||
97, 0, 0, 0, 110, 111, 0, 0, 0, 103,
|
||||
98, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 74, 82, 50, 83, 29, 31, 0, 107, 0,
|
||||
0, 66, 0, 0, 11, 12, 0, 0, 0, 0,
|
||||
92, 0, 0, 0, 46, 0, 39, 38, 34, 35,
|
||||
0, 37, 36, 0, 0, 92, 0, 58, 59, 55,
|
||||
57, 56, 65, 53, 52, 70, 72, 68, 71, 67,
|
||||
89, 90, 88, 79, 81, 77, 80, 76, 106, 108,
|
||||
109, 105, 104, 28, 85, 0, 101, 0, 101, 101,
|
||||
101, 0, 0, 0, 86, 62, 101, 0, 101, 0,
|
||||
0, 0, 40, 93, 0, 0, 101, 48, 45, 27,
|
||||
0, 61, 0, 91, 102, 41, 42, 43, 0, 0,
|
||||
47, 60, 63, 44, 49
|
||||
};
|
||||
|
||||
/* YYDEFGOTO[NTERM-NUM]. */
|
||||
static const yytype_int16 yydefgoto[] =
|
||||
{
|
||||
-1, 1, 2, 25, 26, 101, 27, 28, 29, 30,
|
||||
65, 102, 103, 147, 175, 31, 32, 117, 33, 67,
|
||||
113, 68, 34, 121, 35, 69, 36, 37, 129, 38,
|
||||
71, 39, 40, 41, 104, 105, 70, 106, 142, 143,
|
||||
42, 74, 156, 60, 61, 51
|
||||
-1, 3, 4, 5, 32, 33, 107, 34, 35, 36,
|
||||
37, 73, 108, 109, 152, 180, 38, 39, 123, 40,
|
||||
75, 119, 76, 41, 127, 42, 77, 6, 43, 44,
|
||||
135, 45, 79, 46, 47, 48, 110, 111, 78, 112,
|
||||
147, 148, 49, 7, 161, 68, 69, 59
|
||||
};
|
||||
|
||||
/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
|
||||
STATE-NUM. */
|
||||
#define YYPACT_NINF -80
|
||||
#define YYPACT_NINF -89
|
||||
static const yytype_int16 yypact[] =
|
||||
{
|
||||
-80, 2, 132, -80, -13, -1, -1, -2, -1, 9,
|
||||
33, -1, 27, 40, -3, 38, -80, -80, -80, -80,
|
||||
-80, -80, -80, 71, -80, 77, -80, -80, -80, -80,
|
||||
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
|
||||
-80, -80, -80, -80, -80, -80, 57, 61, -80, 63,
|
||||
-80, 76, -80, 87, 101, 133, -80, -80, -3, -3,
|
||||
195, -6, -80, 136, 149, 39, 104, 65, 150, 5,
|
||||
194, 5, 167, -80, 176, -80, -80, -80, -80, -80,
|
||||
-80, 68, -80, -3, -3, 176, 72, 72, -80, -80,
|
||||
177, 187, 78, -1, -1, -3, 196, 72, -80, 222,
|
||||
-80, -80, -80, -80, 221, -80, -80, 205, -1, -1,
|
||||
211, -80, -80, -80, -80, -80, -80, -80, -80, -80,
|
||||
-80, -80, -80, -80, -80, -80, -80, -80, -80, -80,
|
||||
-80, -80, -80, -80, 206, -80, -80, -80, -80, -80,
|
||||
-3, 223, 209, 223, 197, 223, 72, 7, 210, -80,
|
||||
-80, 223, 212, 223, 201, -3, 213, -80, -80, 214,
|
||||
215, 223, 208, -80, -80, 216, -80, 217, -80, 113,
|
||||
-80, -80, -80, 218, -1, -80, -80, -80, -80, -80
|
||||
3, 4, -89, 20, -89, 100, -89, 7, -89, -89,
|
||||
-8, -89, 17, 4, 28, 4, 37, 36, 4, 68,
|
||||
87, -18, 69, -89, -89, -89, -89, -89, -89, -89,
|
||||
128, -89, 138, -89, -89, -89, -89, -89, -89, -89,
|
||||
-89, -89, -89, -89, -89, -89, -89, -89, -89, -89,
|
||||
127, -89, -89, 110, -89, 126, -89, 136, -89, 137,
|
||||
-89, 147, 150, 152, -89, -89, -18, -18, 171, -14,
|
||||
-89, 153, 157, 34, 67, 180, 233, 220, 207, 220,
|
||||
154, -89, -89, -89, -89, -89, -89, 0, -89, -18,
|
||||
-18, 110, 44, 44, -89, -89, 163, 174, 182, 4,
|
||||
4, -18, 194, 44, -89, 219, -89, -89, -89, -89,
|
||||
223, -89, -89, 203, 4, 4, 215, -89, -89, -89,
|
||||
-89, -89, -89, -89, -89, -89, -89, -89, -89, -89,
|
||||
-89, -89, -89, -89, -89, -89, -89, -89, -89, 213,
|
||||
-89, -89, -89, -89, -89, -18, 232, 227, 232, -5,
|
||||
232, 44, 35, 234, -89, -89, 232, 235, 232, 224,
|
||||
-18, 236, -89, -89, 237, 238, 232, 216, -89, -89,
|
||||
240, -89, 241, -89, 71, -89, -89, -89, 242, 4,
|
||||
-89, -89, -89, -89, -89
|
||||
};
|
||||
|
||||
/* YYPGOTO[NTERM-NUM]. */
|
||||
static const yytype_int16 yypgoto[] =
|
||||
{
|
||||
-80, -80, -80, -80, 122, -34, -80, -80, -80, -80,
|
||||
220, -80, -80, -80, -80, -80, -80, -80, 59, -80,
|
||||
-80, -80, -80, -80, -80, -80, -80, -80, -80, 125,
|
||||
-80, -80, -80, -80, -80, 183, 219, 22, 142, -5,
|
||||
147, 192, 69, -54, -79, -80
|
||||
-89, -89, 255, 267, -89, 47, -57, -89, -89, -89,
|
||||
-89, 239, -89, -89, -89, -89, -89, -89, -89, 130,
|
||||
-89, -89, -89, -89, -89, -89, -89, -89, -89, -89,
|
||||
-89, 181, -89, -89, -89, -89, -89, 199, 229, 16,
|
||||
162, -1, 74, -7, 103, -65, -88, -89
|
||||
};
|
||||
|
||||
/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
|
||||
positive, shift that token. If negative, reduce the rule which
|
||||
number is the opposite. If zero, do what YYDEFACT says.
|
||||
If YYTABLE_NINF, syntax error. */
|
||||
#define YYTABLE_NINF -82
|
||||
#define YYTABLE_NINF -85
|
||||
static const yytype_int16 yytable[] =
|
||||
{
|
||||
46, 47, 3, 49, 81, 82, 53, 136, 137, 6,
|
||||
7, 8, 9, 10, 11, 12, 13, 43, 146, 14,
|
||||
15, 86, 56, 57, 44, 45, 58, 87, 48, 134,
|
||||
135, 59, 162, 112, 50, 24, 125, 163, 125, -28,
|
||||
90, 144, -28, -28, -28, -28, -28, -28, -28, -28,
|
||||
-28, 91, 54, -28, -28, 92, -28, 93, 94, 95,
|
||||
96, 97, 98, 52, 99, 55, 90, 161, 62, 100,
|
||||
-49, -49, 63, -49, -49, -49, -49, 91, 64, -49,
|
||||
-49, 92, 107, 108, 109, 110, 154, 73, 141, 115,
|
||||
99, 75, 126, 76, 126, 111, 133, 56, 57, 83,
|
||||
84, 169, 140, 151, -30, 90, 77, -30, -30, -30,
|
||||
-30, -30, -30, -30, -30, -30, 91, 78, -30, -30,
|
||||
92, -30, 93, 94, 95, 96, 97, 98, 120, 99,
|
||||
128, 79, -2, 4, 100, 5, 6, 7, 8, 9,
|
||||
10, 11, 12, 13, 83, 84, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 7, 8, 23, 10, 11,
|
||||
12, 13, 24, 80, 14, 15, 88, -81, 90, 179,
|
||||
-81, -81, -81, -81, -81, -81, -81, -81, -81, 89,
|
||||
24, -81, -81, 92, -81, -81, -81, -81, -81, -81,
|
||||
116, 119, 99, 127, 122, 90, 130, 124, -72, -72,
|
||||
-72, -72, -72, -72, -72, -72, 132, 138, -72, -72,
|
||||
92, 155, 158, 159, 160, 118, 123, 139, 131, 99,
|
||||
165, 145, 167, 148, 124, 73, 83, 84, 83, 84,
|
||||
173, 168, 83, 84, 149, 150, 153, 155, 84, 157,
|
||||
164, 174, 166, 170, 171, 172, 176, 177, 178, 66,
|
||||
114, 152, 85, 0, 0, 0, 0, 0, 0, 72
|
||||
10, 87, 88, 53, 141, 142, 1, 64, 65, 160,
|
||||
1, 66, 55, 92, 57, 151, 67, 61, 118, 93,
|
||||
11, 131, 2, 131, 139, 140, 89, 90, 138, 8,
|
||||
9, 89, 90, 2, -30, 96, 149, 51, -30, -30,
|
||||
-30, -30, -30, -30, -30, -30, 97, 54, -30, -30,
|
||||
98, -30, 99, 100, 101, 102, 103, 104, 56, 105,
|
||||
167, 91, 58, 166, 106, 168, 60, -32, 96, 64,
|
||||
65, -32, -32, -32, -32, -32, -32, -32, -32, 97,
|
||||
159, -32, -32, 98, -32, 99, 100, 101, 102, 103,
|
||||
104, 121, 105, 62, 132, 174, 132, 106, 146, 70,
|
||||
-5, 12, 89, 90, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 63, 156, 21, 22, 23, 24, 25, 26,
|
||||
27, 28, 29, 122, 125, 30, 133, -4, 12, 71,
|
||||
31, 13, 14, 15, 16, 17, 18, 19, 20, 72,
|
||||
51, 21, 22, 23, 24, 25, 26, 27, 28, 29,
|
||||
124, 129, 30, 137, -84, 96, 81, 31, -84, -84,
|
||||
-84, -84, -84, -84, -84, -84, 82, 83, -84, -84,
|
||||
98, -84, -84, -84, -84, -84, -84, 84, 184, 105,
|
||||
85, 96, 86, 94, 130, -51, -51, 95, -51, -51,
|
||||
-51, -51, 97, 143, -51, -51, 98, 113, 114, 115,
|
||||
116, 2, 89, 90, 144, 105, 145, 126, 96, 134,
|
||||
117, -75, -75, -75, -75, -75, -75, -75, -75, 150,
|
||||
153, -75, -75, 98, 13, 14, 15, 16, 17, 18,
|
||||
19, 20, 105, 155, 21, 22, 154, 130, 14, 15,
|
||||
158, 17, 18, 19, 20, 90, 160, 21, 22, 179,
|
||||
31, 163, 164, 165, 173, 89, 90, 162, 128, 170,
|
||||
136, 172, 52, 31, 169, 171, 175, 176, 177, 178,
|
||||
181, 182, 183, 50, 120, 74, 80, 157
|
||||
};
|
||||
|
||||
static const yytype_int16 yycheck[] =
|
||||
static const yytype_uint8 yycheck[] =
|
||||
{
|
||||
5, 6, 0, 8, 58, 59, 11, 86, 87, 4,
|
||||
5, 6, 7, 8, 9, 10, 11, 30, 97, 14,
|
||||
15, 27, 25, 26, 25, 26, 29, 33, 30, 83,
|
||||
84, 34, 25, 67, 25, 30, 70, 30, 72, 0,
|
||||
1, 95, 3, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 12, 25, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 30, 25, 25, 1, 146, 30, 30,
|
||||
5, 6, 1, 8, 9, 10, 11, 12, 1, 14,
|
||||
15, 16, 17, 18, 19, 20, 140, 30, 93, 67,
|
||||
25, 30, 70, 30, 72, 30, 28, 25, 26, 31,
|
||||
32, 155, 24, 108, 0, 1, 30, 3, 4, 5,
|
||||
1, 66, 67, 10, 92, 93, 3, 25, 26, 14,
|
||||
3, 29, 13, 27, 15, 103, 34, 18, 75, 33,
|
||||
0, 78, 30, 80, 89, 90, 31, 32, 28, 25,
|
||||
26, 31, 32, 30, 0, 1, 101, 30, 4, 5,
|
||||
6, 7, 8, 9, 10, 11, 12, 30, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 69, 25,
|
||||
71, 30, 0, 1, 30, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 31, 32, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 5, 6, 25, 8, 9,
|
||||
10, 11, 30, 30, 14, 15, 30, 0, 1, 174,
|
||||
3, 4, 5, 6, 7, 8, 9, 10, 11, 30,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 30, 25,
|
||||
25, 68, 25, 151, 30, 30, 30, 0, 1, 25,
|
||||
26, 4, 5, 6, 7, 8, 9, 10, 11, 12,
|
||||
145, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
23, 75, 25, 25, 78, 160, 80, 30, 99, 30,
|
||||
0, 1, 31, 32, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 25, 114, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 76, 77, 25, 79, 0, 1, 1,
|
||||
30, 4, 5, 6, 7, 8, 9, 10, 11, 1,
|
||||
30, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
68, 69, 25, 71, 69, 1, 71, 30, 4, 5,
|
||||
76, 77, 25, 79, 0, 1, 30, 30, 4, 5,
|
||||
6, 7, 8, 9, 10, 11, 30, 30, 14, 15,
|
||||
16, 14, 143, 144, 145, 68, 69, 30, 71, 25,
|
||||
151, 25, 153, 1, 30, 30, 31, 32, 31, 32,
|
||||
161, 30, 31, 32, 13, 30, 25, 14, 32, 30,
|
||||
30, 33, 30, 30, 30, 30, 30, 30, 30, 29,
|
||||
67, 109, 60, -1, -1, -1, -1, -1, -1, 40
|
||||
16, 17, 18, 19, 20, 21, 22, 30, 179, 25,
|
||||
30, 1, 30, 30, 30, 5, 6, 30, 8, 9,
|
||||
10, 11, 12, 30, 14, 15, 16, 17, 18, 19,
|
||||
20, 30, 31, 32, 30, 25, 24, 77, 1, 79,
|
||||
30, 4, 5, 6, 7, 8, 9, 10, 11, 25,
|
||||
1, 14, 15, 16, 4, 5, 6, 7, 8, 9,
|
||||
10, 11, 25, 30, 14, 15, 13, 30, 5, 6,
|
||||
25, 8, 9, 10, 11, 32, 14, 14, 15, 33,
|
||||
30, 148, 149, 150, 30, 31, 32, 30, 77, 156,
|
||||
79, 158, 7, 30, 30, 30, 30, 30, 30, 166,
|
||||
30, 30, 30, 6, 75, 36, 47, 115
|
||||
};
|
||||
|
||||
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
|
||||
symbol of state STATE-NUM. */
|
||||
static const yytype_uint8 yystos[] =
|
||||
{
|
||||
0, 36, 37, 0, 1, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 14, 15, 16, 17, 18, 19,
|
||||
20, 21, 22, 25, 30, 38, 39, 41, 42, 43,
|
||||
44, 50, 51, 53, 57, 59, 61, 62, 64, 66,
|
||||
67, 68, 75, 30, 25, 26, 74, 74, 30, 74,
|
||||
25, 80, 30, 74, 25, 25, 25, 26, 29, 34,
|
||||
78, 79, 30, 1, 1, 45, 45, 54, 56, 60,
|
||||
71, 65, 71, 30, 76, 30, 30, 30, 30, 30,
|
||||
30, 78, 78, 31, 32, 76, 27, 33, 30, 30,
|
||||
1, 12, 16, 18, 19, 20, 21, 22, 23, 25,
|
||||
30, 40, 46, 47, 69, 70, 72, 17, 18, 19,
|
||||
20, 30, 40, 55, 70, 72, 39, 52, 75, 39,
|
||||
53, 58, 64, 75, 30, 40, 72, 39, 53, 63,
|
||||
64, 75, 30, 28, 78, 78, 79, 79, 30, 30,
|
||||
24, 74, 73, 74, 78, 25, 79, 48, 1, 13,
|
||||
30, 74, 73, 25, 78, 14, 77, 30, 77, 77,
|
||||
77, 79, 25, 30, 30, 77, 30, 77, 30, 78,
|
||||
30, 30, 30, 77, 33, 49, 30, 30, 30, 74
|
||||
0, 3, 30, 36, 37, 38, 62, 78, 25, 26,
|
||||
76, 0, 1, 4, 5, 6, 7, 8, 9, 10,
|
||||
11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
|
||||
25, 30, 39, 40, 42, 43, 44, 45, 51, 52,
|
||||
54, 58, 60, 63, 64, 66, 68, 69, 70, 77,
|
||||
38, 30, 37, 78, 30, 76, 30, 76, 25, 82,
|
||||
30, 76, 25, 25, 25, 26, 29, 34, 80, 81,
|
||||
30, 1, 1, 46, 46, 55, 57, 61, 73, 67,
|
||||
73, 30, 30, 30, 30, 30, 30, 80, 80, 31,
|
||||
32, 78, 27, 33, 30, 30, 1, 12, 16, 18,
|
||||
19, 20, 21, 22, 23, 25, 30, 41, 47, 48,
|
||||
71, 72, 74, 17, 18, 19, 20, 30, 41, 56,
|
||||
72, 74, 40, 53, 77, 40, 54, 59, 66, 77,
|
||||
30, 41, 74, 40, 54, 65, 66, 77, 28, 80,
|
||||
80, 81, 81, 30, 30, 24, 76, 75, 76, 80,
|
||||
25, 81, 49, 1, 13, 30, 76, 75, 25, 80,
|
||||
14, 79, 30, 79, 79, 79, 81, 25, 30, 30,
|
||||
79, 30, 79, 30, 80, 30, 30, 30, 79, 33,
|
||||
50, 30, 30, 30, 76
|
||||
};
|
||||
|
||||
#define yyerrok (yyerrstatus = 0)
|
||||
@@ -1284,7 +1292,7 @@ yydestruct (yymsg, yytype, yyvaluep)
|
||||
|
||||
switch (yytype)
|
||||
{
|
||||
case 51: /* "choice_entry" */
|
||||
case 52: /* "choice_entry" */
|
||||
|
||||
{
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
@@ -1294,7 +1302,7 @@ yydestruct (yymsg, yytype, yyvaluep)
|
||||
};
|
||||
|
||||
break;
|
||||
case 57: /* "if_entry" */
|
||||
case 58: /* "if_entry" */
|
||||
|
||||
{
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
@@ -1304,7 +1312,7 @@ yydestruct (yymsg, yytype, yyvaluep)
|
||||
};
|
||||
|
||||
break;
|
||||
case 62: /* "menu_entry" */
|
||||
case 64: /* "menu_entry" */
|
||||
|
||||
{
|
||||
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
|
||||
@@ -1614,39 +1622,39 @@ yyreduce:
|
||||
YY_REDUCE_PRINT (yyn);
|
||||
switch (yyn)
|
||||
{
|
||||
case 8:
|
||||
case 10:
|
||||
|
||||
{ zconf_error("unexpected end statement"); ;}
|
||||
break;
|
||||
|
||||
case 9:
|
||||
case 11:
|
||||
|
||||
{ zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); ;}
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case 12:
|
||||
|
||||
{
|
||||
zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
|
||||
;}
|
||||
break;
|
||||
|
||||
case 11:
|
||||
case 13:
|
||||
|
||||
{ zconf_error("invalid statement"); ;}
|
||||
break;
|
||||
|
||||
case 25:
|
||||
case 27:
|
||||
|
||||
{ zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); ;}
|
||||
break;
|
||||
|
||||
case 26:
|
||||
case 28:
|
||||
|
||||
{ zconf_error("invalid option"); ;}
|
||||
break;
|
||||
|
||||
case 27:
|
||||
case 29:
|
||||
|
||||
{
|
||||
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
|
||||
@@ -1656,7 +1664,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 28:
|
||||
case 30:
|
||||
|
||||
{
|
||||
menu_end_entry();
|
||||
@@ -1664,7 +1672,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 29:
|
||||
case 31:
|
||||
|
||||
{
|
||||
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
|
||||
@@ -1674,7 +1682,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 30:
|
||||
case 32:
|
||||
|
||||
{
|
||||
if (current_entry->prompt)
|
||||
@@ -1686,7 +1694,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 38:
|
||||
case 40:
|
||||
|
||||
{
|
||||
menu_set_type((yyvsp[(1) - (3)].id)->stype);
|
||||
@@ -1696,7 +1704,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 39:
|
||||
case 41:
|
||||
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
|
||||
@@ -1704,7 +1712,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 40:
|
||||
case 42:
|
||||
|
||||
{
|
||||
menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
|
||||
@@ -1716,7 +1724,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 41:
|
||||
case 43:
|
||||
|
||||
{
|
||||
menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
|
||||
@@ -1724,7 +1732,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 42:
|
||||
case 44:
|
||||
|
||||
{
|
||||
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
|
||||
@@ -1732,7 +1740,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 45:
|
||||
case 47:
|
||||
|
||||
{
|
||||
struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
|
||||
@@ -1744,17 +1752,17 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 46:
|
||||
case 48:
|
||||
|
||||
{ (yyval.string) = NULL; ;}
|
||||
break;
|
||||
|
||||
case 47:
|
||||
case 49:
|
||||
|
||||
{ (yyval.string) = (yyvsp[(2) - (2)].string); ;}
|
||||
break;
|
||||
|
||||
case 48:
|
||||
case 50:
|
||||
|
||||
{
|
||||
struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
|
||||
@@ -1765,14 +1773,14 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 49:
|
||||
case 51:
|
||||
|
||||
{
|
||||
(yyval.menu) = menu_add_menu();
|
||||
;}
|
||||
break;
|
||||
|
||||
case 50:
|
||||
case 52:
|
||||
|
||||
{
|
||||
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
|
||||
@@ -1782,7 +1790,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 58:
|
||||
case 60:
|
||||
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
|
||||
@@ -1790,7 +1798,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 59:
|
||||
case 61:
|
||||
|
||||
{
|
||||
if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
|
||||
@@ -1803,7 +1811,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 60:
|
||||
case 62:
|
||||
|
||||
{
|
||||
current_entry->sym->flags |= SYMBOL_OPTIONAL;
|
||||
@@ -1811,7 +1819,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 61:
|
||||
case 63:
|
||||
|
||||
{
|
||||
if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
|
||||
@@ -1823,7 +1831,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 64:
|
||||
case 66:
|
||||
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
|
||||
@@ -1833,7 +1841,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 65:
|
||||
case 67:
|
||||
|
||||
{
|
||||
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
|
||||
@@ -1843,7 +1851,14 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 71:
|
||||
case 73:
|
||||
|
||||
{
|
||||
menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
|
||||
;}
|
||||
break;
|
||||
|
||||
case 74:
|
||||
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
@@ -1852,14 +1867,14 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 72:
|
||||
case 75:
|
||||
|
||||
{
|
||||
(yyval.menu) = menu_add_menu();
|
||||
;}
|
||||
break;
|
||||
|
||||
case 73:
|
||||
case 76:
|
||||
|
||||
{
|
||||
if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
|
||||
@@ -1869,7 +1884,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 79:
|
||||
case 82:
|
||||
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
|
||||
@@ -1877,7 +1892,7 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 80:
|
||||
case 83:
|
||||
|
||||
{
|
||||
menu_add_entry(NULL);
|
||||
@@ -1886,14 +1901,14 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 81:
|
||||
case 84:
|
||||
|
||||
{
|
||||
menu_end_entry();
|
||||
;}
|
||||
break;
|
||||
|
||||
case 82:
|
||||
case 85:
|
||||
|
||||
{
|
||||
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
|
||||
@@ -1901,14 +1916,14 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 83:
|
||||
case 86:
|
||||
|
||||
{
|
||||
current_entry->help = (yyvsp[(2) - (2)].string);
|
||||
;}
|
||||
break;
|
||||
|
||||
case 88:
|
||||
case 91:
|
||||
|
||||
{
|
||||
menu_add_dep((yyvsp[(3) - (4)].expr));
|
||||
@@ -1916,85 +1931,85 @@ yyreduce:
|
||||
;}
|
||||
break;
|
||||
|
||||
case 90:
|
||||
case 93:
|
||||
|
||||
{
|
||||
menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
|
||||
;}
|
||||
break;
|
||||
|
||||
case 93:
|
||||
case 96:
|
||||
|
||||
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
|
||||
break;
|
||||
|
||||
case 94:
|
||||
|
||||
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
|
||||
break;
|
||||
|
||||
case 95:
|
||||
case 97:
|
||||
|
||||
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
|
||||
break;
|
||||
|
||||
case 98:
|
||||
|
||||
{ (yyval.expr) = NULL; ;}
|
||||
break;
|
||||
|
||||
case 99:
|
||||
|
||||
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
|
||||
break;
|
||||
|
||||
case 100:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
|
||||
{ (yyval.id) = (yyvsp[(1) - (2)].id); ;}
|
||||
break;
|
||||
|
||||
case 101:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
|
||||
{ (yyval.expr) = NULL; ;}
|
||||
break;
|
||||
|
||||
case 102:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
|
||||
{ (yyval.expr) = (yyvsp[(2) - (2)].expr); ;}
|
||||
break;
|
||||
|
||||
case 103:
|
||||
|
||||
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
|
||||
{ (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); ;}
|
||||
break;
|
||||
|
||||
case 104:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
|
||||
{ (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
|
||||
break;
|
||||
|
||||
case 105:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
|
||||
{ (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); ;}
|
||||
break;
|
||||
|
||||
case 106:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
|
||||
{ (yyval.expr) = (yyvsp[(2) - (3)].expr); ;}
|
||||
break;
|
||||
|
||||
case 107:
|
||||
|
||||
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
|
||||
{ (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); ;}
|
||||
break;
|
||||
|
||||
case 108:
|
||||
|
||||
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
|
||||
{ (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
|
||||
break;
|
||||
|
||||
case 109:
|
||||
|
||||
{ (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); ;}
|
||||
break;
|
||||
|
||||
case 110:
|
||||
|
||||
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); ;}
|
||||
break;
|
||||
|
||||
case 111:
|
||||
|
||||
{ (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;}
|
||||
break;
|
||||
|
||||
case 112:
|
||||
|
||||
{ (yyval.string) = NULL; ;}
|
||||
break;
|
||||
|
||||
@@ -2239,6 +2254,10 @@ void conf_parse(const char *name)
|
||||
prop = prop_alloc(P_DEFAULT, modules_sym);
|
||||
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
|
||||
}
|
||||
|
||||
rootmenu.prompt->text = _(rootmenu.prompt->text);
|
||||
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
||||
|
||||
menu_finalize(&rootmenu);
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_check_deps(sym))
|
||||
|
@@ -36,7 +36,7 @@ static struct menu *current_menu, *current_entry;
|
||||
#define YYERROR_VERBOSE
|
||||
#endif
|
||||
%}
|
||||
%expect 26
|
||||
%expect 28
|
||||
|
||||
%union
|
||||
{
|
||||
@@ -104,14 +104,15 @@ static struct menu *current_menu, *current_entry;
|
||||
%}
|
||||
|
||||
%%
|
||||
input: stmt_list;
|
||||
input: nl start | start;
|
||||
|
||||
start: mainmenu_stmt stmt_list | stmt_list;
|
||||
|
||||
stmt_list:
|
||||
/* empty */
|
||||
| stmt_list common_stmt
|
||||
| stmt_list choice_stmt
|
||||
| stmt_list menu_stmt
|
||||
| stmt_list T_MAINMENU prompt nl
|
||||
| stmt_list end { zconf_error("unexpected end statement"); }
|
||||
| stmt_list T_WORD error T_EOL { zconf_error("unknown statement \"%s\"", $2); }
|
||||
| stmt_list option_name error T_EOL
|
||||
@@ -342,6 +343,13 @@ if_block:
|
||||
| if_block choice_stmt
|
||||
;
|
||||
|
||||
/* mainmenu entry */
|
||||
|
||||
mainmenu_stmt: T_MAINMENU prompt nl
|
||||
{
|
||||
menu_add_prompt(P_MENU, $2, NULL);
|
||||
};
|
||||
|
||||
/* menu entry */
|
||||
|
||||
menu: T_MENU prompt T_EOL
|
||||
@@ -494,6 +502,10 @@ void conf_parse(const char *name)
|
||||
prop = prop_alloc(P_DEFAULT, modules_sym);
|
||||
prop->expr = expr_alloc_symbol(sym_lookup("MODULES", 0));
|
||||
}
|
||||
|
||||
rootmenu.prompt->text = _(rootmenu.prompt->text);
|
||||
rootmenu.prompt->text = sym_expand_string_value(rootmenu.prompt->text);
|
||||
|
||||
menu_finalize(&rootmenu);
|
||||
for_all_symbols(i, sym) {
|
||||
if (sym_check_deps(sym))
|
||||
|
@@ -44,12 +44,13 @@ use strict;
|
||||
# Note: This only supports 'c'.
|
||||
|
||||
# usage:
|
||||
# kernel-doc [ -docbook | -html | -text | -man ] [ -no-doc-sections ]
|
||||
# kernel-doc [ -docbook | -html | -text | -man | -list ] [ -no-doc-sections ]
|
||||
# [ -function funcname [ -function funcname ...] ] c file(s)s > outputfile
|
||||
# or
|
||||
# [ -nofunction funcname [ -function funcname ...] ] c file(s)s > outputfile
|
||||
#
|
||||
# Set output format using one of -docbook -html -text or -man. Default is man.
|
||||
# The -list format is for internal use by docproc.
|
||||
#
|
||||
# -no-doc-sections
|
||||
# Do not output DOC: sections
|
||||
@@ -210,9 +211,16 @@ my %highlights_text = ( $type_constant, "\$1",
|
||||
$type_param, "\$1" );
|
||||
my $blankline_text = "";
|
||||
|
||||
# list mode
|
||||
my %highlights_list = ( $type_constant, "\$1",
|
||||
$type_func, "\$1",
|
||||
$type_struct, "\$1",
|
||||
$type_param, "\$1" );
|
||||
my $blankline_list = "";
|
||||
|
||||
sub usage {
|
||||
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man ] [ -no-doc-sections ]\n";
|
||||
print "Usage: $0 [ -v ] [ -docbook | -html | -text | -man | -list ]\n";
|
||||
print " [ -no-doc-sections ]\n";
|
||||
print " [ -function funcname [ -function funcname ...] ]\n";
|
||||
print " [ -nofunction funcname [ -nofunction funcname ...] ]\n";
|
||||
print " c source file(s) > outputfile\n";
|
||||
@@ -318,6 +326,10 @@ while ($ARGV[0] =~ m/^-(.*)/) {
|
||||
$output_mode = "xml";
|
||||
%highlights = %highlights_xml;
|
||||
$blankline = $blankline_xml;
|
||||
} elsif ($cmd eq "-list") {
|
||||
$output_mode = "list";
|
||||
%highlights = %highlights_list;
|
||||
$blankline = $blankline_list;
|
||||
} elsif ($cmd eq "-gnome") {
|
||||
$output_mode = "gnome";
|
||||
%highlights = %highlights_gnome;
|
||||
@@ -1361,6 +1373,42 @@ sub output_blockhead_text(%) {
|
||||
}
|
||||
}
|
||||
|
||||
## list mode output functions
|
||||
|
||||
sub output_function_list(%) {
|
||||
my %args = %{$_[0]};
|
||||
|
||||
print $args{'function'} . "\n";
|
||||
}
|
||||
|
||||
# output enum in list
|
||||
sub output_enum_list(%) {
|
||||
my %args = %{$_[0]};
|
||||
print $args{'enum'} . "\n";
|
||||
}
|
||||
|
||||
# output typedef in list
|
||||
sub output_typedef_list(%) {
|
||||
my %args = %{$_[0]};
|
||||
print $args{'typedef'} . "\n";
|
||||
}
|
||||
|
||||
# output struct as list
|
||||
sub output_struct_list(%) {
|
||||
my %args = %{$_[0]};
|
||||
|
||||
print $args{'struct'} . "\n";
|
||||
}
|
||||
|
||||
sub output_blockhead_list(%) {
|
||||
my %args = %{$_[0]};
|
||||
my ($parameter, $section);
|
||||
|
||||
foreach $section (@{$args{'sectionlist'}}) {
|
||||
print "DOC: $section\n";
|
||||
}
|
||||
}
|
||||
|
||||
##
|
||||
# generic output function for all types (function, struct/union, typedef, enum);
|
||||
# calls the generated, variable output_ function name based on
|
||||
@@ -1454,6 +1502,8 @@ sub dump_enum($$) {
|
||||
my $file = shift;
|
||||
|
||||
$x =~ s@/\*.*?\*/@@gos; # strip comments.
|
||||
$x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums
|
||||
|
||||
if ($x =~ /enum\s+(\w+)\s*{(.*)}/) {
|
||||
$declaration_name = $1;
|
||||
my $members = $2;
|
||||
@@ -1677,7 +1727,7 @@ sub check_sections($$$$$$) {
|
||||
foreach $px (0 .. $#prms) {
|
||||
$prm_clean = $prms[$px];
|
||||
$prm_clean =~ s/\[.*\]//;
|
||||
$prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//;
|
||||
$prm_clean =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i;
|
||||
# ignore array size in a parameter string;
|
||||
# however, the original param string may contain
|
||||
# spaces, e.g.: addr[6 + 2]
|
||||
|
@@ -44,7 +44,9 @@ all:
|
||||
|
||||
Makefile:;
|
||||
|
||||
\$(all) %/: all
|
||||
\$(all): all
|
||||
@:
|
||||
|
||||
%/: all
|
||||
@:
|
||||
EOF
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include "modpost.h"
|
||||
#include "../../include/generated/autoconf.h"
|
||||
#include "../../include/linux/license.h"
|
||||
@@ -789,6 +790,7 @@ static const char *section_white_list[] =
|
||||
{
|
||||
".comment*",
|
||||
".debug*",
|
||||
".GCC-command-line", /* mn10300 */
|
||||
".mdebug*", /* alpha, score, mips etc. */
|
||||
".pdr", /* alpha, score, mips etc. */
|
||||
".stab*",
|
||||
@@ -1033,6 +1035,13 @@ static const struct sectioncheck *section_mismatch(
|
||||
* fromsec = .data*
|
||||
* atsym =__param*
|
||||
*
|
||||
* Pattern 1a:
|
||||
* module_param_call() ops can refer to __init set function if permissions=0
|
||||
* The pattern is identified by:
|
||||
* tosec = .init.text
|
||||
* fromsec = .data*
|
||||
* atsym = __param_ops_*
|
||||
*
|
||||
* Pattern 2:
|
||||
* Many drivers utilise a *driver container with references to
|
||||
* add, remove, probe functions etc.
|
||||
@@ -1067,6 +1076,12 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
|
||||
(strncmp(fromsym, "__param", strlen("__param")) == 0))
|
||||
return 0;
|
||||
|
||||
/* Check for pattern 1a */
|
||||
if (strcmp(tosec, ".init.text") == 0 &&
|
||||
match(fromsec, data_sections) &&
|
||||
(strncmp(fromsym, "__param_ops_", strlen("__param_ops_")) == 0))
|
||||
return 0;
|
||||
|
||||
/* Check for pattern 2 */
|
||||
if (match(tosec, init_exit_sections) &&
|
||||
match(fromsec, data_sections) &&
|
||||
@@ -1220,7 +1235,7 @@ static char *sec2annotation(const char *s)
|
||||
strcat(p, " ");
|
||||
return r;
|
||||
} else {
|
||||
return "";
|
||||
return strdup("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1248,6 +1263,8 @@ static void report_sec_mismatch(const char *modname,
|
||||
{
|
||||
const char *from, *from_p;
|
||||
const char *to, *to_p;
|
||||
char *prl_from;
|
||||
char *prl_to;
|
||||
|
||||
switch (from_is_func) {
|
||||
case 0: from = "variable"; from_p = ""; break;
|
||||
@@ -1271,16 +1288,21 @@ static void report_sec_mismatch(const char *modname,
|
||||
|
||||
switch (mismatch->mismatch) {
|
||||
case TEXT_TO_ANY_INIT:
|
||||
prl_from = sec2annotation(fromsec);
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The function %s%s() references\n"
|
||||
"the %s %s%s%s.\n"
|
||||
"This is often because %s lacks a %s\n"
|
||||
"annotation or the annotation of %s is wrong.\n",
|
||||
sec2annotation(fromsec), fromsym,
|
||||
to, sec2annotation(tosec), tosym, to_p,
|
||||
fromsym, sec2annotation(tosec), tosym);
|
||||
prl_from, fromsym,
|
||||
to, prl_to, tosym, to_p,
|
||||
fromsym, prl_to, tosym);
|
||||
free(prl_from);
|
||||
free(prl_to);
|
||||
break;
|
||||
case DATA_TO_ANY_INIT: {
|
||||
prl_to = sec2annotation(tosec);
|
||||
const char *const *s = mismatch->symbol_white_list;
|
||||
fprintf(stderr,
|
||||
"The variable %s references\n"
|
||||
@@ -1288,20 +1310,24 @@ static void report_sec_mismatch(const char *modname,
|
||||
"If the reference is valid then annotate the\n"
|
||||
"variable with __init* or __refdata (see linux/init.h) "
|
||||
"or name the variable:\n",
|
||||
fromsym, to, sec2annotation(tosec), tosym, to_p);
|
||||
fromsym, to, prl_to, tosym, to_p);
|
||||
while (*s)
|
||||
fprintf(stderr, "%s, ", *s++);
|
||||
fprintf(stderr, "\n");
|
||||
free(prl_to);
|
||||
break;
|
||||
}
|
||||
case TEXT_TO_ANY_EXIT:
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The function %s() references a %s in an exit section.\n"
|
||||
"Often the %s %s%s has valid usage outside the exit section\n"
|
||||
"and the fix is to remove the %sannotation of %s.\n",
|
||||
fromsym, to, to, tosym, to_p, sec2annotation(tosec), tosym);
|
||||
fromsym, to, to, tosym, to_p, prl_to, tosym);
|
||||
free(prl_to);
|
||||
break;
|
||||
case DATA_TO_ANY_EXIT: {
|
||||
prl_to = sec2annotation(tosec);
|
||||
const char *const *s = mismatch->symbol_white_list;
|
||||
fprintf(stderr,
|
||||
"The variable %s references\n"
|
||||
@@ -1309,24 +1335,31 @@ static void report_sec_mismatch(const char *modname,
|
||||
"If the reference is valid then annotate the\n"
|
||||
"variable with __exit* (see linux/init.h) or "
|
||||
"name the variable:\n",
|
||||
fromsym, to, sec2annotation(tosec), tosym, to_p);
|
||||
fromsym, to, prl_to, tosym, to_p);
|
||||
while (*s)
|
||||
fprintf(stderr, "%s, ", *s++);
|
||||
fprintf(stderr, "\n");
|
||||
free(prl_to);
|
||||
break;
|
||||
}
|
||||
case XXXINIT_TO_SOME_INIT:
|
||||
case XXXEXIT_TO_SOME_EXIT:
|
||||
prl_from = sec2annotation(fromsec);
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The %s %s%s%s references\n"
|
||||
"a %s %s%s%s.\n"
|
||||
"If %s is only used by %s then\n"
|
||||
"annotate %s with a matching annotation.\n",
|
||||
from, sec2annotation(fromsec), fromsym, from_p,
|
||||
to, sec2annotation(tosec), tosym, to_p,
|
||||
from, prl_from, fromsym, from_p,
|
||||
to, prl_to, tosym, to_p,
|
||||
tosym, fromsym, tosym);
|
||||
free(prl_from);
|
||||
free(prl_to);
|
||||
break;
|
||||
case ANY_INIT_TO_ANY_EXIT:
|
||||
prl_from = sec2annotation(fromsec);
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The %s %s%s%s references\n"
|
||||
"a %s %s%s%s.\n"
|
||||
@@ -1335,11 +1368,15 @@ static void report_sec_mismatch(const char *modname,
|
||||
"uses functionality in the exit path.\n"
|
||||
"The fix is often to remove the %sannotation of\n"
|
||||
"%s%s so it may be used outside an exit section.\n",
|
||||
from, sec2annotation(fromsec), fromsym, from_p,
|
||||
to, sec2annotation(tosec), tosym, to_p,
|
||||
sec2annotation(tosec), tosym, to_p);
|
||||
from, prl_from, fromsym, from_p,
|
||||
to, prl_to, tosym, to_p,
|
||||
prl_to, tosym, to_p);
|
||||
free(prl_from);
|
||||
free(prl_to);
|
||||
break;
|
||||
case ANY_EXIT_TO_ANY_INIT:
|
||||
prl_from = sec2annotation(fromsec);
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The %s %s%s%s references\n"
|
||||
"a %s %s%s%s.\n"
|
||||
@@ -1348,16 +1385,20 @@ static void report_sec_mismatch(const char *modname,
|
||||
"uses functionality in the init path.\n"
|
||||
"The fix is often to remove the %sannotation of\n"
|
||||
"%s%s so it may be used outside an init section.\n",
|
||||
from, sec2annotation(fromsec), fromsym, from_p,
|
||||
to, sec2annotation(tosec), tosym, to_p,
|
||||
sec2annotation(tosec), tosym, to_p);
|
||||
from, prl_from, fromsym, from_p,
|
||||
to, prl_to, tosym, to_p,
|
||||
prl_to, tosym, to_p);
|
||||
free(prl_from);
|
||||
free(prl_to);
|
||||
break;
|
||||
case EXPORT_TO_INIT_EXIT:
|
||||
prl_to = sec2annotation(tosec);
|
||||
fprintf(stderr,
|
||||
"The symbol %s is exported and annotated %s\n"
|
||||
"Fix this by removing the %sannotation of %s "
|
||||
"or drop the export.\n",
|
||||
tosym, sec2annotation(tosec), sec2annotation(tosec), tosym);
|
||||
tosym, prl_to, prl_to, tosym);
|
||||
free(prl_to);
|
||||
break;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
@@ -84,6 +84,64 @@ my %ksymtab = (); # names that appear in __ksymtab_
|
||||
my %ref = (); # $ref{$name} exists if there is a true external reference to $name
|
||||
my %export = (); # $export{$name} exists if there is an EXPORT_... of $name
|
||||
|
||||
my %nmexception = (
|
||||
'fs/ext3/bitmap' => 1,
|
||||
'fs/ext4/bitmap' => 1,
|
||||
'arch/x86/lib/thunk_32' => 1,
|
||||
'arch/x86/lib/cmpxchg' => 1,
|
||||
'arch/x86/vdso/vdso32/note' => 1,
|
||||
'lib/irq_regs' => 1,
|
||||
'usr/initramfs_data' => 1,
|
||||
'drivers/scsi/aic94xx/aic94xx_dump' => 1,
|
||||
'drivers/scsi/libsas/sas_dump' => 1,
|
||||
'lib/dec_and_lock' => 1,
|
||||
'drivers/ide/ide-probe-mini' => 1,
|
||||
'usr/initramfs_data' => 1,
|
||||
'drivers/acpi/acpia/exdump' => 1,
|
||||
'drivers/acpi/acpia/rsdump' => 1,
|
||||
'drivers/acpi/acpia/nsdumpdv' => 1,
|
||||
'drivers/acpi/acpia/nsdump' => 1,
|
||||
'arch/ia64/sn/kernel/sn2/io' => 1,
|
||||
'arch/ia64/kernel/gate-data' => 1,
|
||||
'security/capability' => 1,
|
||||
'fs/ntfs/sysctl' => 1,
|
||||
'fs/jfs/jfs_debug' => 1,
|
||||
);
|
||||
|
||||
my %nameexception = (
|
||||
'mod_use_count_' => 1,
|
||||
'__initramfs_end' => 1,
|
||||
'__initramfs_start' => 1,
|
||||
'_einittext' => 1,
|
||||
'_sinittext' => 1,
|
||||
'kallsyms_names' => 1,
|
||||
'kallsyms_num_syms' => 1,
|
||||
'kallsyms_addresses'=> 1,
|
||||
'__this_module' => 1,
|
||||
'_etext' => 1,
|
||||
'_edata' => 1,
|
||||
'_end' => 1,
|
||||
'__bss_start' => 1,
|
||||
'_text' => 1,
|
||||
'_stext' => 1,
|
||||
'__gp' => 1,
|
||||
'ia64_unw_start' => 1,
|
||||
'ia64_unw_end' => 1,
|
||||
'__init_begin' => 1,
|
||||
'__init_end' => 1,
|
||||
'__bss_stop' => 1,
|
||||
'__nosave_begin' => 1,
|
||||
'__nosave_end' => 1,
|
||||
'pg0' => 1,
|
||||
'vdso_enabled' => 1,
|
||||
'__stack_chk_fail' => 1,
|
||||
'VDSO32_PRELINK' => 1,
|
||||
'VDSO32_vsyscall' => 1,
|
||||
'VDSO32_rt_sigreturn'=>1,
|
||||
'VDSO32_sigreturn' => 1,
|
||||
);
|
||||
|
||||
|
||||
&find(\&linux_objects, '.'); # find the objects and do_nm on them
|
||||
&list_multiply_defined();
|
||||
&resolve_external_references();
|
||||
@@ -105,7 +163,8 @@ sub linux_objects
|
||||
if (/.*\.o$/ &&
|
||||
! (
|
||||
m:/built-in.o$:
|
||||
|| m:arch/x86/kernel/vsyscall-syms.o$:
|
||||
|| m:arch/x86/vdso/:
|
||||
|| m:arch/x86/boot/:
|
||||
|| m:arch/ia64/ia32/ia32.o$:
|
||||
|| m:arch/ia64/kernel/gate-syms.o$:
|
||||
|| m:arch/ia64/lib/__divdi3.o$:
|
||||
@@ -148,6 +207,7 @@ sub linux_objects
|
||||
|| m:^.*/\.tmp_:
|
||||
|| m:^\.tmp_:
|
||||
|| m:/vmlinux-obj.o$:
|
||||
|| m:^tools/:
|
||||
)
|
||||
) {
|
||||
do_nm($basename, $_);
|
||||
@@ -167,11 +227,11 @@ sub do_nm
|
||||
printf STDERR "$fullname is not an object file\n";
|
||||
return;
|
||||
}
|
||||
($source = $fullname) =~ s/\.o$//;
|
||||
if (-e "$objtree$source.c" || -e "$objtree$source.S") {
|
||||
$source = "$objtree$source";
|
||||
($source = $basename) =~ s/\.o$//;
|
||||
if (-e "$source.c" || -e "$source.S") {
|
||||
$source = "$objtree$File::Find::dir/$source";
|
||||
} else {
|
||||
$source = "$srctree$source";
|
||||
$source = "$srctree$File::Find::dir/$source";
|
||||
}
|
||||
if (! -e "$source.c" && ! -e "$source.S") {
|
||||
# No obvious source, exclude the object if it is conglomerate
|
||||
@@ -214,6 +274,7 @@ sub do_nm
|
||||
# T global label/procedure
|
||||
# U external reference
|
||||
# W weak external reference to text that has been resolved
|
||||
# V similar to W, but the value of the weak symbol becomes zero with no error.
|
||||
# a assembler equate
|
||||
# b static variable, uninitialised
|
||||
# d static variable, initialised
|
||||
@@ -222,8 +283,9 @@ sub do_nm
|
||||
# s static variable, uninitialised, small bss
|
||||
# t static label/procedures
|
||||
# w weak external reference to text that has not been resolved
|
||||
# v similar to w
|
||||
# ? undefined type, used a lot by modules
|
||||
if ($type !~ /^[ABCDGRSTUWabdgrstw?]$/) {
|
||||
if ($type !~ /^[ABCDGRSTUWVabdgrstwv?]$/) {
|
||||
printf STDERR "nm output for $fullname contains unknown type '$_'\n";
|
||||
}
|
||||
elsif ($name =~ /\./) {
|
||||
@@ -234,7 +296,7 @@ sub do_nm
|
||||
# binutils keeps changing the type for exported symbols, force it to R
|
||||
$type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/);
|
||||
$name =~ s/_R[a-f0-9]{8}$//; # module versions adds this
|
||||
if ($type =~ /[ABCDGRSTW]/ &&
|
||||
if ($type =~ /[ABCDGRSTWV]/ &&
|
||||
$name ne 'init_module' &&
|
||||
$name ne 'cleanup_module' &&
|
||||
$name ne 'Using_Versions' &&
|
||||
@@ -270,27 +332,9 @@ sub do_nm
|
||||
close($nmdata);
|
||||
|
||||
if ($#nmdata < 0) {
|
||||
if (
|
||||
$fullname ne "lib/brlock.o"
|
||||
&& $fullname ne "lib/dec_and_lock.o"
|
||||
&& $fullname ne "fs/xfs/xfs_macros.o"
|
||||
&& $fullname ne "drivers/ide/ide-probe-mini.o"
|
||||
&& $fullname ne "usr/initramfs_data.o"
|
||||
&& $fullname ne "drivers/acpi/executer/exdump.o"
|
||||
&& $fullname ne "drivers/acpi/resources/rsdump.o"
|
||||
&& $fullname ne "drivers/acpi/namespace/nsdumpdv.o"
|
||||
&& $fullname ne "drivers/acpi/namespace/nsdump.o"
|
||||
&& $fullname ne "arch/ia64/sn/kernel/sn2/io.o"
|
||||
&& $fullname ne "arch/ia64/kernel/gate-data.o"
|
||||
&& $fullname ne "drivers/ieee1394/oui.o"
|
||||
&& $fullname ne "security/capability.o"
|
||||
&& $fullname ne "sound/core/wrappers.o"
|
||||
&& $fullname ne "fs/ntfs/sysctl.o"
|
||||
&& $fullname ne "fs/jfs/jfs_debug.o"
|
||||
) {
|
||||
printf "No nm data for $fullname\n";
|
||||
}
|
||||
return;
|
||||
printf "No nm data for $fullname\n"
|
||||
unless $nmexception{$fullname};
|
||||
return;
|
||||
}
|
||||
$nmdata{$fullname} = \@nmdata;
|
||||
}
|
||||
@@ -319,18 +363,14 @@ sub list_multiply_defined
|
||||
foreach my $name (keys(%def)) {
|
||||
if ($#{$def{$name}} > 0) {
|
||||
# Special case for cond_syscall
|
||||
if ($#{$def{$name}} == 1 && $name =~ /^sys_/ &&
|
||||
($def{$name}[0] eq "kernel/sys.o" ||
|
||||
$def{$name}[1] eq "kernel/sys.o")) {
|
||||
&drop_def("kernel/sys.o", $name);
|
||||
next;
|
||||
}
|
||||
# Special case for i386 entry code
|
||||
if ($#{$def{$name}} == 1 && $name =~ /^__kernel_/ &&
|
||||
$def{$name}[0] eq "arch/x86/kernel/vsyscall-int80_32.o" &&
|
||||
$def{$name}[1] eq "arch/x86/kernel/vsyscall-sysenter_32.o") {
|
||||
&drop_def("arch/x86/kernel/vsyscall-sysenter_32.o", $name);
|
||||
next;
|
||||
if ($#{$def{$name}} == 1 &&
|
||||
($name =~ /^sys_/ || $name =~ /^compat_sys_/ ||
|
||||
$name =~ /^sys32_/)) {
|
||||
if($def{$name}[0] eq "kernel/sys_ni.o" ||
|
||||
$def{$name}[1] eq "kernel/sys_ni.o") {
|
||||
&drop_def("kernel/sys_ni.o", $name);
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
printf "$name is multiply defined in :-\n";
|
||||
@@ -372,31 +412,7 @@ sub resolve_external_references
|
||||
$ref{$name} = ""
|
||||
}
|
||||
}
|
||||
elsif ( $name ne "mod_use_count_"
|
||||
&& $name ne "__initramfs_end"
|
||||
&& $name ne "__initramfs_start"
|
||||
&& $name ne "_einittext"
|
||||
&& $name ne "_sinittext"
|
||||
&& $name ne "kallsyms_names"
|
||||
&& $name ne "kallsyms_num_syms"
|
||||
&& $name ne "kallsyms_addresses"
|
||||
&& $name ne "__this_module"
|
||||
&& $name ne "_etext"
|
||||
&& $name ne "_edata"
|
||||
&& $name ne "_end"
|
||||
&& $name ne "__bss_start"
|
||||
&& $name ne "_text"
|
||||
&& $name ne "_stext"
|
||||
&& $name ne "__gp"
|
||||
&& $name ne "ia64_unw_start"
|
||||
&& $name ne "ia64_unw_end"
|
||||
&& $name ne "__init_begin"
|
||||
&& $name ne "__init_end"
|
||||
&& $name ne "__bss_stop"
|
||||
&& $name ne "__nosave_begin"
|
||||
&& $name ne "__nosave_end"
|
||||
&& $name ne "pg0"
|
||||
&& $name ne "__module_text_address"
|
||||
elsif ( ! $nameexception{$name}
|
||||
&& $name !~ /^__sched_text_/
|
||||
&& $name !~ /^__start_/
|
||||
&& $name !~ /^__end_/
|
||||
@@ -407,7 +423,6 @@ sub resolve_external_references
|
||||
&& $name !~ /^__.*per_cpu_end/
|
||||
&& $name !~ /^__alt_instructions/
|
||||
&& $name !~ /^__setup_/
|
||||
&& $name !~ /^jiffies/
|
||||
&& $name !~ /^__mod_timer/
|
||||
&& $name !~ /^__mod_page_state/
|
||||
&& $name !~ /^init_module/
|
||||
|
@@ -111,13 +111,38 @@ tar%pkg: FORCE
|
||||
clean-dirs += $(objtree)/tar-install/
|
||||
|
||||
|
||||
# perf-pkg - generate a source tarball with perf source
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
perf-tar=perf-$(KERNELVERSION)
|
||||
|
||||
quiet_cmd_perf_tar = TAR
|
||||
cmd_perf_tar = \
|
||||
git archive --prefix=$(perf-tar)/ HEAD^{tree} \
|
||||
$$(cat $(srctree)/tools/perf/MANIFEST) -o $(perf-tar).tar; \
|
||||
mkdir -p $(perf-tar); \
|
||||
git rev-parse HEAD > $(perf-tar)/HEAD; \
|
||||
tar rf $(perf-tar).tar $(perf-tar)/HEAD; \
|
||||
rm -r $(perf-tar); \
|
||||
$(if $(findstring tar-src,$@),, \
|
||||
$(if $(findstring bz2,$@),bzip2, \
|
||||
$(if $(findstring gz,$@),gzip, \
|
||||
$(error unknown target $@))) \
|
||||
-f -9 $(perf-tar).tar)
|
||||
|
||||
perf-%pkg: FORCE
|
||||
$(call cmd,perf_tar)
|
||||
|
||||
# Help text displayed when executing 'make help'
|
||||
# ---------------------------------------------------------------------------
|
||||
help: FORCE
|
||||
@echo ' rpm-pkg - Build both source and binary RPM kernel packages'
|
||||
@echo ' binrpm-pkg - Build only the binary kernel package'
|
||||
@echo ' deb-pkg - Build the kernel as an deb package'
|
||||
@echo ' tar-pkg - Build the kernel as an uncompressed tarball'
|
||||
@echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
|
||||
@echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
|
||||
@echo ' rpm-pkg - Build both source and binary RPM kernel packages'
|
||||
@echo ' binrpm-pkg - Build only the binary kernel package'
|
||||
@echo ' deb-pkg - Build the kernel as an deb package'
|
||||
@echo ' tar-pkg - Build the kernel as an uncompressed tarball'
|
||||
@echo ' targz-pkg - Build the kernel as a gzip compressed tarball'
|
||||
@echo ' tarbz2-pkg - Build the kernel as a bzip2 compressed tarball'
|
||||
@echo ' perf-tar-src-pkg - Build $(perf-tar).tar source tarball'
|
||||
@echo ' perf-targz-src-pkg - Build $(perf-tar).tar.gz source tarball'
|
||||
@echo ' perf-tarbz2-src-pkg - Build $(perf-tar).tar.bz2 source tarball'
|
||||
|
||||
|
@@ -66,7 +66,9 @@ else
|
||||
cp System.map "$tmpdir/boot/System.map-$version"
|
||||
cp .config "$tmpdir/boot/config-$version"
|
||||
# Not all arches include the boot path in KBUILD_IMAGE
|
||||
if ! cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"; then
|
||||
if [ -e $KBUILD_IMAGE ]; then
|
||||
cp $KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
|
||||
else
|
||||
cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/boot/vmlinuz-$version"
|
||||
fi
|
||||
fi
|
||||
@@ -148,10 +150,11 @@ EOF
|
||||
# Generate a control file
|
||||
cat <<EOF > debian/control
|
||||
Source: linux-upstream
|
||||
Section: admin
|
||||
Section: kernel
|
||||
Priority: optional
|
||||
Maintainer: $maintainer
|
||||
Standards-Version: 3.8.1
|
||||
Standards-Version: 3.8.4
|
||||
Homepage: http://www.kernel.org/
|
||||
EOF
|
||||
|
||||
if [ "$ARCH" = "um" ]; then
|
||||
|
@@ -70,7 +70,7 @@ echo 'mkdir -p $RPM_BUILD_ROOT/boot $RPM_BUILD_ROOT/lib/modules'
|
||||
echo 'mkdir -p $RPM_BUILD_ROOT/lib/firmware'
|
||||
echo "%endif"
|
||||
|
||||
echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{_smp_mflags} KBUILD_SRC= modules_install'
|
||||
echo 'INSTALL_MOD_PATH=$RPM_BUILD_ROOT make %{?_smp_mflags} KBUILD_SRC= modules_install'
|
||||
echo "%ifarch ia64"
|
||||
echo 'cp $KBUILD_IMAGE $RPM_BUILD_ROOT'"/boot/efi/vmlinuz-$KERNELRELEASE"
|
||||
echo 'ln -s '"efi/vmlinuz-$KERNELRELEASE" '$RPM_BUILD_ROOT'"/boot/"
|
||||
|
407
scripts/recordmcount.c
Normal file
407
scripts/recordmcount.c
Normal file
@@ -0,0 +1,407 @@
|
||||
/*
|
||||
* recordmcount.c: construct a table of the locations of calls to 'mcount'
|
||||
* so that ftrace can find them quickly.
|
||||
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
|
||||
* Licensed under the GNU General Public License, version 2 (GPLv2).
|
||||
*
|
||||
* Restructured to fit Linux format, as well as other updates:
|
||||
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Strategy: alter the .o file in-place.
|
||||
*
|
||||
* Append a new STRTAB that has the new section names, followed by a new array
|
||||
* ElfXX_Shdr[] that has the new section headers, followed by the section
|
||||
* contents for __mcount_loc and its relocations. The old shstrtab strings,
|
||||
* and the old ElfXX_Shdr[] array, remain as "garbage" (commonly, a couple
|
||||
* kilobytes.) Subsequent processing by /bin/ld (or the kernel module loader)
|
||||
* will ignore the garbage regions, because they are not designated by the
|
||||
* new .e_shoff nor the new ElfXX_Shdr[]. [In order to remove the garbage,
|
||||
* then use "ld -r" to create a new file that omits the garbage.]
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <elf.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int fd_map; /* File descriptor for file being modified. */
|
||||
static int mmap_failed; /* Boolean flag. */
|
||||
static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
|
||||
static char gpfx; /* prefix for global symbol name (sometimes '_') */
|
||||
static struct stat sb; /* Remember .st_size, etc. */
|
||||
static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
|
||||
|
||||
/* setjmp() return values */
|
||||
enum {
|
||||
SJ_SETJMP = 0, /* hardwired first return */
|
||||
SJ_FAIL,
|
||||
SJ_SUCCEED
|
||||
};
|
||||
|
||||
/* Per-file resource cleanup when multiple files. */
|
||||
static void
|
||||
cleanup(void)
|
||||
{
|
||||
if (!mmap_failed)
|
||||
munmap(ehdr_curr, sb.st_size);
|
||||
else
|
||||
free(ehdr_curr);
|
||||
close(fd_map);
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn))
|
||||
fail_file(void)
|
||||
{
|
||||
cleanup();
|
||||
longjmp(jmpenv, SJ_FAIL);
|
||||
}
|
||||
|
||||
static void __attribute__((noreturn))
|
||||
succeed_file(void)
|
||||
{
|
||||
cleanup();
|
||||
longjmp(jmpenv, SJ_SUCCEED);
|
||||
}
|
||||
|
||||
/* ulseek, uread, ...: Check return value for errors. */
|
||||
|
||||
static off_t
|
||||
ulseek(int const fd, off_t const offset, int const whence)
|
||||
{
|
||||
off_t const w = lseek(fd, offset, whence);
|
||||
if ((off_t)-1 == w) {
|
||||
perror("lseek");
|
||||
fail_file();
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
static size_t
|
||||
uread(int const fd, void *const buf, size_t const count)
|
||||
{
|
||||
size_t const n = read(fd, buf, count);
|
||||
if (n != count) {
|
||||
perror("read");
|
||||
fail_file();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static size_t
|
||||
uwrite(int const fd, void const *const buf, size_t const count)
|
||||
{
|
||||
size_t const n = write(fd, buf, count);
|
||||
if (n != count) {
|
||||
perror("write");
|
||||
fail_file();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static void *
|
||||
umalloc(size_t size)
|
||||
{
|
||||
void *const addr = malloc(size);
|
||||
if (0 == addr) {
|
||||
fprintf(stderr, "malloc failed: %zu bytes\n", size);
|
||||
fail_file();
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the whole file as a programming convenience in order to avoid
|
||||
* malloc+lseek+read+free of many pieces. If successful, then mmap
|
||||
* avoids copying unused pieces; else just read the whole file.
|
||||
* Open for both read and write; new info will be appended to the file.
|
||||
* Use MAP_PRIVATE so that a few changes to the in-memory ElfXX_Ehdr
|
||||
* do not propagate to the file until an explicit overwrite at the last.
|
||||
* This preserves most aspects of consistency (all except .st_size)
|
||||
* for simultaneous readers of the file while we are appending to it.
|
||||
* However, multiple writers still are bad. We choose not to use
|
||||
* locking because it is expensive and the use case of kernel build
|
||||
* makes multiple writers unlikely.
|
||||
*/
|
||||
static void *mmap_file(char const *fname)
|
||||
{
|
||||
void *addr;
|
||||
|
||||
fd_map = open(fname, O_RDWR);
|
||||
if (0 > fd_map || 0 > fstat(fd_map, &sb)) {
|
||||
perror(fname);
|
||||
fail_file();
|
||||
}
|
||||
if (!S_ISREG(sb.st_mode)) {
|
||||
fprintf(stderr, "not a regular file: %s\n", fname);
|
||||
fail_file();
|
||||
}
|
||||
addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
|
||||
fd_map, 0);
|
||||
mmap_failed = 0;
|
||||
if (MAP_FAILED == addr) {
|
||||
mmap_failed = 1;
|
||||
addr = umalloc(sb.st_size);
|
||||
uread(fd_map, addr, sb.st_size);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
|
||||
/* w8rev, w8nat, ...: Handle endianness. */
|
||||
|
||||
static uint64_t w8rev(uint64_t const x)
|
||||
{
|
||||
return ((0xff & (x >> (0 * 8))) << (7 * 8))
|
||||
| ((0xff & (x >> (1 * 8))) << (6 * 8))
|
||||
| ((0xff & (x >> (2 * 8))) << (5 * 8))
|
||||
| ((0xff & (x >> (3 * 8))) << (4 * 8))
|
||||
| ((0xff & (x >> (4 * 8))) << (3 * 8))
|
||||
| ((0xff & (x >> (5 * 8))) << (2 * 8))
|
||||
| ((0xff & (x >> (6 * 8))) << (1 * 8))
|
||||
| ((0xff & (x >> (7 * 8))) << (0 * 8));
|
||||
}
|
||||
|
||||
static uint32_t w4rev(uint32_t const x)
|
||||
{
|
||||
return ((0xff & (x >> (0 * 8))) << (3 * 8))
|
||||
| ((0xff & (x >> (1 * 8))) << (2 * 8))
|
||||
| ((0xff & (x >> (2 * 8))) << (1 * 8))
|
||||
| ((0xff & (x >> (3 * 8))) << (0 * 8));
|
||||
}
|
||||
|
||||
static uint32_t w2rev(uint16_t const x)
|
||||
{
|
||||
return ((0xff & (x >> (0 * 8))) << (1 * 8))
|
||||
| ((0xff & (x >> (1 * 8))) << (0 * 8));
|
||||
}
|
||||
|
||||
static uint64_t w8nat(uint64_t const x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static uint32_t w4nat(uint32_t const x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static uint32_t w2nat(uint16_t const x)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
static uint64_t (*w8)(uint64_t);
|
||||
static uint32_t (*w)(uint32_t);
|
||||
static uint32_t (*w2)(uint16_t);
|
||||
|
||||
/* Names of the sections that could contain calls to mcount. */
|
||||
static int
|
||||
is_mcounted_section_name(char const *const txtname)
|
||||
{
|
||||
return 0 == strcmp(".text", txtname) ||
|
||||
0 == strcmp(".sched.text", txtname) ||
|
||||
0 == strcmp(".spinlock.text", txtname) ||
|
||||
0 == strcmp(".irqentry.text", txtname) ||
|
||||
0 == strcmp(".text.unlikely", txtname);
|
||||
}
|
||||
|
||||
/* 32 bit and 64 bit are very similar */
|
||||
#include "recordmcount.h"
|
||||
#define RECORD_MCOUNT_64
|
||||
#include "recordmcount.h"
|
||||
|
||||
/* 64-bit EM_MIPS has weird ELF64_Rela.r_info.
|
||||
* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
|
||||
* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40]
|
||||
* to imply the order of the members; the spec does not say so.
|
||||
* typedef unsigned char Elf64_Byte;
|
||||
* fails on MIPS64 because their <elf.h> already has it!
|
||||
*/
|
||||
|
||||
typedef uint8_t myElf64_Byte; /* Type for a 8-bit quantity. */
|
||||
|
||||
union mips_r_info {
|
||||
Elf64_Xword r_info;
|
||||
struct {
|
||||
Elf64_Word r_sym; /* Symbol index. */
|
||||
myElf64_Byte r_ssym; /* Special symbol. */
|
||||
myElf64_Byte r_type3; /* Third relocation. */
|
||||
myElf64_Byte r_type2; /* Second relocation. */
|
||||
myElf64_Byte r_type; /* First relocation. */
|
||||
} r_mips;
|
||||
};
|
||||
|
||||
static uint64_t MIPS64_r_sym(Elf64_Rel const *rp)
|
||||
{
|
||||
return w(((union mips_r_info){ .r_info = rp->r_info }).r_mips.r_sym);
|
||||
}
|
||||
|
||||
static void MIPS64_r_info(Elf64_Rel *const rp, unsigned sym, unsigned type)
|
||||
{
|
||||
rp->r_info = ((union mips_r_info){
|
||||
.r_mips = { .r_sym = w(sym), .r_type = type }
|
||||
}).r_info;
|
||||
}
|
||||
|
||||
static void
|
||||
do_file(char const *const fname)
|
||||
{
|
||||
Elf32_Ehdr *const ehdr = mmap_file(fname);
|
||||
unsigned int reltype = 0;
|
||||
|
||||
ehdr_curr = ehdr;
|
||||
w = w4nat;
|
||||
w2 = w2nat;
|
||||
w8 = w8nat;
|
||||
switch (ehdr->e_ident[EI_DATA]) {
|
||||
static unsigned int const endian = 1;
|
||||
default: {
|
||||
fprintf(stderr, "unrecognized ELF data encoding %d: %s\n",
|
||||
ehdr->e_ident[EI_DATA], fname);
|
||||
fail_file();
|
||||
} break;
|
||||
case ELFDATA2LSB: {
|
||||
if (1 != *(unsigned char const *)&endian) {
|
||||
/* main() is big endian, file.o is little endian. */
|
||||
w = w4rev;
|
||||
w2 = w2rev;
|
||||
w8 = w8rev;
|
||||
}
|
||||
} break;
|
||||
case ELFDATA2MSB: {
|
||||
if (0 != *(unsigned char const *)&endian) {
|
||||
/* main() is little endian, file.o is big endian. */
|
||||
w = w4rev;
|
||||
w2 = w2rev;
|
||||
w8 = w8rev;
|
||||
}
|
||||
} break;
|
||||
} /* end switch */
|
||||
if (0 != memcmp(ELFMAG, ehdr->e_ident, SELFMAG)
|
||||
|| ET_REL != w2(ehdr->e_type)
|
||||
|| EV_CURRENT != ehdr->e_ident[EI_VERSION]) {
|
||||
fprintf(stderr, "unrecognized ET_REL file %s\n", fname);
|
||||
fail_file();
|
||||
}
|
||||
|
||||
gpfx = 0;
|
||||
switch (w2(ehdr->e_machine)) {
|
||||
default: {
|
||||
fprintf(stderr, "unrecognized e_machine %d %s\n",
|
||||
w2(ehdr->e_machine), fname);
|
||||
fail_file();
|
||||
} break;
|
||||
case EM_386: reltype = R_386_32; break;
|
||||
case EM_ARM: reltype = R_ARM_ABS32; break;
|
||||
case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break;
|
||||
case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break;
|
||||
case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break;
|
||||
case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break;
|
||||
case EM_S390: /* reltype: e_class */ gpfx = '_'; break;
|
||||
case EM_SH: reltype = R_SH_DIR32; break;
|
||||
case EM_SPARCV9: reltype = R_SPARC_64; gpfx = '_'; break;
|
||||
case EM_X86_64: reltype = R_X86_64_64; break;
|
||||
} /* end switch */
|
||||
|
||||
switch (ehdr->e_ident[EI_CLASS]) {
|
||||
default: {
|
||||
fprintf(stderr, "unrecognized ELF class %d %s\n",
|
||||
ehdr->e_ident[EI_CLASS], fname);
|
||||
fail_file();
|
||||
} break;
|
||||
case ELFCLASS32: {
|
||||
if (sizeof(Elf32_Ehdr) != w2(ehdr->e_ehsize)
|
||||
|| sizeof(Elf32_Shdr) != w2(ehdr->e_shentsize)) {
|
||||
fprintf(stderr,
|
||||
"unrecognized ET_REL file: %s\n", fname);
|
||||
fail_file();
|
||||
}
|
||||
if (EM_S390 == w2(ehdr->e_machine))
|
||||
reltype = R_390_32;
|
||||
if (EM_MIPS == w2(ehdr->e_machine)) {
|
||||
reltype = R_MIPS_32;
|
||||
is_fake_mcount32 = MIPS32_is_fake_mcount;
|
||||
}
|
||||
do32(ehdr, fname, reltype);
|
||||
} break;
|
||||
case ELFCLASS64: {
|
||||
Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr;
|
||||
if (sizeof(Elf64_Ehdr) != w2(ghdr->e_ehsize)
|
||||
|| sizeof(Elf64_Shdr) != w2(ghdr->e_shentsize)) {
|
||||
fprintf(stderr,
|
||||
"unrecognized ET_REL file: %s\n", fname);
|
||||
fail_file();
|
||||
}
|
||||
if (EM_S390 == w2(ghdr->e_machine))
|
||||
reltype = R_390_64;
|
||||
if (EM_MIPS == w2(ghdr->e_machine)) {
|
||||
reltype = R_MIPS_64;
|
||||
Elf64_r_sym = MIPS64_r_sym;
|
||||
Elf64_r_info = MIPS64_r_info;
|
||||
is_fake_mcount64 = MIPS64_is_fake_mcount;
|
||||
}
|
||||
do64(ghdr, fname, reltype);
|
||||
} break;
|
||||
} /* end switch */
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char const *argv[])
|
||||
{
|
||||
const char ftrace[] = "kernel/trace/ftrace.o";
|
||||
int ftrace_size = sizeof(ftrace) - 1;
|
||||
int n_error = 0; /* gcc-4.3.0 false positive complaint */
|
||||
|
||||
if (argc <= 1) {
|
||||
fprintf(stderr, "usage: recordmcount file.o...\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Process each file in turn, allowing deep failure. */
|
||||
for (--argc, ++argv; 0 < argc; --argc, ++argv) {
|
||||
int const sjval = setjmp(jmpenv);
|
||||
int len;
|
||||
|
||||
/*
|
||||
* The file kernel/trace/ftrace.o references the mcount
|
||||
* function but does not call it. Since ftrace.o should
|
||||
* not be traced anyway, we just skip it.
|
||||
*/
|
||||
len = strlen(argv[0]);
|
||||
if (len >= ftrace_size &&
|
||||
strcmp(argv[0] + (len - ftrace_size), ftrace) == 0)
|
||||
continue;
|
||||
|
||||
switch (sjval) {
|
||||
default: {
|
||||
fprintf(stderr, "internal error: %s\n", argv[0]);
|
||||
exit(1);
|
||||
} break;
|
||||
case SJ_SETJMP: { /* normal sequence */
|
||||
/* Avoid problems if early cleanup() */
|
||||
fd_map = -1;
|
||||
ehdr_curr = NULL;
|
||||
mmap_failed = 1;
|
||||
do_file(argv[0]);
|
||||
} break;
|
||||
case SJ_FAIL: { /* error in do_file or below */
|
||||
++n_error;
|
||||
} break;
|
||||
case SJ_SUCCEED: { /* premature success */
|
||||
/* do nothing */
|
||||
} break;
|
||||
} /* end switch */
|
||||
}
|
||||
return !!n_error;
|
||||
}
|
||||
|
||||
|
442
scripts/recordmcount.h
Normal file
442
scripts/recordmcount.h
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* recordmcount.h
|
||||
*
|
||||
* This code was taken out of recordmcount.c written by
|
||||
* Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved.
|
||||
*
|
||||
* The original code had the same algorithms for both 32bit
|
||||
* and 64bit ELF files, but the code was duplicated to support
|
||||
* the difference in structures that were used. This
|
||||
* file creates a macro of everything that is different between
|
||||
* the 64 and 32 bit code, such that by including this header
|
||||
* twice we can create both sets of functions by including this
|
||||
* header once with RECORD_MCOUNT_64 undefined, and again with
|
||||
* it defined.
|
||||
*
|
||||
* This conversion to macros was done by:
|
||||
* Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc.
|
||||
*
|
||||
* Licensed under the GNU General Public License, version 2 (GPLv2).
|
||||
*/
|
||||
#undef append_func
|
||||
#undef is_fake_mcount
|
||||
#undef fn_is_fake_mcount
|
||||
#undef MIPS_is_fake_mcount
|
||||
#undef sift_rel_mcount
|
||||
#undef find_secsym_ndx
|
||||
#undef __has_rel_mcount
|
||||
#undef has_rel_mcount
|
||||
#undef tot_relsize
|
||||
#undef do_func
|
||||
#undef Elf_Addr
|
||||
#undef Elf_Ehdr
|
||||
#undef Elf_Shdr
|
||||
#undef Elf_Rel
|
||||
#undef Elf_Rela
|
||||
#undef Elf_Sym
|
||||
#undef ELF_R_SYM
|
||||
#undef Elf_r_sym
|
||||
#undef ELF_R_INFO
|
||||
#undef Elf_r_info
|
||||
#undef ELF_ST_BIND
|
||||
#undef fn_ELF_R_SYM
|
||||
#undef fn_ELF_R_INFO
|
||||
#undef uint_t
|
||||
#undef _w
|
||||
#undef _align
|
||||
#undef _size
|
||||
|
||||
#ifdef RECORD_MCOUNT_64
|
||||
# define append_func append64
|
||||
# define sift_rel_mcount sift64_rel_mcount
|
||||
# define find_secsym_ndx find64_secsym_ndx
|
||||
# define __has_rel_mcount __has64_rel_mcount
|
||||
# define has_rel_mcount has64_rel_mcount
|
||||
# define tot_relsize tot64_relsize
|
||||
# define do_func do64
|
||||
# define is_fake_mcount is_fake_mcount64
|
||||
# define fn_is_fake_mcount fn_is_fake_mcount64
|
||||
# define MIPS_is_fake_mcount MIPS64_is_fake_mcount
|
||||
# define Elf_Addr Elf64_Addr
|
||||
# define Elf_Ehdr Elf64_Ehdr
|
||||
# define Elf_Shdr Elf64_Shdr
|
||||
# define Elf_Rel Elf64_Rel
|
||||
# define Elf_Rela Elf64_Rela
|
||||
# define Elf_Sym Elf64_Sym
|
||||
# define ELF_R_SYM ELF64_R_SYM
|
||||
# define Elf_r_sym Elf64_r_sym
|
||||
# define ELF_R_INFO ELF64_R_INFO
|
||||
# define Elf_r_info Elf64_r_info
|
||||
# define ELF_ST_BIND ELF64_ST_BIND
|
||||
# define fn_ELF_R_SYM fn_ELF64_R_SYM
|
||||
# define fn_ELF_R_INFO fn_ELF64_R_INFO
|
||||
# define uint_t uint64_t
|
||||
# define _w w8
|
||||
# define _align 7u
|
||||
# define _size 8
|
||||
#else
|
||||
# define append_func append32
|
||||
# define sift_rel_mcount sift32_rel_mcount
|
||||
# define find_secsym_ndx find32_secsym_ndx
|
||||
# define __has_rel_mcount __has32_rel_mcount
|
||||
# define has_rel_mcount has32_rel_mcount
|
||||
# define tot_relsize tot32_relsize
|
||||
# define do_func do32
|
||||
# define is_fake_mcount is_fake_mcount32
|
||||
# define fn_is_fake_mcount fn_is_fake_mcount32
|
||||
# define MIPS_is_fake_mcount MIPS32_is_fake_mcount
|
||||
# define Elf_Addr Elf32_Addr
|
||||
# define Elf_Ehdr Elf32_Ehdr
|
||||
# define Elf_Shdr Elf32_Shdr
|
||||
# define Elf_Rel Elf32_Rel
|
||||
# define Elf_Rela Elf32_Rela
|
||||
# define Elf_Sym Elf32_Sym
|
||||
# define ELF_R_SYM ELF32_R_SYM
|
||||
# define Elf_r_sym Elf32_r_sym
|
||||
# define ELF_R_INFO ELF32_R_INFO
|
||||
# define Elf_r_info Elf32_r_info
|
||||
# define ELF_ST_BIND ELF32_ST_BIND
|
||||
# define fn_ELF_R_SYM fn_ELF32_R_SYM
|
||||
# define fn_ELF_R_INFO fn_ELF32_R_INFO
|
||||
# define uint_t uint32_t
|
||||
# define _w w
|
||||
# define _align 3u
|
||||
# define _size 4
|
||||
#endif
|
||||
|
||||
/* Functions and pointers that do_file() may override for specific e_machine. */
|
||||
static int fn_is_fake_mcount(Elf_Rel const *rp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static int (*is_fake_mcount)(Elf_Rel const *rp) = fn_is_fake_mcount;
|
||||
|
||||
static uint_t fn_ELF_R_SYM(Elf_Rel const *rp)
|
||||
{
|
||||
return ELF_R_SYM(_w(rp->r_info));
|
||||
}
|
||||
static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
|
||||
|
||||
static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
|
||||
{
|
||||
rp->r_info = ELF_R_INFO(sym, type);
|
||||
}
|
||||
static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
|
||||
|
||||
/*
|
||||
* MIPS mcount long call has 2 _mcount symbols, only the position of the 1st
|
||||
* _mcount symbol is needed for dynamic function tracer, with it, to disable
|
||||
* tracing(ftrace_make_nop), the instruction in the position is replaced with
|
||||
* the "b label" instruction, to enable tracing(ftrace_make_call), replace the
|
||||
* instruction back. So, here, we set the 2nd one as fake and filter it.
|
||||
*
|
||||
* c: 3c030000 lui v1,0x0 <--> b label
|
||||
* c: R_MIPS_HI16 _mcount
|
||||
* c: R_MIPS_NONE *ABS*
|
||||
* c: R_MIPS_NONE *ABS*
|
||||
* 10: 64630000 daddiu v1,v1,0
|
||||
* 10: R_MIPS_LO16 _mcount
|
||||
* 10: R_MIPS_NONE *ABS*
|
||||
* 10: R_MIPS_NONE *ABS*
|
||||
* 14: 03e0082d move at,ra
|
||||
* 18: 0060f809 jalr v1
|
||||
* label:
|
||||
*/
|
||||
#define MIPS_FAKEMCOUNT_OFFSET 4
|
||||
|
||||
static int MIPS_is_fake_mcount(Elf_Rel const *rp)
|
||||
{
|
||||
static Elf_Addr old_r_offset;
|
||||
Elf_Addr current_r_offset = _w(rp->r_offset);
|
||||
int is_fake;
|
||||
|
||||
is_fake = old_r_offset &&
|
||||
(current_r_offset - old_r_offset == MIPS_FAKEMCOUNT_OFFSET);
|
||||
old_r_offset = current_r_offset;
|
||||
|
||||
return is_fake;
|
||||
}
|
||||
|
||||
/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */
|
||||
static void append_func(Elf_Ehdr *const ehdr,
|
||||
Elf_Shdr *const shstr,
|
||||
uint_t const *const mloc0,
|
||||
uint_t const *const mlocp,
|
||||
Elf_Rel const *const mrel0,
|
||||
Elf_Rel const *const mrelp,
|
||||
unsigned int const rel_entsize,
|
||||
unsigned int const symsec_sh_link)
|
||||
{
|
||||
/* Begin constructing output file */
|
||||
Elf_Shdr mcsec;
|
||||
char const *mc_name = (sizeof(Elf_Rela) == rel_entsize)
|
||||
? ".rela__mcount_loc"
|
||||
: ".rel__mcount_loc";
|
||||
unsigned const old_shnum = w2(ehdr->e_shnum);
|
||||
uint_t const old_shoff = _w(ehdr->e_shoff);
|
||||
uint_t const old_shstr_sh_size = _w(shstr->sh_size);
|
||||
uint_t const old_shstr_sh_offset = _w(shstr->sh_offset);
|
||||
uint_t t = 1 + strlen(mc_name) + _w(shstr->sh_size);
|
||||
uint_t new_e_shoff;
|
||||
|
||||
shstr->sh_size = _w(t);
|
||||
shstr->sh_offset = _w(sb.st_size);
|
||||
t += sb.st_size;
|
||||
t += (_align & -t); /* word-byte align */
|
||||
new_e_shoff = t;
|
||||
|
||||
/* body for new shstrtab */
|
||||
ulseek(fd_map, sb.st_size, SEEK_SET);
|
||||
uwrite(fd_map, old_shstr_sh_offset + (void *)ehdr, old_shstr_sh_size);
|
||||
uwrite(fd_map, mc_name, 1 + strlen(mc_name));
|
||||
|
||||
/* old(modified) Elf_Shdr table, word-byte aligned */
|
||||
ulseek(fd_map, t, SEEK_SET);
|
||||
t += sizeof(Elf_Shdr) * old_shnum;
|
||||
uwrite(fd_map, old_shoff + (void *)ehdr,
|
||||
sizeof(Elf_Shdr) * old_shnum);
|
||||
|
||||
/* new sections __mcount_loc and .rel__mcount_loc */
|
||||
t += 2*sizeof(mcsec);
|
||||
mcsec.sh_name = w((sizeof(Elf_Rela) == rel_entsize) + strlen(".rel")
|
||||
+ old_shstr_sh_size);
|
||||
mcsec.sh_type = w(SHT_PROGBITS);
|
||||
mcsec.sh_flags = _w(SHF_ALLOC);
|
||||
mcsec.sh_addr = 0;
|
||||
mcsec.sh_offset = _w(t);
|
||||
mcsec.sh_size = _w((void *)mlocp - (void *)mloc0);
|
||||
mcsec.sh_link = 0;
|
||||
mcsec.sh_info = 0;
|
||||
mcsec.sh_addralign = _w(_size);
|
||||
mcsec.sh_entsize = _w(_size);
|
||||
uwrite(fd_map, &mcsec, sizeof(mcsec));
|
||||
|
||||
mcsec.sh_name = w(old_shstr_sh_size);
|
||||
mcsec.sh_type = (sizeof(Elf_Rela) == rel_entsize)
|
||||
? w(SHT_RELA)
|
||||
: w(SHT_REL);
|
||||
mcsec.sh_flags = 0;
|
||||
mcsec.sh_addr = 0;
|
||||
mcsec.sh_offset = _w((void *)mlocp - (void *)mloc0 + t);
|
||||
mcsec.sh_size = _w((void *)mrelp - (void *)mrel0);
|
||||
mcsec.sh_link = w(symsec_sh_link);
|
||||
mcsec.sh_info = w(old_shnum);
|
||||
mcsec.sh_addralign = _w(_size);
|
||||
mcsec.sh_entsize = _w(rel_entsize);
|
||||
uwrite(fd_map, &mcsec, sizeof(mcsec));
|
||||
|
||||
uwrite(fd_map, mloc0, (void *)mlocp - (void *)mloc0);
|
||||
uwrite(fd_map, mrel0, (void *)mrelp - (void *)mrel0);
|
||||
|
||||
ehdr->e_shoff = _w(new_e_shoff);
|
||||
ehdr->e_shnum = w2(2 + w2(ehdr->e_shnum)); /* {.rel,}__mcount_loc */
|
||||
ulseek(fd_map, 0, SEEK_SET);
|
||||
uwrite(fd_map, ehdr, sizeof(*ehdr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Look at the relocations in order to find the calls to mcount.
|
||||
* Accumulate the section offsets that are found, and their relocation info,
|
||||
* onto the end of the existing arrays.
|
||||
*/
|
||||
static uint_t *sift_rel_mcount(uint_t *mlocp,
|
||||
unsigned const offbase,
|
||||
Elf_Rel **const mrelpp,
|
||||
Elf_Shdr const *const relhdr,
|
||||
Elf_Ehdr const *const ehdr,
|
||||
unsigned const recsym,
|
||||
uint_t const recval,
|
||||
unsigned const reltype)
|
||||
{
|
||||
uint_t *const mloc0 = mlocp;
|
||||
Elf_Rel *mrelp = *mrelpp;
|
||||
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
|
||||
+ (void *)ehdr);
|
||||
unsigned const symsec_sh_link = w(relhdr->sh_link);
|
||||
Elf_Shdr const *const symsec = &shdr0[symsec_sh_link];
|
||||
Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symsec->sh_offset)
|
||||
+ (void *)ehdr);
|
||||
|
||||
Elf_Shdr const *const strsec = &shdr0[w(symsec->sh_link)];
|
||||
char const *const str0 = (char const *)(_w(strsec->sh_offset)
|
||||
+ (void *)ehdr);
|
||||
|
||||
Elf_Rel const *const rel0 = (Elf_Rel const *)(_w(relhdr->sh_offset)
|
||||
+ (void *)ehdr);
|
||||
unsigned rel_entsize = _w(relhdr->sh_entsize);
|
||||
unsigned const nrel = _w(relhdr->sh_size) / rel_entsize;
|
||||
Elf_Rel const *relp = rel0;
|
||||
|
||||
unsigned mcountsym = 0;
|
||||
unsigned t;
|
||||
|
||||
for (t = nrel; t; --t) {
|
||||
if (!mcountsym) {
|
||||
Elf_Sym const *const symp =
|
||||
&sym0[Elf_r_sym(relp)];
|
||||
char const *symname = &str0[w(symp->st_name)];
|
||||
|
||||
if ('.' == symname[0])
|
||||
++symname; /* ppc64 hack */
|
||||
if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
|
||||
symname))
|
||||
mcountsym = Elf_r_sym(relp);
|
||||
}
|
||||
|
||||
if (mcountsym == Elf_r_sym(relp) && !is_fake_mcount(relp)) {
|
||||
uint_t const addend = _w(_w(relp->r_offset) - recval);
|
||||
|
||||
mrelp->r_offset = _w(offbase
|
||||
+ ((void *)mlocp - (void *)mloc0));
|
||||
Elf_r_info(mrelp, recsym, reltype);
|
||||
if (sizeof(Elf_Rela) == rel_entsize) {
|
||||
((Elf_Rela *)mrelp)->r_addend = addend;
|
||||
*mlocp++ = 0;
|
||||
} else
|
||||
*mlocp++ = addend;
|
||||
|
||||
mrelp = (Elf_Rel *)(rel_entsize + (void *)mrelp);
|
||||
}
|
||||
relp = (Elf_Rel const *)(rel_entsize + (void *)relp);
|
||||
}
|
||||
*mrelpp = mrelp;
|
||||
return mlocp;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find a symbol in the given section, to be used as the base for relocating
|
||||
* the table of offsets of calls to mcount. A local or global symbol suffices,
|
||||
* but avoid a Weak symbol because it may be overridden; the change in value
|
||||
* would invalidate the relocations of the offsets of the calls to mcount.
|
||||
* Often the found symbol will be the unnamed local symbol generated by
|
||||
* GNU 'as' for the start of each section. For example:
|
||||
* Num: Value Size Type Bind Vis Ndx Name
|
||||
* 2: 00000000 0 SECTION LOCAL DEFAULT 1
|
||||
*/
|
||||
static unsigned find_secsym_ndx(unsigned const txtndx,
|
||||
char const *const txtname,
|
||||
uint_t *const recvalp,
|
||||
Elf_Shdr const *const symhdr,
|
||||
Elf_Ehdr const *const ehdr)
|
||||
{
|
||||
Elf_Sym const *const sym0 = (Elf_Sym const *)(_w(symhdr->sh_offset)
|
||||
+ (void *)ehdr);
|
||||
unsigned const nsym = _w(symhdr->sh_size) / _w(symhdr->sh_entsize);
|
||||
Elf_Sym const *symp;
|
||||
unsigned t;
|
||||
|
||||
for (symp = sym0, t = nsym; t; --t, ++symp) {
|
||||
unsigned int const st_bind = ELF_ST_BIND(symp->st_info);
|
||||
|
||||
if (txtndx == w2(symp->st_shndx)
|
||||
/* avoid STB_WEAK */
|
||||
&& (STB_LOCAL == st_bind || STB_GLOBAL == st_bind)) {
|
||||
*recvalp = _w(symp->st_value);
|
||||
return symp - sym0;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Cannot find symbol for section %d: %s.\n",
|
||||
txtndx, txtname);
|
||||
fail_file();
|
||||
}
|
||||
|
||||
|
||||
/* Evade ISO C restriction: no declaration after statement in has_rel_mcount. */
|
||||
static char const *
|
||||
__has_rel_mcount(Elf_Shdr const *const relhdr, /* is SHT_REL or SHT_RELA */
|
||||
Elf_Shdr const *const shdr0,
|
||||
char const *const shstrtab,
|
||||
char const *const fname)
|
||||
{
|
||||
/* .sh_info depends on .sh_type == SHT_REL[,A] */
|
||||
Elf_Shdr const *const txthdr = &shdr0[w(relhdr->sh_info)];
|
||||
char const *const txtname = &shstrtab[w(txthdr->sh_name)];
|
||||
|
||||
if (0 == strcmp("__mcount_loc", txtname)) {
|
||||
fprintf(stderr, "warning: __mcount_loc already exists: %s\n",
|
||||
fname);
|
||||
succeed_file();
|
||||
}
|
||||
if (SHT_PROGBITS != w(txthdr->sh_type) ||
|
||||
!is_mcounted_section_name(txtname))
|
||||
return NULL;
|
||||
return txtname;
|
||||
}
|
||||
|
||||
static char const *has_rel_mcount(Elf_Shdr const *const relhdr,
|
||||
Elf_Shdr const *const shdr0,
|
||||
char const *const shstrtab,
|
||||
char const *const fname)
|
||||
{
|
||||
if (SHT_REL != w(relhdr->sh_type) && SHT_RELA != w(relhdr->sh_type))
|
||||
return NULL;
|
||||
return __has_rel_mcount(relhdr, shdr0, shstrtab, fname);
|
||||
}
|
||||
|
||||
|
||||
static unsigned tot_relsize(Elf_Shdr const *const shdr0,
|
||||
unsigned nhdr,
|
||||
const char *const shstrtab,
|
||||
const char *const fname)
|
||||
{
|
||||
unsigned totrelsz = 0;
|
||||
Elf_Shdr const *shdrp = shdr0;
|
||||
|
||||
for (; nhdr; --nhdr, ++shdrp) {
|
||||
if (has_rel_mcount(shdrp, shdr0, shstrtab, fname))
|
||||
totrelsz += _w(shdrp->sh_size);
|
||||
}
|
||||
return totrelsz;
|
||||
}
|
||||
|
||||
|
||||
/* Overall supervision for Elf32 ET_REL file. */
|
||||
static void
|
||||
do_func(Elf_Ehdr *const ehdr, char const *const fname, unsigned const reltype)
|
||||
{
|
||||
Elf_Shdr *const shdr0 = (Elf_Shdr *)(_w(ehdr->e_shoff)
|
||||
+ (void *)ehdr);
|
||||
unsigned const nhdr = w2(ehdr->e_shnum);
|
||||
Elf_Shdr *const shstr = &shdr0[w2(ehdr->e_shstrndx)];
|
||||
char const *const shstrtab = (char const *)(_w(shstr->sh_offset)
|
||||
+ (void *)ehdr);
|
||||
|
||||
Elf_Shdr const *relhdr;
|
||||
unsigned k;
|
||||
|
||||
/* Upper bound on space: assume all relevant relocs are for mcount. */
|
||||
unsigned const totrelsz = tot_relsize(shdr0, nhdr, shstrtab, fname);
|
||||
Elf_Rel *const mrel0 = umalloc(totrelsz);
|
||||
Elf_Rel * mrelp = mrel0;
|
||||
|
||||
/* 2*sizeof(address) <= sizeof(Elf_Rel) */
|
||||
uint_t *const mloc0 = umalloc(totrelsz>>1);
|
||||
uint_t * mlocp = mloc0;
|
||||
|
||||
unsigned rel_entsize = 0;
|
||||
unsigned symsec_sh_link = 0;
|
||||
|
||||
for (relhdr = shdr0, k = nhdr; k; --k, ++relhdr) {
|
||||
char const *const txtname = has_rel_mcount(relhdr, shdr0,
|
||||
shstrtab, fname);
|
||||
if (txtname) {
|
||||
uint_t recval = 0;
|
||||
unsigned const recsym = find_secsym_ndx(
|
||||
w(relhdr->sh_info), txtname, &recval,
|
||||
&shdr0[symsec_sh_link = w(relhdr->sh_link)],
|
||||
ehdr);
|
||||
|
||||
rel_entsize = _w(relhdr->sh_entsize);
|
||||
mlocp = sift_rel_mcount(mlocp,
|
||||
(void *)mlocp - (void *)mloc0, &mrelp,
|
||||
relhdr, ehdr, recsym, recval, reltype);
|
||||
}
|
||||
}
|
||||
if (mloc0 != mlocp) {
|
||||
append_func(ehdr, shstr, mloc0, mlocp, mrel0, mrelp,
|
||||
rel_entsize, symsec_sh_link);
|
||||
}
|
||||
free(mrel0);
|
||||
free(mloc0);
|
||||
}
|
@@ -159,6 +159,7 @@ my $section_regex; # Find the start of a section
|
||||
my $function_regex; # Find the name of a function
|
||||
# (return offset and func name)
|
||||
my $mcount_regex; # Find the call site to mcount (return offset)
|
||||
my $mcount_adjust; # Address adjustment to mcount offset
|
||||
my $alignment; # The .align value to use for $mcount_section
|
||||
my $section_type; # Section header plus possible alignment command
|
||||
my $can_use_local = 0; # If we can use local function references
|
||||
@@ -213,6 +214,7 @@ $section_regex = "Disassembly of section\\s+(\\S+):";
|
||||
$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
|
||||
$section_type = '@progbits';
|
||||
$mcount_adjust = 0;
|
||||
$type = ".long";
|
||||
|
||||
if ($arch eq "x86_64") {
|
||||
@@ -268,6 +270,8 @@ if ($arch eq "x86_64") {
|
||||
} elsif ($arch eq "arm") {
|
||||
$alignment = 2;
|
||||
$section_type = '%progbits';
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):\\s*R_ARM_(CALL|PC24|THM_CALL)" .
|
||||
"\\s+(__gnu_mcount_nc|mcount)\$";
|
||||
|
||||
} elsif ($arch eq "ia64") {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
||||
@@ -326,7 +330,7 @@ if ($arch eq "x86_64") {
|
||||
# 14: R_MIPS_NONE *ABS*
|
||||
# 18: 00020021 nop
|
||||
if ($is_module eq "0") {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$";
|
||||
} else {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
|
||||
}
|
||||
@@ -351,6 +355,9 @@ if ($arch eq "x86_64") {
|
||||
} elsif ($arch eq "microblaze") {
|
||||
# Microblaze calls '_mcount' instead of plain 'mcount'.
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
|
||||
} elsif ($arch eq "blackfin") {
|
||||
$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s__mcount\$";
|
||||
$mcount_adjust = -4;
|
||||
} else {
|
||||
die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
|
||||
}
|
||||
@@ -511,7 +518,7 @@ while (<IN>) {
|
||||
}
|
||||
# is this a call site to mcount? If so, record it to print later
|
||||
if ($text_found && /$mcount_regex/) {
|
||||
push(@offsets, hex $1);
|
||||
push(@offsets, (hex $1) + $mcount_adjust);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -43,7 +43,7 @@ scm_version()
|
||||
fi
|
||||
|
||||
# Check for git and a git repo.
|
||||
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
|
||||
if test -d .git && head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
|
||||
|
||||
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
|
||||
# it, because this version is defined in the top level Makefile.
|
||||
@@ -85,7 +85,7 @@ scm_version()
|
||||
fi
|
||||
|
||||
# Check for mercurial and a mercurial repo.
|
||||
if hgid=`hg id 2>/dev/null`; then
|
||||
if test -d .hg && hgid=`hg id 2>/dev/null`; then
|
||||
tag=`printf '%s' "$hgid" | cut -s -d' ' -f2`
|
||||
|
||||
# Do we have an untagged version?
|
||||
|
Reference in New Issue
Block a user