- Resync Kconfiglib with the v14.1.0 release.
- Re-sync our <linux/compiler*h> files with v5.7-rc5 from upstream.
- Fully resync checkpatch.pl with v5.7 release.
To safely to all of the above, we have a few bugfixes about functions
that need a 'static inline' but weren't. We also stop setting
CROSS_COMPILE in arch/*/config.mk. Finally, with the above changes
boards can now opt-in to optimizing inlining and we do this for the
socfpga stratix10 platform for space savings.
#
mainmenu "U-Boot $(UBOOTVERSION) Configuration"
+comment "Compiler: $(CC_VERSION_TEXT)"
+
+source "scripts/Kconfig.include"
+
# Allow defaults in arch-specific code to override any given here
source "arch/Kconfig"
This option is enabled by default for U-Boot.
+config OPTIMIZE_INLINING
+ bool "Allow compiler to uninline functions marked 'inline' in full U-Boot"
+ default n
+ help
+ This option determines if U-Boot forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable in some cases for size
+ reasons.
+
+config SPL_OPTIMIZE_INLINING
+ bool "Allow compiler to uninline functions marked 'inline' in SPL"
+ depends on SPL
+ default n
+ help
+ This option determines if U-Boot forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable in some cases for size
+ reasons.
+
+config TPL_OPTIMIZE_INLINING
+ bool "Allow compiler to uninline functions marked 'inline' in TPL"
+ depends on TPL
+ default n
+ help
+ This option determines if U-Boot forces gcc to inline the functions
+ developers have marked 'inline'. Doing so takes away freedom from gcc to
+ do what it thinks is best, which is desirable in some cases for size
+ reasons.
+
config CC_COVERAGE
bool "Enable code coverage analysis"
depends on SANDBOX
Enabling this option will pass "--coverage" to gcc to compile
and link code instrumented for coverage analysis.
+config CC_HAS_ASM_INLINE
+ def_bool $(success,echo 'void foo(void) { asm inline (""); }' | $(CC) -x c - -c -o /dev/null)
+
config DISTRO_DEFAULTS
bool "Select defaults suitable for booting general purpose Linux distributions"
select AUTO_COMPLETE
# disable stringop warnings in gcc 8+
KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation)
+# Enabled with W=2, disabled by default as noisy
+KBUILD_CFLAGS += $(call cc-disable-warning, maybe-uninitialized)
+
# change __FILE__ to the relative path from the srctree
KBUILD_CFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
#ifdef CONFIG_FPGA
void socfpga_fpga_add(void *fpga_desc);
#else
-inline void socfpga_fpga_add(void *fpga_desc) {}
+static inline void socfpga_fpga_add(void *fpga_desc) {}
#endif
#ifdef CONFIG_TARGET_SOCFPGA_GEN5
{
/*
* This function performs multiple checks on the same values with
- * security implications, so create snapshots with ACCESS_ONCE() to
+ * security implications, so create snapshots with READ_ONCE() to
* ensure that these checks use the same values.
*/
- uint32_t w_count = ACCESS_ONCE(ch->w_count);
- uint32_t r_count = ACCESS_ONCE(ch->r_count);
+ uint32_t w_count = READ_ONCE(ch->w_count);
+ uint32_t r_count = READ_ONCE(ch->r_count);
/*
* Perform an over-full check to prevent denial of service attacks where
* Invalid cases where the counters indicate that the queue is over
* capacity also appear full.
*/
- return (ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count)) >=
+ return (READ_ONCE(ch->w_count) - READ_ONCE(ch->r_count)) >=
ivc->nframes;
}
static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
{
- ACCESS_ONCE(ivc->rx_channel->r_count) =
- ACCESS_ONCE(ivc->rx_channel->r_count) + 1;
+ WRITE_ONCE(ivc->rx_channel->r_count,
+ READ_ONCE(ivc->rx_channel->r_count) + 1);
if (ivc->r_pos == ivc->nframes - 1)
ivc->r_pos = 0;
static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
{
- ACCESS_ONCE(ivc->tx_channel->w_count) =
- ACCESS_ONCE(ivc->tx_channel->w_count) + 1;
+ WRITE_ONCE(ivc->tx_channel->w_count,
+ READ_ONCE(ivc->tx_channel->w_count) + 1);
if (ivc->w_pos == ivc->nframes - 1)
ivc->w_pos = 0;
* comment in tegra_ivc_channel_empty() for an explanation about
* special over-full considerations.
*/
- return ACCESS_ONCE(ch->w_count) - ACCESS_ONCE(ch->r_count);
+ return READ_ONCE(ch->w_count) - READ_ONCE(ch->r_count);
}
int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, void **frame)
/* Copy the receiver's state out of shared memory. */
offset = offsetof(struct tegra_ivc_channel_header, w_count);
tegra_ivc_invalidate_counter(ivc, ivc->rx_channel, offset);
- peer_state = ACCESS_ONCE(ivc->rx_channel->state);
+ peer_state = READ_ONCE(ivc->rx_channel->state);
if (peer_state == ivc_state_sync) {
/*
# (C) Copyright 2000-2002
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := m68k-elf-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR ?= 0x20000
PLATFORM_CPPFLAGS += -D__M68K__
# (C) Copyright 2004 Atmark Techno, Inc.
# Yasushi SHOJI <yashi@atmark-techno.com>
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := mb-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR ?= 0x80F00000
PLATFORM_CPPFLAGS += -ffixed-r31 -D__microblaze__
# Macpaul Lin, Andes Technology Corporation <macpaul@andestech.com>
#
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := nds32le-linux-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR = 0x300000
LDFLAGS_STANDALONE += -T $(srctree)/examples/standalone/nds32.lds
# Psyent Corporation <www.psyent.com>
# Scott McNutt <smcnutt@psyent.com>
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := nios2-elf-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR ?= 0x02000000
PLATFORM_CPPFLAGS += -D__NIOS2__
# (C) Copyright 2000-2010
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := ppc_8xx-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
LDFLAGS_FINAL += --gc-sections
LDFLAGS_FINAL += --bss-plt
# (C) Copyright 2000-2002
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
-ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := sh4-linux-
-endif
-
CONFIG_STANDALONE_LOAD_ADDR ?= 0x8C000000
ifeq ($(CPU),sh2)
LDFLAGS_STANDALONE += -EB
# (C) Copyright 2002
# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
-CROSS_COMPILE ?= i386-linux-
-
# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
LDPPFLAGS += -DRESET_SEG_START=$(CONFIG_RESET_SEG_START)
LDPPFLAGS += -DRESET_VEC_LOC=$(CONFIG_RESET_VEC_LOC)
*/
static inline int atomic_read(const atomic_t *v)
{
- return ACCESS_ONCE((v)->counter);
+ return READ_ONCE((v)->counter);
}
/**
# (C) Copyright 2007 - 2013 Tensilica, Inc.
# (C) Copyright 2014 - 2016 Cadence Design Systems Inc.
-CROSS_COMPILE ?= xtensa-linux-
PLATFORM_CPPFLAGS += -D__XTENSA__ -mlongcalls -mforce-no-pic \
-ffunction-sections -fdata-sections
CONFIG_IDENT_STRING="socfpga_stratix10"
CONFIG_SPL_FS_FAT=y
CONFIG_SPL_TEXT_BASE=0xFFE00000
+CONFIG_OPTIMIZE_INLINING=y
+CONFIG_SPL_OPTIMIZE_INLINING=y
CONFIG_BOOTDELAY=5
CONFIG_USE_BOOTARGS=y
CONFIG_BOOTARGS="earlycon"
int rockchip_pcie_phy_get(struct udevice *dev);
-inline struct rockchip_pcie_phy *pcie_get_phy(struct rockchip_pcie *pcie)
+static inline struct rockchip_pcie_phy *pcie_get_phy(struct rockchip_pcie *pcie)
{
return pcie->phy;
}
-inline
-struct rockchip_pcie_phy_ops *phy_get_ops(struct rockchip_pcie_phy *phy)
+static inline struct rockchip_pcie_phy_ops *phy_get_ops(struct rockchip_pcie_phy *phy)
{
return (struct rockchip_pcie_phy_ops *)phy->ops;
}
-#ifndef __LINUX_COMPILER_H
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
#error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
#endif
-/* Some compiler specific definitions are overwritten here
- * for Clang compiler
- */
+/* Compiler specific definitions for Clang compiler */
-#ifdef uninitialized_var
-#undef uninitialized_var
#define uninitialized_var(x) x = *(&(x))
+
+/* same as gcc, this was present in clang-2.6 so we can assume it works
+ * with any version that can compile the kernel
+ */
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+
+/* all clang versions usable with the kernel support KASAN ABI version 5 */
+#define KASAN_ABI_VERSION 5
+
+#if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer)
+/* emulate gcc's __SANITIZE_ADDRESS__ flag */
+#define __SANITIZE_ADDRESS__
+#define __no_sanitize_address \
+ __attribute__((no_sanitize("address", "hwaddress")))
+#else
+#define __no_sanitize_address
#endif
+
+/*
+ * Not all versions of clang implement the the type-generic versions
+ * of the builtin overflow checkers. Fortunately, clang implements
+ * __has_builtin allowing us to avoid awkward version
+ * checks. Unfortunately, we don't know which version of gcc clang
+ * pretends to be, so the macro may or may not be defined.
+ */
+#if __has_builtin(__builtin_mul_overflow) && \
+ __has_builtin(__builtin_add_overflow) && \
+ __has_builtin(__builtin_sub_overflow)
+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
+#endif
+
+/* The following are for compatibility with GCC, from compiler-gcc.h,
+ * and may be redefined here because they should not be shared with other
+ * compilers, like ICC.
+ */
+#define barrier() __asm__ __volatile__("" : : : "memory")
-#ifndef __LINUX_COMPILER_H
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
#error "Please don't include <linux/compiler-gcc.h> directly, include <linux/compiler.h> instead."
#endif
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
+#if GCC_VERSION < 40600
+# error Sorry, your compiler is too old - please upgrade it.
+#endif
+
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
-#define barrier() \
- __asm__ __volatile__("": : :"memory")
+#define barrier() __asm__ __volatile__("": : :"memory")
/*
* This version is i.e. to prevent dead stores elimination on @ptr
* where gcc and llvm may behave differently when otherwise using
* clobbered. The issue is as follows: while the inline asm might
* access any memory it wants, the compiler could have fit all of
* @ptr into memory registers instead, and since @ptr never escaped
- * from that, it proofed that the inline asm wasn't touching any of
+ * from that, it proved that the inline asm wasn't touching any of
* it. This version works well with both compilers, i.e. we're telling
* the compiler that the inline asm absolutely may see the contents
* of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
*/
-#define barrier_data(ptr) \
- __asm__ __volatile__("": :"r"(ptr) :"memory")
+#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
/*
* This macro obfuscates arithmetic on a variable address so that gcc
(typeof(ptr)) (__ptr + (off)); \
})
-/* Make the optimizer believe the variable can be manipulated arbitrarily. */
-#define OPTIMIZER_HIDE_VAR(var) \
- __asm__ ("" : "=r" (var) : "0" (var))
-
-#ifdef __CHECKER__
-#define __must_be_array(a) 0
-#else
-/* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
-#endif
-
-/*
- * Force always-inline if the user requests it so via the .config,
- * or if gcc is too old:
- */
-#if !defined(CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING) || \
- !defined(CONFIG_OPTIMIZE_INLINING) || (__GNUC__ < 4)
-#define inline inline __attribute__((always_inline)) notrace
-#define __inline__ __inline__ __attribute__((always_inline)) notrace
-#define __inline __inline __attribute__((always_inline)) notrace
-#else
-/* A lot of inline functions can cause havoc with function tracing */
-#define inline inline notrace
-#define __inline__ __inline__ notrace
-#define __inline __inline notrace
-#endif
-
-#define __always_inline inline __attribute__((always_inline))
-#define noinline __attribute__((noinline))
-
-#define __deprecated __attribute__((deprecated))
-#define __packed __attribute__((packed))
-#define __weak __attribute__((weak))
-#define __alias(symbol) __attribute__((alias(#symbol)))
-
/*
- * it doesn't make sense on ARM (currently the only user of __naked)
- * to trace naked functions because then mcount is called without
- * stack and frame pointer being set up and there is no chance to
- * restore the lr register to the value before mcount was called.
- *
- * The asm() bodies of naked functions often depend on standard calling
- * conventions, therefore they must be noinline and noclone.
- *
- * GCC 4.[56] currently fail to enforce this, so we must do so ourselves.
- * See GCC PR44290.
- */
-#define __naked __attribute__((naked)) noinline __noclone notrace
-
-#define __noreturn __attribute__((noreturn))
-
-/*
- * From the GCC manual:
- *
- * Many functions have no effects except the return value and their
- * return value depends only on the parameters and/or global
- * variables. Such a function can be subject to common subexpression
- * elimination and loop optimization just as an arithmetic operator
- * would be.
- * [...]
+ * A trick to suppress uninitialized variable warning without generating any
+ * code
*/
-#define __pure __attribute__((pure))
-#define __aligned(x) __attribute__((aligned(x)))
-#define __printf(a, b) __attribute__((format(printf, a, b)))
-#define __scanf(a, b) __attribute__((format(scanf, a, b)))
-#define __attribute_const__ __attribute__((__const__))
-#define __maybe_unused __attribute__((unused))
-#define __always_unused __attribute__((unused))
-
-/* gcc version specific checks */
-
-#if GCC_VERSION < 30200
-# error Sorry, your compiler is too old - please upgrade it.
-#endif
-
-#if GCC_VERSION < 30300
-# define __used __attribute__((__unused__))
-#else
-# define __used __attribute__((__used__))
-#endif
-
-#ifdef CONFIG_GCOV_KERNEL
-# if GCC_VERSION < 30400
-# error "GCOV profiling support for gcc versions below 3.4 not included"
-# endif /* __GNUC_MINOR__ */
-#endif /* CONFIG_GCOV_KERNEL */
+#define uninitialized_var(x) x = x
-#if GCC_VERSION >= 30400
-#define __must_check __attribute__((warn_unused_result))
+#ifdef CONFIG_RETPOLINE
+#define __noretpoline __attribute__((__indirect_branch__("keep")))
#endif
-#if GCC_VERSION >= 40000
+#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
-/* GCC 4.1.[01] miscompiles __weak */
-#ifdef __KERNEL__
-# if GCC_VERSION >= 40100 && GCC_VERSION <= 40101
-# error Your version of gcc miscompiles the __weak directive
-# endif
-#endif
+#define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
-#define __used __attribute__((__used__))
-#define __compiler_offsetof(a, b) \
- __builtin_offsetof(a, b)
+#define __compiletime_warning(message) __attribute__((__warning__(message)))
+#define __compiletime_error(message) __attribute__((__error__(message)))
-#if GCC_VERSION >= 40100 && GCC_VERSION < 40600
-# define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
+#if defined(LATENT_ENTROPY_PLUGIN) && !defined(__CHECKER__)
+#define __latent_entropy __attribute__((latent_entropy))
#endif
-#if GCC_VERSION >= 40300
-/* Mark functions as cold. gcc will assume any path leading to a call
- * to them will be unlikely. This means a lot of manual unlikely()s
- * are unnecessary now for any paths leading to the usual suspects
- * like BUG(), printk(), panic() etc. [but let's keep them for now for
- * older compilers]
- *
- * Early snapshots of gcc 4.3 don't support this and we can't detect this
- * in the preprocessor, but we can live with this because they're unreleased.
- * Maketime probing would be overkill here.
+/*
+ * calling noreturn functions, __builtin_unreachable() and __builtin_trap()
+ * confuse the stack allocation in gcc, leading to overly large stack
+ * frames, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365
*
- * gcc also has a __attribute__((__hot__)) to move hot functions into
- * a special section, but I don't see any sense in this right now in
- * the kernel context
+ * Adding an empty inline assembly before it works around the problem
*/
-#define __cold __attribute__((__cold__))
-
-#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__)
+#define barrier_before_unreachable() asm volatile("")
-#ifndef __CHECKER__
-# define __compiletime_warning(message) __attribute__((warning(message)))
-# define __compiletime_error(message) __attribute__((error(message)))
-#endif /* __CHECKER__ */
-#endif /* GCC_VERSION >= 40300 */
-
-#if GCC_VERSION >= 40500
/*
* Mark a position in code as unreachable. This can be used to
* suppress control flow warnings after asm blocks that transfer
* control elsewhere.
- *
- * Early snapshots of gcc 4.5 don't support this and we can't detect
- * this in the preprocessor, but we can live with this because they're
- * unreleased. Really, we need to have autoconf for the kernel.
- */
-#define unreachable() __builtin_unreachable()
-
-/* Mark a function definition as prohibited from being cloned. */
-#define __noclone __attribute__((__noclone__))
-
-#endif /* GCC_VERSION >= 40500 */
-
-#if GCC_VERSION >= 40600
-/*
- * When used with Link Time Optimization, gcc can optimize away C functions or
- * variables which are referenced only from assembly code. __visible tells the
- * optimizer that something else uses this function or variable, thus preventing
- * this.
*/
-#define __visible __attribute__((externally_visible))
-#endif
-
+#define unreachable() \
+ do { \
+ annotate_unreachable(); \
+ barrier_before_unreachable(); \
+ __builtin_unreachable(); \
+ } while (0)
-#if GCC_VERSION >= 40900 && !defined(__CHECKER__)
-/*
- * __assume_aligned(n, k): Tell the optimizer that the returned
- * pointer can be assumed to be k modulo n. The second argument is
- * optional (default 0), so we use a variadic macro to make the
- * shorthand.
- *
- * Beware: Do not apply this to functions which may return
- * ERR_PTRs. Also, it is probably unwise to apply it to functions
- * returning extra information in the low bits (but in that case the
- * compiler should see some alignment anyway, when the return value is
- * massaged by 'flags = ptr & 3; ptr &= ~3;').
- */
-#define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
+#if defined(RANDSTRUCT_PLUGIN) && !defined(__CHECKER__)
+#define __randomize_layout __attribute__((randomize_layout))
+#define __no_randomize_layout __attribute__((no_randomize_layout))
+/* This anon struct can add padding, so only enable it under randstruct. */
+#define randomized_struct_fields_start struct {
+#define randomized_struct_fields_end } __randomize_layout;
#endif
/*
*/
#define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0)
-#ifdef CONFIG_ARCH_USE_BUILTIN_BSWAP
-#if GCC_VERSION >= 40400
+/*
+ * sparse (__CHECKER__) pretends to be gcc, but can't do constant
+ * folding in __builtin_bswap*() (yet), so don't set these for it.
+ */
+#if defined(CONFIG_ARCH_USE_BUILTIN_BSWAP) && !defined(__CHECKER__)
#define __HAVE_BUILTIN_BSWAP32__
#define __HAVE_BUILTIN_BSWAP64__
-#endif
-#if GCC_VERSION >= 40800 || (defined(__powerpc__) && GCC_VERSION >= 40600)
+#if GCC_VERSION >= 40800
#define __HAVE_BUILTIN_BSWAP16__
#endif
-#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
+#endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP && !__CHECKER__ */
-#if GCC_VERSION >= 50000
+#if GCC_VERSION >= 70000
+#define KASAN_ABI_VERSION 5
+#elif GCC_VERSION >= 50000
#define KASAN_ABI_VERSION 4
#elif GCC_VERSION >= 40902
#define KASAN_ABI_VERSION 3
#endif
-#if GCC_VERSION >= 40902
-/*
- * Tell the compiler that address safety instrumentation (KASAN)
- * should not be applied to that function.
- * Conflicts with inlining: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
- */
+#if __has_attribute(__no_sanitize_address__)
#define __no_sanitize_address __attribute__((no_sanitize_address))
+#else
+#define __no_sanitize_address
#endif
-#endif /* gcc version >= 40000 specific checks */
-
-#if !defined(__noclone)
-#define __noclone /* not needed */
-#endif
-
-#if !defined(__no_sanitize_address)
-#define __no_sanitize_address
+#if GCC_VERSION >= 50100
+#define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1
#endif
/*
- * A trick to suppress uninitialized variable warning without generating any
- * code
+ * Turn individual warnings and errors on and off locally, depending
+ * on version.
*/
-#define uninitialized_var(x) x = x
+#define __diag_GCC(version, severity, s) \
+ __diag_GCC_ ## version(__diag_GCC_ ## severity s)
+
+/* Severity used in pragma directives */
+#define __diag_GCC_ignore ignored
+#define __diag_GCC_warn warning
+#define __diag_GCC_error error
+
+#define __diag_str1(s) #s
+#define __diag_str(s) __diag_str1(s)
+#define __diag(s) _Pragma(__diag_str(GCC diagnostic s))
+
+#if GCC_VERSION >= 80000
+#define __diag_GCC_8(s) __diag(s)
+#else
+#define __diag_GCC_8(s)
+#endif
+
+#define __no_fgcse __attribute__((optimize("-fno-gcse")))
-#ifndef __LINUX_COMPILER_H
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
#error "Please don't include <linux/compiler-intel.h> directly, include <linux/compiler.h> instead."
#endif
#ifdef __ECC
-/* Some compiler specific definitions are overwritten here
- * for Intel ECC compiler
- */
+/* Compiler specific definitions for Intel ECC compiler */
#include <asm/intrinsics.h>
/* Intel ECC compiler doesn't support gcc specific asm stmts.
* It uses intrinsics to do the equivalent things.
*/
-#undef barrier
-#undef barrier_data
-#undef RELOC_HIDE
-#undef OPTIMIZER_HIDE_VAR
#define barrier() __memory_barrier()
#define barrier_data(ptr) barrier()
*/
#define OPTIMIZER_HIDE_VAR(var) barrier()
-/* Intel ECC compiler doesn't support __builtin_types_compatible_p() */
-#define __must_be_array(a) 0
-
#endif
-#ifndef __HAVE_BUILTIN_BSWAP16__
/* icc has this, but it's called _bswap16 */
#define __HAVE_BUILTIN_BSWAP16__
#define __builtin_bswap16 _bswap16
-#endif
-
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __LINUX_COMPILER_H
#define __LINUX_COMPILER_H
-#ifndef __ASSEMBLY__
+#include <linux/compiler_types.h>
-#ifdef __CHECKER__
-# define __user __attribute__((noderef, address_space(1)))
-# define __kernel __attribute__((address_space(0)))
-# define __safe __attribute__((safe))
-# define __force __attribute__((force))
-# define __nocast __attribute__((nocast))
-# define __iomem __attribute__((noderef, address_space(2)))
-# define __must_hold(x) __attribute__((context(x,1,1)))
-# define __acquires(x) __attribute__((context(x,0,1)))
-# define __releases(x) __attribute__((context(x,1,0)))
-# define __acquire(x) __context__(x,1)
-# define __release(x) __context__(x,-1)
-# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
-# define __percpu __attribute__((noderef, address_space(3)))
-# define __pmem __attribute__((noderef, address_space(5)))
-#ifdef CONFIG_SPARSE_RCU_POINTER
-# define __rcu __attribute__((noderef, address_space(4)))
-#else
-# define __rcu
-#endif
-extern void __chk_user_ptr(const volatile void __user *);
-extern void __chk_io_ptr(const volatile void __iomem *);
-#else
-# define __user
-# define __kernel
-# define __safe
-# define __force
-# define __nocast
-# define __iomem
-# define __chk_user_ptr(x) (void)0
-# define __chk_io_ptr(x) (void)0
-# define __builtin_warning(x, y...) (1)
-# define __must_hold(x)
-# define __acquires(x)
-# define __releases(x)
-# define __acquire(x) (void)0
-# define __release(x) (void)0
-# define __cond_lock(x,c) (c)
-# define __percpu
-# define __rcu
-# define __pmem
-#endif
-
-/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
-#define ___PASTE(a,b) a##b
-#define __PASTE(a,b) ___PASTE(a,b)
+#ifndef __ASSEMBLY__
#ifdef __KERNEL__
-#ifdef __GNUC__
-#include <linux/compiler-gcc.h>
-#endif
-
-#if defined(CC_USING_HOTPATCH) && !defined(__CHECKER__)
-#define notrace __attribute__((hotpatch(0,0)))
-#else
-#define notrace __attribute__((no_instrument_function))
-#endif
-
-/* Intel compiler defines __GNUC__. So we will overwrite implementations
- * coming from above header files here
- */
-#ifdef __INTEL_COMPILER
-# include <linux/compiler-intel.h>
-#endif
-
-/* Clang compiler defines __GNUC__. So we will overwrite implementations
- * coming from above header files here
- */
-#ifdef __clang__
-#include <linux/compiler-clang.h>
-#endif
-
-/*
- * Generic compiler-dependent macros required for kernel
- * build go below this comment. Actual compiler/compiler version
- * specific implementations come from the above header files
- */
-
-struct ftrace_branch_data {
- const char *func;
- const char *file;
- unsigned line;
- union {
- struct {
- unsigned long correct;
- unsigned long incorrect;
- };
- struct {
- unsigned long miss;
- unsigned long hit;
- };
- unsigned long miss_hit[2];
- };
-};
-
/*
* Note: DISABLE_BRANCH_PROFILING can be used by special lowlevel code
* to disable branch tracing on a per file basis.
*/
#if defined(CONFIG_TRACE_BRANCH_PROFILING) \
&& !defined(DISABLE_BRANCH_PROFILING) && !defined(__CHECKER__)
-void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
+void ftrace_likely_update(struct ftrace_likely_data *f, int val,
+ int expect, int is_constant);
#define likely_notrace(x) __builtin_expect(!!(x), 1)
#define unlikely_notrace(x) __builtin_expect(!!(x), 0)
-#define __branch_check__(x, expect) ({ \
- int ______r; \
- static struct ftrace_branch_data \
- __attribute__((__aligned__(4))) \
- __attribute__((section("_ftrace_annotated_branch"))) \
+#define __branch_check__(x, expect, is_constant) ({ \
+ long ______r; \
+ static struct ftrace_likely_data \
+ __aligned(4) \
+ __section(_ftrace_annotated_branch) \
______f = { \
- .func = __func__, \
- .file = __FILE__, \
- .line = __LINE__, \
+ .data.func = __func__, \
+ .data.file = __FILE__, \
+ .data.line = __LINE__, \
}; \
- ______r = likely_notrace(x); \
- ftrace_likely_update(&______f, ______r, expect); \
+ ______r = __builtin_expect(!!(x), expect); \
+ ftrace_likely_update(&______f, ______r, \
+ expect, is_constant); \
______r; \
})
* written by Daniel Walker.
*/
# ifndef likely
-# define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
+# define likely(x) (__branch_check__(x, 1, __builtin_constant_p(x)))
# endif
# ifndef unlikely
-# define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
+# define unlikely(x) (__branch_check__(x, 0, __builtin_constant_p(x)))
# endif
#ifdef CONFIG_PROFILE_ALL_BRANCHES
* "Define 'is'", Bill Clinton
* "Define 'if'", Steven Rostedt
*/
-#define if(cond, ...) __trace_if( (cond , ## __VA_ARGS__) )
-#define __trace_if(cond) \
- if (__builtin_constant_p(!!(cond)) ? !!(cond) : \
- ({ \
- int ______r; \
- static struct ftrace_branch_data \
- __attribute__((__aligned__(4))) \
- __attribute__((section("_ftrace_branch"))) \
- ______f = { \
- .func = __func__, \
- .file = __FILE__, \
- .line = __LINE__, \
- }; \
- ______r = !!(cond); \
- ______f.miss_hit[______r]++; \
- ______r; \
- }))
+#define if(cond, ...) if ( __trace_if_var( !!(cond , ## __VA_ARGS__) ) )
+
+#define __trace_if_var(cond) (__builtin_constant_p(cond) ? (cond) : __trace_if_value(cond))
+
+#define __trace_if_value(cond) ({ \
+ static struct ftrace_branch_data \
+ __aligned(4) \
+ __section(_ftrace_branch) \
+ __if_trace = { \
+ .func = __func__, \
+ .file = __FILE__, \
+ .line = __LINE__, \
+ }; \
+ (cond) ? \
+ (__if_trace.miss_hit[1]++,1) : \
+ (__if_trace.miss_hit[0]++,0); \
+})
+
#endif /* CONFIG_PROFILE_ALL_BRANCHES */
#else
# define barrier_data(ptr) barrier()
#endif
+/* workaround for GCC PR82365 if needed */
+#ifndef barrier_before_unreachable
+# define barrier_before_unreachable() do { } while (0)
+#endif
+
/* Unreachable code */
+#ifdef CONFIG_STACK_VALIDATION
+/*
+ * These macros help objtool understand GCC code flow for unreachable code.
+ * The __COUNTER__ based labels are a hack to make each instance of the macros
+ * unique, to convince GCC not to merge duplicate inline asm statements.
+ */
+#define annotate_reachable() ({ \
+ asm volatile("%c0:\n\t" \
+ ".pushsection .discard.reachable\n\t" \
+ ".long %c0b - .\n\t" \
+ ".popsection\n\t" : : "i" (__COUNTER__)); \
+})
+#define annotate_unreachable() ({ \
+ asm volatile("%c0:\n\t" \
+ ".pushsection .discard.unreachable\n\t" \
+ ".long %c0b - .\n\t" \
+ ".popsection\n\t" : : "i" (__COUNTER__)); \
+})
+#define ASM_UNREACHABLE \
+ "999:\n\t" \
+ ".pushsection .discard.unreachable\n\t" \
+ ".long 999b - .\n\t" \
+ ".popsection\n\t"
+
+/* Annotate a C jump table to allow objtool to follow the code flow */
+#define __annotate_jump_table __section(.rodata..c_jump_table)
+
+#else
+#define annotate_reachable()
+#define annotate_unreachable()
+#define __annotate_jump_table
+#endif
+
+#ifndef ASM_UNREACHABLE
+# define ASM_UNREACHABLE
+#endif
#ifndef unreachable
-# define unreachable() do { } while (1)
+# define unreachable() do { \
+ annotate_unreachable(); \
+ __builtin_unreachable(); \
+} while (0)
+#endif
+
+/*
+ * KENTRY - kernel entry point
+ * This can be used to annotate symbols (functions or data) that are used
+ * without their linker symbol being referenced explicitly. For example,
+ * interrupt vector handlers, or functions in the kernel image that are found
+ * programatically.
+ *
+ * Not required for symbols exported with EXPORT_SYMBOL, or initcalls. Those
+ * are handled in their own way (with KEEP() in linker scripts).
+ *
+ * KENTRY can be avoided if the symbols in question are marked as KEEP() in the
+ * linker script. For example an architecture could KEEP() its entire
+ * boot/exception vector code rather than annotate each function and data.
+ */
+#ifndef KENTRY
+# define KENTRY(sym) \
+ extern typeof(sym) sym; \
+ static const unsigned long __kentry_##sym \
+ __used \
+ __section("___kentry" "+" #sym ) \
+ = (unsigned long)&sym;
#endif
#ifndef RELOC_HIDE
#endif
#ifndef OPTIMIZER_HIDE_VAR
-#define OPTIMIZER_HIDE_VAR(var) barrier()
+/* Make the optimizer believe the variable can be manipulated arbitrarily. */
+#define OPTIMIZER_HIDE_VAR(var) \
+ __asm__ ("" : "=r" (var) : "0" (var))
#endif
/* Not-quite-unique ID. */
#ifdef CONFIG_KASAN
/*
- * This function is not 'inline' because __no_sanitize_address confilcts
+ * We can't declare function 'inline' because __no_sanitize_address confilcts
* with inlining. Attempt to inline it may cause a build failure.
* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67368
* '__maybe_unused' allows us to avoid defined-but-not-used warnings.
*/
-static __no_sanitize_address __maybe_unused
-void __read_once_size_nocheck(const volatile void *p, void *res, int size)
-{
- __READ_ONCE_SIZE;
-}
+# define __no_kasan_or_inline __no_sanitize_address notrace __maybe_unused
#else
-static __always_inline
+# define __no_kasan_or_inline __always_inline
+#endif
+
+static __no_kasan_or_inline
void __read_once_size_nocheck(const volatile void *p, void *res, int size)
{
__READ_ONCE_SIZE;
}
-#endif
static __always_inline void __write_once_size(volatile void *p, void *res, int size)
{
/*
* Prevent the compiler from merging or refetching reads or writes. The
* compiler is also forbidden from reordering successive instances of
- * READ_ONCE, WRITE_ONCE and ACCESS_ONCE (see below), but only when the
- * compiler is aware of some particular ordering. One way to make the
- * compiler aware of ordering is to put the two invocations of READ_ONCE,
- * WRITE_ONCE or ACCESS_ONCE() in different C statements.
+ * READ_ONCE and WRITE_ONCE, but only when the compiler is aware of some
+ * particular ordering. One way to make the compiler aware of ordering is to
+ * put the two invocations of READ_ONCE or WRITE_ONCE in different C
+ * statements.
*
- * In contrast to ACCESS_ONCE these two macros will also work on aggregate
- * data types like structs or unions. If the size of the accessed data
- * type exceeds the word size of the machine (e.g., 32 bits or 64 bits)
- * READ_ONCE() and WRITE_ONCE() will fall back to memcpy and print a
- * compile-time warning.
+ * These two macros will also work on aggregate data types like structs or
+ * unions. If the size of the accessed data type exceeds the word size of
+ * the machine (e.g., 32 bits or 64 bits) READ_ONCE() and WRITE_ONCE() will
+ * fall back to memcpy(). There's at least two memcpy()s: one for the
+ * __builtin_memcpy() and then one for the macro doing the copy of variable
+ * - '__u' allocated on the stack.
*
* Their two major use cases are: (1) Mediating communication between
* process-level code and irq/NMI handlers, all running on the same CPU,
- * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
+ * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
* mutilate accesses that either do not require ordering or that interact
* with an explicit memory barrier or atomic instruction that provides the
* required ordering.
*/
#define READ_ONCE_NOCHECK(x) __READ_ONCE(x, 0)
+static __no_kasan_or_inline
+unsigned long read_word_at_a_time(const void *addr)
+{
+ return *(unsigned long *)addr;
+}
+
#define WRITE_ONCE(x, val) \
({ \
union { typeof(x) __val; char __c[1]; } __u = \
__u.__val; \
})
-/**
- * smp_cond_acquire() - Spin wait for cond with ACQUIRE ordering
- * @cond: boolean expression to wait for
- *
- * Equivalent to using smp_load_acquire() on the condition variable but employs
- * the control dependency of the wait to reduce the barrier on many platforms.
- *
- * The control dependency provides a LOAD->STORE order, the additional RMB
- * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order,
- * aka. ACQUIRE.
- */
-#define smp_cond_acquire(cond) do { \
- while (!(cond)) \
- cpu_relax(); \
- smp_rmb(); /* ctrl + rmb := acquire */ \
-} while (0)
-
-#endif /* __KERNEL__ */
-
-#endif /* __ASSEMBLY__ */
-
-#ifdef __KERNEL__
-/*
- * Allow us to mark functions as 'deprecated' and have gcc emit a nice
- * warning for each use, in hopes of speeding the functions removal.
- * Usage is:
- * int __deprecated foo(void)
- */
-#ifndef __deprecated
-# define __deprecated /* unimplemented */
-#endif
-
-#ifdef MODULE
-#define __deprecated_for_modules __deprecated
-#else
-#define __deprecated_for_modules
-#endif
-
-#ifndef __must_check
-#define __must_check
-#endif
-
-#ifndef CONFIG_ENABLE_MUST_CHECK
-#undef __must_check
-#define __must_check
-#endif
-#ifndef CONFIG_ENABLE_WARN_DEPRECATED
-#undef __deprecated
-#undef __deprecated_for_modules
-#define __deprecated
-#define __deprecated_for_modules
-#endif
-
-/*
- * Allow us to avoid 'defined but not used' warnings on functions and data,
- * as well as force them to be emitted to the assembly file.
- *
- * As of gcc 3.4, static functions that are not marked with attribute((used))
- * may be elided from the assembly file. As of gcc 3.4, static data not so
- * marked will not be elided, but this may change in a future gcc version.
- *
- * NOTE: Because distributions shipped with a backported unit-at-a-time
- * compiler in gcc 3.3, we must define __used to be __attribute__((used))
- * for gcc >=3.3 instead of 3.4.
- *
- * In prior versions of gcc, such functions and data would be emitted, but
- * would be warned about except with attribute((unused)).
- *
- * Mark functions that are referenced only in inline assembly as __used so
- * the code is emitted even though it appears to be unreferenced.
- */
-#ifndef __used
-# define __used /* unimplemented */
-#endif
-
-#ifndef __maybe_unused
-# define __maybe_unused /* unimplemented */
-#endif
-
-#ifndef __always_unused
-# define __always_unused /* unimplemented */
-#endif
-
-#ifndef noinline
-#define noinline
-#endif
-
-/*
- * Rather then using noinline to prevent stack consumption, use
- * noinline_for_stack instead. For documentation reasons.
- */
-#define noinline_for_stack noinline
-
-#ifndef __always_inline
-#define __always_inline inline
-#endif
-
#endif /* __KERNEL__ */
/*
- * From the GCC manual:
- *
- * Many functions do not examine any values except their arguments,
- * and have no effects except the return value. Basically this is
- * just slightly more strict class than the `pure' attribute above,
- * since function is not allowed to read global memory.
- *
- * Note that a function that has pointer arguments and examines the
- * data pointed to must _not_ be declared `const'. Likewise, a
- * function that calls a non-`const' function usually must not be
- * `const'. It does not make sense for a `const' function to return
- * `void'.
- */
-#ifndef __attribute_const__
-# define __attribute_const__ /* unimplemented */
-#endif
-
-/*
- * Tell gcc if a function is cold. The compiler will assume any path
- * directly leading to the call is unlikely.
+ * Force the compiler to emit 'sym' as a symbol, so that we can reference
+ * it from inline assembler. Necessary in case 'sym' could be inlined
+ * otherwise, or eliminated entirely due to lack of references that are
+ * visible to the compiler.
*/
+#define __ADDRESSABLE(sym) \
+ static void * __section(.discard.addressable) __used \
+ __PASTE(__addressable_##sym, __LINE__) = (void *)&sym;
-#ifndef __cold
-#define __cold
-#endif
-
-/* Simple shorthand for a section definition */
-#ifndef __section
-# define __section(S) __attribute__ ((__section__(#S)))
-#endif
-
-#ifndef __visible
-#define __visible
-#endif
-
-/*
- * Assume alignment of return value.
+/**
+ * offset_to_ptr - convert a relative memory offset to an absolute pointer
+ * @off: the address of the 32-bit offset value
*/
-#ifndef __assume_aligned
-#define __assume_aligned(a, ...)
-#endif
-
-
-/* Are two types/vars the same type (ignoring qualifiers)? */
-#ifndef __same_type
-# define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
-#endif
+static inline void *offset_to_ptr(const int *off)
+{
+ return (void *)((unsigned long)off + *off);
+}
-/* Is this type a native word size -- useful for atomic operations */
-#ifndef __native_word
-# define __native_word(t) (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
-#endif
+#endif /* __ASSEMBLY__ */
/* Compile time object size, -1 for unknown */
#ifndef __compiletime_object_size
#endif
#ifndef __compiletime_error
# define __compiletime_error(message)
-/*
- * Sparse complains of variable sized arrays due to the temporary variable in
- * __compiletime_assert. Unfortunately we can't just expand it out to make
- * sparse see a constant array size without breaking compiletime_assert on old
- * versions of GCC (e.g. 4.2.4), so hide the array from sparse altogether.
- */
-# ifndef __CHECKER__
-# define __compiletime_error_fallback(condition) \
- do { ((void)sizeof(char[1 - 2 * condition])); } while (0)
-# endif
-#endif
-#ifndef __compiletime_error_fallback
-# define __compiletime_error_fallback(condition) do { } while (0)
#endif
#ifdef __OPTIMIZE__
# define __compiletime_assert(condition, msg, prefix, suffix) \
do { \
- bool __cond = !(condition); \
extern void prefix ## suffix(void) __compiletime_error(msg); \
- if (__cond) \
+ if (!(condition)) \
prefix ## suffix(); \
- __compiletime_error_fallback(__cond); \
} while (0)
#else
# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0)
* compiler has support to do so.
*/
#define compiletime_assert(condition, msg) \
- _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
+ _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
#define compiletime_assert_atomic_type(t) \
compiletime_assert(__native_word(t), \
"Need native word sized stores/loads for atomicity.")
-/*
- * Prevent the compiler from merging or refetching accesses. The compiler
- * is also forbidden from reordering successive instances of ACCESS_ONCE(),
- * but only when the compiler is aware of some particular ordering. One way
- * to make the compiler aware of ordering is to put the two invocations of
- * ACCESS_ONCE() in different C statements.
- *
- * ACCESS_ONCE will only work on scalar types. For union types, ACCESS_ONCE
- * on a union member will work as long as the size of the member matches the
- * size of the union and the size is smaller than word size.
- *
- * The major use cases of ACCESS_ONCE used to be (1) Mediating communication
- * between process-level code and irq/NMI handlers, all running on the same CPU,
- * and (2) Ensuring that the compiler does not fold, spindle, or otherwise
- * mutilate accesses that either do not require ordering or that interact
- * with an explicit memory barrier or atomic instruction that provides the
- * required ordering.
- *
- * If possible use READ_ONCE()/WRITE_ONCE() instead.
- */
-#define __ACCESS_ONCE(x) ({ \
- __maybe_unused typeof(x) __var = (__force typeof(x)) 0; \
- (volatile typeof(x) *)&(x); })
-#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x))
-
-/**
- * lockless_dereference() - safely load a pointer for later dereference
- * @p: The pointer to load
- *
- * Similar to rcu_dereference(), but for situations where the pointed-to
- * object's lifetime is managed by something other than RCU. That
- * "something other" might be reference counting or simple immortality.
- */
-#define lockless_dereference(p) \
-({ \
- typeof(p) _________p1 = READ_ONCE(p); \
- smp_read_barrier_depends(); /* Dependency order vs. p above. */ \
- (_________p1); \
-})
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
-/* Ignore/forbid kprobes attach on very low level functions marked by this attribute: */
-#ifdef CONFIG_KPROBES
-# define __kprobes __attribute__((__section__(".kprobes.text")))
-# define nokprobe_inline __always_inline
-#else
-# define __kprobes
-# define nokprobe_inline inline
-#endif
#endif /* __LINUX_COMPILER_H */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_ATTRIBUTES_H
+#define __LINUX_COMPILER_ATTRIBUTES_H
+
+/*
+ * The attributes in this file are unconditionally defined and they directly
+ * map to compiler attribute(s), unless one of the compilers does not support
+ * the attribute. In that case, __has_attribute is used to check for support
+ * and the reason is stated in its comment ("Optional: ...").
+ *
+ * Any other "attributes" (i.e. those that depend on a configuration option,
+ * on a compiler, on an architecture, on plugins, on other attributes...)
+ * should be defined elsewhere (e.g. compiler_types.h or compiler-*.h).
+ * The intention is to keep this file as simple as possible, as well as
+ * compiler- and version-agnostic (e.g. avoiding GCC_VERSION checks).
+ *
+ * This file is meant to be sorted (by actual attribute name,
+ * not by #define identifier). Use the __attribute__((__name__)) syntax
+ * (i.e. with underscores) to avoid future collisions with other macros.
+ * Provide links to the documentation of each supported compiler, if it exists.
+ */
+
+/*
+ * __has_attribute is supported on gcc >= 5, clang >= 2.9 and icc >= 17.
+ * In the meantime, to support 4.6 <= gcc < 5, we implement __has_attribute
+ * by hand.
+ *
+ * sparse does not support __has_attribute (yet) and defines __GNUC_MINOR__
+ * depending on the compiler used to build it; however, these attributes have
+ * no semantic effects for sparse, so it does not matter. Also note that,
+ * in order to avoid sparse's warnings, even the unsupported ones must be
+ * defined to 0.
+ */
+#ifndef __has_attribute
+# define __has_attribute(x) __GCC4_has_attribute_##x
+# define __GCC4_has_attribute___assume_aligned__ (__GNUC_MINOR__ >= 9)
+# define __GCC4_has_attribute___copy__ 0
+# define __GCC4_has_attribute___designated_init__ 0
+# define __GCC4_has_attribute___externally_visible__ 1
+# define __GCC4_has_attribute___noclone__ 1
+# define __GCC4_has_attribute___nonstring__ 0
+# define __GCC4_has_attribute___no_sanitize_address__ (__GNUC_MINOR__ >= 8)
+# define __GCC4_has_attribute___fallthrough__ 0
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alias-function-attribute
+ */
+#define __alias(symbol) __attribute__((__alias__(#symbol)))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-aligned-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-aligned-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-aligned-variable-attribute
+ */
+#define __aligned(x) __attribute__((__aligned__(x)))
+#define __aligned_largest __attribute__((__aligned__))
+
+/*
+ * Note: users of __always_inline currently do not write "inline" themselves,
+ * which seems to be required by gcc to apply the attribute according
+ * to its docs (and also "warning: always_inline function might not be
+ * inlinable [-Wattributes]" is emitted).
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-always_005finline-function-attribute
+ * clang: mentioned
+ */
+#define __always_inline inline __attribute__((__always_inline__))
+
+/*
+ * The second argument is optional (default 0), so we use a variadic macro
+ * to make the shorthand.
+ *
+ * Beware: Do not apply this to functions which may return
+ * ERR_PTRs. Also, it is probably unwise to apply it to functions
+ * returning extra information in the low bits (but in that case the
+ * compiler should see some alignment anyway, when the return value is
+ * massaged by 'flags = ptr & 3; ptr &= ~3;').
+ *
+ * Optional: only supported since gcc >= 4.9
+ * Optional: not supported by icc
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-assume_005faligned-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#assume-aligned
+ */
+#if __has_attribute(__assume_aligned__)
+# define __assume_aligned(a, ...) __attribute__((__assume_aligned__(a, ## __VA_ARGS__)))
+#else
+# define __assume_aligned(a, ...)
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-cold-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-cold-label-attribute
+ */
+#define __cold __attribute__((__cold__))
+
+/*
+ * Note the long name.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute
+ */
+#define __attribute_const__ __attribute__((__const__))
+
+/*
+ * Optional: only supported since gcc >= 9
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
+ */
+#if __has_attribute(__copy__)
+# define __copy(symbol) __attribute__((__copy__(symbol)))
+#else
+# define __copy(symbol)
+#endif
+
+/*
+ * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
+ * attribute warnings entirely and for good") for more information.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-deprecated-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-deprecated-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-deprecated-variable-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Enumerator-Attributes.html#index-deprecated-enumerator-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#deprecated
+ */
+#define __deprecated
+
+/*
+ * Optional: only supported since gcc >= 5.1
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-designated_005finit-type-attribute
+ */
+#if __has_attribute(__designated_init__)
+# define __designated_init __attribute__((__designated_init__))
+#else
+# define __designated_init
+#endif
+
+/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-externally_005fvisible-function-attribute
+ */
+#if __has_attribute(__externally_visible__)
+# define __visible __attribute__((__externally_visible__))
+#else
+# define __visible
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-format-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#format
+ */
+#define __printf(a, b) __attribute__((__format__(printf, a, b)))
+#define __scanf(a, b) __attribute__((__format__(scanf, a, b)))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-gnu_005finline-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#gnu-inline
+ */
+#define __gnu_inline __attribute__((__gnu_inline__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-malloc-function-attribute
+ */
+#define __malloc __attribute__((__malloc__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-mode-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-mode-variable-attribute
+ */
+#define __mode(x) __attribute__((__mode__(x)))
+
+/*
+ * Optional: not supported by clang
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noclone-function-attribute
+ */
+#if __has_attribute(__noclone__)
+# define __noclone __attribute__((__noclone__))
+#else
+# define __noclone
+#endif
+
+/*
+ * Add the pseudo keyword 'fallthrough' so case statement blocks
+ * must end with any of these keywords:
+ * break;
+ * fallthrough;
+ * goto <label>;
+ * return [expression];
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
+ */
+#if __has_attribute(__fallthrough__)
+# define fallthrough __attribute__((__fallthrough__))
+#else
+# define fallthrough do {} while (0) /* fallthrough */
+#endif
+
+/*
+ * Note the missing underscores.
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noinline-function-attribute
+ * clang: mentioned
+ */
+#define noinline __attribute__((__noinline__))
+
+/*
+ * Optional: only supported since gcc >= 8
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-nonstring-variable-attribute
+ */
+#if __has_attribute(__nonstring__)
+# define __nonstring __attribute__((__nonstring__))
+#else
+# define __nonstring
+#endif
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-noreturn-function-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#noreturn
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#id1
+ */
+#define __noreturn __attribute__((__noreturn__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-packed-type-attribute
+ * clang: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-packed-variable-attribute
+ */
+#define __packed __attribute__((__packed__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute
+ */
+#define __pure __attribute__((__pure__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#section-declspec-allocate
+ */
+#define __section(S) __attribute__((__section__(#S)))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-unused-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html#index-unused-type-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-unused-variable-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Label-Attributes.html#index-unused-label-attribute
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#maybe-unused-unused
+ */
+#define __always_unused __attribute__((__unused__))
+#define __maybe_unused __attribute__((__unused__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-used-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-used-variable-attribute
+ */
+#define __used __attribute__((__used__))
+
+/*
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute
+ * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-weak-variable-attribute
+ */
+#define __weak __attribute__((__weak__))
+
+#endif /* __LINUX_COMPILER_ATTRIBUTES_H */
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
+#define __LINUX_COMPILER_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef __CHECKER__
+# define __user __attribute__((noderef, address_space(1)))
+# define __kernel __attribute__((address_space(0)))
+# define __safe __attribute__((safe))
+# define __force __attribute__((force))
+# define __nocast __attribute__((nocast))
+# define __iomem __attribute__((noderef, address_space(2)))
+# define __must_hold(x) __attribute__((context(x,1,1)))
+# define __acquires(x) __attribute__((context(x,0,1)))
+# define __releases(x) __attribute__((context(x,1,0)))
+# define __acquire(x) __context__(x,1)
+# define __release(x) __context__(x,-1)
+# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
+# define __percpu __attribute__((noderef, address_space(3)))
+# define __rcu __attribute__((noderef, address_space(4)))
+# define __private __attribute__((noderef))
+extern void __chk_user_ptr(const volatile void __user *);
+extern void __chk_io_ptr(const volatile void __iomem *);
+# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
+#else /* __CHECKER__ */
+# ifdef STRUCTLEAK_PLUGIN
+# define __user __attribute__((user))
+# else
+# define __user
+# endif
+# define __kernel
+# define __safe
+# define __force
+# define __nocast
+# define __iomem
+# define __chk_user_ptr(x) (void)0
+# define __chk_io_ptr(x) (void)0
+# define __builtin_warning(x, y...) (1)
+# define __must_hold(x)
+# define __acquires(x)
+# define __releases(x)
+# define __acquire(x) (void)0
+# define __release(x) (void)0
+# define __cond_lock(x,c) (c)
+# define __percpu
+# define __rcu
+# define __private
+# define ACCESS_PRIVATE(p, member) ((p)->member)
+#endif /* __CHECKER__ */
+
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a,b) a##b
+#define __PASTE(a,b) ___PASTE(a,b)
+
+#ifdef __KERNEL__
+
+/* Attributes */
+#include <linux/compiler_attributes.h>
+
+/* Compiler specific macros. */
+#ifdef __clang__
+#include <linux/compiler-clang.h>
+#elif defined(__INTEL_COMPILER)
+#include <linux/compiler-intel.h>
+#elif defined(__GNUC__)
+/* The above compilers also define __GNUC__, so order is important here. */
+#include <linux/compiler-gcc.h>
+#else
+#error "Unknown compiler"
+#endif
+
+/*
+ * Some architectures need to provide custom definitions of macros provided
+ * by linux/compiler-*.h, and can do so using asm/compiler.h. We include that
+ * conditionally rather than using an asm-generic wrapper in order to avoid
+ * build failures if any C compilation, which will include this file via an
+ * -include argument in c_flags, occurs prior to the asm-generic wrappers being
+ * generated.
+ */
+#ifdef CONFIG_HAVE_ARCH_COMPILER_H
+#include <asm/compiler.h>
+#endif
+
+struct ftrace_branch_data {
+ const char *func;
+ const char *file;
+ unsigned line;
+ union {
+ struct {
+ unsigned long correct;
+ unsigned long incorrect;
+ };
+ struct {
+ unsigned long miss;
+ unsigned long hit;
+ };
+ unsigned long miss_hit[2];
+ };
+};
+
+struct ftrace_likely_data {
+ struct ftrace_branch_data data;
+ unsigned long constant;
+};
+
+#ifdef CONFIG_ENABLE_MUST_CHECK
+#define __must_check __attribute__((__warn_unused_result__))
+#else
+#define __must_check
+#endif
+
+#if defined(CC_USING_HOTPATCH)
+#define notrace __attribute__((hotpatch(0, 0)))
+#elif defined(CC_USING_PATCHABLE_FUNCTION_ENTRY)
+#define notrace __attribute__((patchable_function_entry(0, 0)))
+#else
+#define notrace __attribute__((__no_instrument_function__))
+#endif
+
+/*
+ * it doesn't make sense on ARM (currently the only user of __naked)
+ * to trace naked functions because then mcount is called without
+ * stack and frame pointer being set up and there is no chance to
+ * restore the lr register to the value before mcount was called.
+ */
+#define __naked __attribute__((__naked__)) notrace
+
+#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
+
+/*
+ * Force always-inline if the user requests it so via the .config.
+ * Prefer gnu_inline, so that extern inline functions do not emit an
+ * externally visible function. This makes extern inline behave as per gnu89
+ * semantics rather than c99. This prevents multiple symbol definition errors
+ * of extern inline functions at link time.
+ * A lot of inline functions can cause havoc with function tracing.
+ * Do not use __always_inline here, since currently it expands to inline again
+ * (which would break users of __always_inline).
+ */
+#if !CONFIG_IS_ENABLED(OPTIMIZE_INLINING)
+#define inline inline __attribute__((__always_inline__)) __gnu_inline \
+ __inline_maybe_unused notrace
+#else
+#define inline inline __gnu_inline \
+ __inline_maybe_unused notrace
+#endif
+
+/*
+ * gcc provides both __inline__ and __inline as alternate spellings of
+ * the inline keyword, though the latter is undocumented. New kernel
+ * code should only use the inline spelling, but some existing code
+ * uses __inline__. Since we #define inline above, to ensure
+ * __inline__ has the same semantics, we need this #define.
+ *
+ * However, the spelling __inline is strictly reserved for referring
+ * to the bare keyword.
+ */
+#define __inline__ inline
+
+/*
+ * GCC does not warn about unused static inline functions for -Wunused-function.
+ * Suppress the warning in clang as well by using __maybe_unused, but enable it
+ * for W=1 build. This will allow clang to find unused functions. Remove the
+ * __inline_maybe_unused entirely after fixing most of -Wunused-function warnings.
+ */
+#ifdef KBUILD_EXTRA_WARN1
+#define __inline_maybe_unused
+#else
+#define __inline_maybe_unused __maybe_unused
+#endif
+
+/*
+ * Rather then using noinline to prevent stack consumption, use
+ * noinline_for_stack instead. For documentation reasons.
+ */
+#define noinline_for_stack noinline
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The below symbols may be defined for one or more, but not ALL, of the above
+ * compilers. We don't consider that to be an error, so set them to nothing.
+ * For example, some of them are for compiler specific plugins.
+ */
+#ifndef __latent_entropy
+# define __latent_entropy
+#endif
+
+#ifndef __randomize_layout
+# define __randomize_layout __designated_init
+#endif
+
+#ifndef __no_randomize_layout
+# define __no_randomize_layout
+#endif
+
+#ifndef randomized_struct_fields_start
+# define randomized_struct_fields_start
+# define randomized_struct_fields_end
+#endif
+
+#ifndef asm_volatile_goto
+#define asm_volatile_goto(x...) asm goto(x)
+#endif
+
+#ifdef CONFIG_CC_HAS_ASM_INLINE
+#define asm_inline asm __inline
+#else
+#define asm_inline asm
+#endif
+
+#ifndef __no_fgcse
+# define __no_fgcse
+#endif
+
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+
+/* Is this type a native word size -- useful for atomic operations */
+#define __native_word(t) \
+ (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
+ sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+
+/* Helpers for emitting diagnostics in pragmas. */
+#ifndef __diag
+#define __diag(string)
+#endif
+
+#ifndef __diag_GCC
+#define __diag_GCC(version, severity, string)
+#endif
+
+#define __diag_push() __diag(push)
+#define __diag_pop() __diag(pop)
+
+#define __diag_ignore(compiler, version, option, comment) \
+ __diag_ ## compiler(version, ignore, option)
+#define __diag_warn(compiler, version, option, comment) \
+ __diag_ ## compiler(version, warn, option)
+#define __diag_error(compiler, version, option, comment) \
+ __diag_ ## compiler(version, error, option)
+
+#endif /* __LINUX_COMPILER_TYPES_H */
#include <linux/types.h>
#include <linux/string.h>
-#define noinline __attribute__((noinline))
-
/* we use this so that we can do without the ctype library */
#define is_digit(c) ((c) >= '0' && (c) <= '9')
--- /dev/null
+# Kconfig helper macros
+
+# Convenient variables
+comma := ,
+quote := "
+squote := '
+empty :=
+space := $(empty) $(empty)
+dollar := $
+right_paren := )
+left_paren := (
+
+# $(if-success,<command>,<then>,<else>)
+# Return <then> if <command> exits with 0, <else> otherwise.
+if-success = $(shell,{ $(1); } >/dev/null 2>&1 && echo "$(2)" || echo "$(3)")
+
+# $(success,<command>)
+# Return y if <command> exits with 0, n otherwise
+success = $(if-success,$(1),y,n)
+
+# $(cc-option,<flag>)
+# Return y if the compiler supports <flag>, n otherwise
+cc-option = $(success,$(CC) -Werror $(1) -E -x c /dev/null -o /dev/null)
+
+# $(ld-option,<flag>)
+# Return y if the linker supports <flag>, n otherwise
+ld-option = $(success,$(LD) -v $(1))
+
+# gcc version including patch level
+gcc-version := $(shell,$(srctree)/scripts/gcc-version.sh -p $(CC) | sed 's/^0*//')
my $typedefsfile = "";
my $u_boot = 0;
my $color = "auto";
-my $allow_c99_comments = 1;
+my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANCE
+# git output parsing needs US English output, so first set backtick child process LANGUAGE
+my $git_command ='export LANGUAGE=en_US.UTF-8; git';
+my $tabsize = 8;
sub help {
my ($exitcode) = @_;
if exceeded, warn on patches
requires --strict for use with --file
--min-conf-desc-length=n set the min description length, if shorter, warn
+ --tab-size=n set the number of spaces for tab (default $tabsize)
--root=PATH PATH to the kernel tree root
--no-summary suppress the per-file summary
--mailback only produce a report in case of warnings/errors
'list-types!' => \$list_types,
'max-line-length=i' => \$max_line_length,
'min-conf-desc-length=i' => \$min_conf_desc_length,
+ 'tab-size=i' => \$tabsize,
'root=s' => \$root,
'summary!' => \$summary,
'mailback!' => \$mailback,
die "Invalid color mode: $color\n";
}
+# skip TAB size 1 to avoid additional checks on $tabsize - 1
+die "Invalid TAB size: $tabsize\n" if ($tabsize < 2);
+
sub hash_save_array_words {
my ($hashRef, $arrayRef) = @_;
seq_vprintf|seq_printf|seq_puts
)};
+our $allocFunctions = qr{(?x:
+ (?:(?:devm_)?
+ (?:kv|k|v)[czm]alloc(?:_node|_array)? |
+ kstrdup(?:_const)? |
+ kmemdup(?:_nul)?) |
+ (?:\w+)?alloc_skb(?:_ip_align)? |
+ # dev_alloc_skb/netdev_alloc_skb, et al
+ dma_alloc_coherent
+)};
+
our $signature_tags = qr{(?xi:
Signed-off-by:|
+ Co-developed-by:|
Acked-by:|
Tested-by:|
Reviewed-by:|
}
$mode_perms_search = "(?:${mode_perms_search})";
+our %deprecated_apis = (
+ "synchronize_rcu_bh" => "synchronize_rcu",
+ "synchronize_rcu_bh_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_bh" => "call_rcu",
+ "rcu_barrier_bh" => "rcu_barrier",
+ "synchronize_sched" => "synchronize_rcu",
+ "synchronize_sched_expedited" => "synchronize_rcu_expedited",
+ "call_rcu_sched" => "call_rcu",
+ "rcu_barrier_sched" => "rcu_barrier",
+ "get_state_synchronize_sched" => "get_state_synchronize_rcu",
+ "cond_synchronize_sched" => "cond_synchronize_rcu",
+);
+
+#Create a search pattern for all these strings to speed up a loop below
+our $deprecated_apis_search = "";
+foreach my $entry (keys %deprecated_apis) {
+ $deprecated_apis_search .= '|' if ($deprecated_apis_search ne "");
+ $deprecated_apis_search .= $entry;
+}
+$deprecated_apis_search = "(?:${deprecated_apis_search})";
+
our $mode_perms_world_writable = qr{
S_IWUGO |
S_IWOTH |
}x;
$Type = qr{
$NonptrType
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$TypeMisordered = qr{
$NonptrTypeMisordered
- (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+)?
+ (?:(?:\s|\*|\[\])+\s*const|(?:\s|\*\s*(?:const\s*)?|\[\])+|(?:\s*\[\s*\])+){0,4}
(?:\s+$Inline|\s+$Modifier)*
}x;
$Declare = qr{(?:$Storage\s+(?:$Inline\s+)?)?$Type};
}
}
+our %maintained_status = ();
+
sub is_maintained_obsolete {
my ($filename) = @_;
return 0 if (!$tree || !(-e "$root/scripts/get_maintainer.pl"));
- my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
+ if (!exists($maintained_status{$filename})) {
+ $maintained_status{$filename} = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`;
+ }
- return $status =~ /obsolete/i;
+ return $maintained_status{$filename} =~ /obsolete/i;
}
sub is_SPDX_License_valid {
$camelcase_seeded = 1;
if (-e ".git") {
- my $git_last_include_commit = `git log --no-merges --pretty=format:"%h%n" -1 -- include`;
+ my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`;
chomp $git_last_include_commit;
$camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit";
} else {
}
if (-e ".git") {
- $files = `git ls-files "include/*.h"`;
+ $files = `${git_command} ls-files "include/*.h"`;
@include_files = split('\n', $files);
}
return ($id, $desc) if ((which("git") eq "") || !(-e ".git"));
- my $output = `git log --no-color --format='%H %s' -1 $commit 2>&1`;
+ my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`;
$output =~ s/^\s*//gm;
my @lines = split("\n", $output);
return ($id, $desc) if ($#lines < 0);
- if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous\./) {
+ if ($lines[0] =~ /^error: short SHA1 $commit is ambiguous/) {
# Maybe one day convert this block of bash into something that returns
# all matching commit ids, but it's very slow...
#
} else {
$git_range = "-1 $commit_expr";
}
- my $lines = `git log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
+ my $lines = `${git_command} log --no-color --no-merges --pretty=format:'%H %s' $git_range`;
foreach my $line (split(/\n/, $lines)) {
$line =~ /^([0-9a-fA-F]{40,40}) (.*)$/;
next if (!defined($1) || !defined($2));
}
my $vname;
+$allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"};
for my $filename (@ARGV) {
my $FILE;
if ($git) {
my ($formatted_email) = @_;
my $name = "";
+ my $name_comment = "";
my $address = "";
my $comment = "";
$name = trim($name);
$name =~ s/^\"|\"$//g;
+ $name =~ s/(\s*\([^\)]+\))\s*//;
+ if (defined($1)) {
+ $name_comment = trim($1);
+ }
$address = trim($address);
$address =~ s/^\<|\>$//g;
$name = "\"$name\"";
}
- return ($name, $address, $comment);
+ return ($name, $name_comment, $address, $comment);
}
sub format_email {
return $formatted_email;
}
+sub reformat_email {
+ my ($email) = @_;
+
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
+ return format_email($email_name, $email_address);
+}
+
+sub same_email_addresses {
+ my ($email1, $email2) = @_;
+
+ my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
+ my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
+
+ return $email1_name eq $email2_name &&
+ $email1_address eq $email2_address;
+}
+
sub which {
my ($bin) = @_;
if ($c eq "\t") {
$res .= ' ';
$n++;
- for (; ($n % 8) != 0; $n++) {
+ for (; ($n % $tabsize) != 0; $n++) {
$res .= ' ';
}
next;
sub tabify {
my ($leading) = @_;
- my $source_indent = 8;
+ my $source_indent = $tabsize;
my $max_spaces_before_tab = $source_indent - 1;
my $spaces_to_tab = " " x $source_indent;
return length(expand_tabs(substr($line, 0, $last_openparen))) + 1;
}
+sub get_raw_comment {
+ my ($line, $rawline) = @_;
+ my $comment = '';
+
+ for my $i (0 .. (length($line) - 1)) {
+ if (substr($line, $i, 1) eq "$;") {
+ $comment .= substr($rawline, $i, 1);
+ }
+ }
+
+ return $comment;
+}
+
# Checks specific to U-Boot
sub u_boot_line {
my ($realfile, $line, $herecurr) = @_;
my $is_binding_patch = -1;
my $in_header_lines = $file ? 0 : 1;
my $in_commit_log = 0; #Scanning lines before patch
+ my $has_patch_separator = 0; #Found a --- line
my $has_commit_log = 0; #Encountered lines before patch
my $commit_log_lines = 0; #Number of commit log lines
my $commit_log_possible_stack_dump = 0;
$sline =~ s/$;/ /g; #with comments as spaces
my $rawline = $rawlines[$linenr - 1];
+ my $raw_comment = get_raw_comment($line, $rawline);
# check if it's a mode change, rename or start of a patch
if (!$in_commit_log &&
$author = $1;
$author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i);
$author =~ s/"//g;
+ $author = reformat_email($author);
}
# Check the patch for a signoff:
- if ($line =~ /^\s*signed-off-by:/i) {
+ if ($line =~ /^\s*signed-off-by:\s*(.*)/i) {
$signoff++;
$in_commit_log = 0;
if ($author ne '') {
- my $l = $line;
- $l =~ s/"//g;
- if ($l =~ /^\s*signed-off-by:\s*\Q$author\E/i) {
- $authorsignoff = 1;
+ if (same_email_addresses($1, $author)) {
+ $authorsignoff = 1;
}
}
}
+# Check for patch separator
+ if ($line =~ /^---$/) {
+ $has_patch_separator = 1;
+ $in_commit_log = 0;
+ }
+
# Check if MAINTAINERS is being updated. If so, there's probably no need to
# emit the "does MAINTAINERS need updating?" message on file add/move/delete
if ($line =~ /^\s*MAINTAINERS\s*\|/) {
}
}
- my ($email_name, $email_address, $comment) = parse_email($email);
+ my ($email_name, $name_comment, $email_address, $comment) = parse_email($email);
my $suggested_email = format_email(($email_name, $email_address));
if ($suggested_email eq "") {
ERROR("BAD_SIGN_OFF",
$dequoted =~ s/" </ </;
# Don't force email to have quotes
# Allow just an angle bracketed address
- if ("$dequoted$comment" ne $email &&
- "<$email_address>$comment" ne $email &&
- "$suggested_email$comment" ne $email) {
+ if (!same_email_addresses($email, $suggested_email)) {
WARN("BAD_SIGN_OFF",
"email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
}
} else {
$signatures{$sig_nospace} = 1;
}
+
+# Check Co-developed-by: immediately followed by Signed-off-by: with same name and email
+ if ($sign_off =~ /^co-developed-by:$/i) {
+ if ($email eq $author) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: should not be used to attribute nominal patch author '$author'\n" . "$here\n" . $rawline);
+ }
+ if (!defined $lines[$linenr]) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline);
+ } elsif ($rawlines[$linenr] !~ /^\s*signed-off-by:\s*(.*)/i) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by: must be immediately followed by Signed-off-by:\n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ } elsif ($1 ne $email) {
+ WARN("BAD_SIGN_OFF",
+ "Co-developed-by and Signed-off-by: name/email do not match \n" . "$here\n" . $rawline . "\n" .$rawlines[$linenr]);
+ }
+ }
}
# Check email subject for common tools that don't need to be mentioned
"A patch subject line should describe the change not the tool that found it\n" . $herecurr);
}
-# Check for unwanted Gerrit info
- if ($in_commit_log && $line =~ /^\s*change-id:/i) {
+# Check for Gerrit Change-Ids not in any patch context
+ if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
ERROR("GERRIT_CHANGE_ID",
- "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
+ "Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
}
# Check if the commit log is in a possible stack dump
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
$line =~ /^\s*\[\s*\d+\.\d{6,6}\s*\]/ ||
# timestamp
- $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/)) {
- # stack dump address
+ $line =~ /^\s*\[\<[0-9a-fA-F]{8,}\>\]/) ||
+ $line =~ /^(?:\s+\w+:\s+[0-9a-fA-F]+){3,3}/ ||
+ $line =~ /^\s*\#\d+\s*\[[0-9a-fA-F]+\]\s*\w+ at [0-9a-fA-F]+/) {
+ # stack dump address styles
$commit_log_possible_stack_dump = 1;
}
# Check for git id commit length and improperly formed commit descriptions
if ($in_commit_log && !$commit_log_possible_stack_dump &&
- $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i &&
+ $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
$line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
}
+# Check for adding new DT bindings not in schema format
+ if (!$in_commit_log &&
+ ($line =~ /^new file mode\s*\d+\s*$/) &&
+ ($realfile =~ m@^Documentation/devicetree/bindings/.*\.txt$@)) {
+ WARN("DT_SCHEMA_BINDING_PATCH",
+ "DT bindings should be in DT schema format. See: Documentation/devicetree/writing-schema.rst\n");
+ }
+
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
ERROR("CORRUPTED_PATCH",
}
}
+# check for invalid commit id
+ if ($in_commit_log && $line =~ /(^fixes:|\bcommit)\s+([0-9a-f]{6,40})\b/i) {
+ my $id;
+ my $description;
+ ($id, $description) = git_commit_info($2, undef, undef);
+ if (!defined($id)) {
+ WARN("UNKNOWN_COMMIT_ID",
+ "Unknown commit id '$2', maybe rebased or not pulled?\n" . $herecurr);
+ }
+ }
+
# ignore non-hunk lines and lines being removed
next if (!$hunk_line || $line =~ /^-/);
my @compats = $rawline =~ /\"([a-zA-Z0-9\-\,\.\+_]+)\"/g;
my $dt_path = $root . "/Documentation/devicetree/bindings/";
- my $vp_file = $dt_path . "vendor-prefixes.txt";
+ my $vp_file = $dt_path . "vendor-prefixes.yaml";
foreach my $compat (@compats) {
my $compat2 = $compat;
next if $compat !~ /^([a-zA-Z0-9\-]+)\,/;
my $vendor = $1;
- `grep -Eq "^$vendor\\b" $vp_file`;
+ `grep -Eq "\\"\\^\Q$vendor\E,\\.\\*\\":" $vp_file`;
if ( $? >> 8 ) {
WARN("UNDOCUMENTED_DT_STRING",
"DT compatible string vendor \"$vendor\" appears un-documented -- check $vp_file\n" . $herecurr);
$comment = '/*';
} elsif ($realfile =~ /\.(c|dts|dtsi)$/) {
$comment = '//';
- } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc)$/) {
+ } elsif (($checklicenseline == 2) || $realfile =~ /\.(sh|pl|py|awk|tc|yaml)$/) {
$comment = '#';
} elsif ($realfile =~ /\.rst$/) {
$comment = '..';
}
+# check SPDX comment style for .[chsS] files
+ if ($realfile =~ /\.[chsS]$/ &&
+ $rawline =~ /SPDX-License-Identifier:/ &&
+ $rawline !~ m@^\+\s*\Q$comment\E\s*@) {
+ WARN("SPDX_LICENSE_TAG",
+ "Improper SPDX comment style for '$realfile', please use '$comment' instead\n" . $herecurr);
+ }
+
if ($comment !~ /^$/ &&
- $rawline !~ /^\+\Q$comment\E SPDX-License-Identifier: /) {
- WARN("SPDX_LICENSE_TAG",
- "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
+ $rawline !~ m@^\+\Q$comment\E SPDX-License-Identifier: @) {
+ WARN("SPDX_LICENSE_TAG",
+ "Missing or malformed SPDX-License-Identifier tag in line $checklicenseline\n" . $herecurr);
} elsif ($rawline =~ /(SPDX-License-Identifier: .*)/) {
- my $spdx_license = $1;
- if (!is_SPDX_License_valid($spdx_license)) {
- WARN("SPDX_LICENSE_TAG",
- "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
- }
+ my $spdx_license = $1;
+ if (!is_SPDX_License_valid($spdx_license)) {
+ WARN("SPDX_LICENSE_TAG",
+ "'$spdx_license' is not supported in LICENSES/...\n" . $herecurr);
+ }
+ if ($realfile =~ m@^Documentation/devicetree/bindings/@ &&
+ not $spdx_license =~ /GPL-2\.0.*BSD-2-Clause/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ if (&{$msg_level}("SPDX_LICENSE_TAG",
+
+ "DT binding documents should be licensed (GPL-2.0-only OR BSD-2-Clause)\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/SPDX-License-Identifier: .*/SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)/;
+ }
+ }
}
}
}
# check we are in a valid source file if not then ignore this hunk
next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/);
+# check for using SPDX-License-Identifier on the wrong line number
+ if ($realline != $checklicenseline &&
+ $rawline =~ /\bSPDX-License-Identifier:/ &&
+ substr($line, @-, @+ - @-) eq "$;" x (@+ - @-)) {
+ WARN("SPDX_LICENSE_TAG",
+ "Misplaced SPDX-License-Identifier tag - use line $checklicenseline instead\n" . $herecurr);
+ }
+
# line length limit (with some exclusions)
#
# There are a few types of lines that may extend beyond $max_line_length:
next if ($realfile !~ /\.(h|c|pl|dtsi|dts)$/);
# at the beginning of a line any tabs must come first and anything
-# more than 8 must use tabs.
+# more than $tabsize must use tabs.
if ($rawline =~ /^\+\s* \t\s*\S/ ||
$rawline =~ /^\+\s* \s*/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
"please, no space before tabs\n" . $herevet) &&
$fix) {
while ($fixed[$fixlinenr] =~
- s/(^\+.*) {8,8}\t/$1\t\t/) {}
+ s/(^\+.*) {$tabsize,$tabsize}\t/$1\t\t/) {}
while ($fixed[$fixlinenr] =~
s/(^\+.*) +\t/$1\t/) {}
}
if ($perl_version_ok &&
$sline =~ /^\+\t+( +)(?:$c90_Keywords\b|\{\s*$|\}\s*(?:else\b|while\b|\s*$)|$Declare\s*$Ident\s*[;=])/) {
my $indent = length($1);
- if ($indent % 8) {
+ if ($indent % $tabsize) {
if (WARN("TABSTOP",
"Statements should start on a tabstop\n" . $herecurr) &&
$fix) {
- $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/8)@e;
+ $fixed[$fixlinenr] =~ s@(^\+\t+) +@$1 . "\t" x ($indent/$tabsize)@e;
}
}
}
my $newindent = $2;
my $goodtabindent = $oldindent .
- "\t" x ($pos / 8) .
- " " x ($pos % 8);
+ "\t" x ($pos / $tabsize) .
+ " " x ($pos % $tabsize);
my $goodspaceindent = $oldindent . " " x $pos;
if ($newindent ne $goodtabindent &&
#print "line<$line> prevline<$prevline> indent<$indent> sindent<$sindent> check<$check> continuation<$continuation> s<$s> cond_lines<$cond_lines> stat_real<$stat_real> stat<$stat>\n";
if ($check && $s ne '' &&
- (($sindent % 8) != 0 ||
+ (($sindent % $tabsize) != 0 ||
($sindent < $indent) ||
($sindent == $indent &&
($s !~ /^\s*(?:\}|\{|else\b)/)) ||
- ($sindent > $indent + 8))) {
+ ($sindent > $indent + $tabsize))) {
WARN("SUSPECT_CODE_INDENT",
"suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
}
WARN("STATIC_CONST_CHAR_ARRAY",
"static const char * array should probably be static const char * const\n" .
$herecurr);
- }
+ }
+
+# check for initialized const char arrays that should be static const
+ if ($line =~ /^\+\s*const\s+(char|unsigned\s+char|_*u8|(?:[us]_)?int8_t)\s+\w+\s*\[\s*(?:\w+\s*)?\]\s*=\s*"/) {
+ if (WARN("STATIC_CONST_CHAR_ARRAY",
+ "const array should probably be static const\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/(^.\s*)const\b/${1}static const/;
+ }
+ }
# check for static char foo[] = "bar" declarations.
if ($line =~ /\bstatic\s+char\s+(\w+)\s*\[\s*\]\s*=\s*"/) {
WARN("STATIC_CONST_CHAR_ARRAY",
"static char array declaration should probably be static const char\n" .
$herecurr);
- }
+ }
# check for const <foo> const where <foo> is not a pointer or array type
if ($sline =~ /\bconst\s+($BasicType)\s+const\b/) {
}
# check for function declarations without arguments like "int foo()"
- if ($line =~ /(\b$Type\s+$Ident)\s*\(\s*\)/) {
+ if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
if (ERROR("FUNCTION_WITHOUT_ARGS",
"Bad function definition - $1() should probably be $1(void)\n" . $herecurr) &&
$fix) {
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
}
- if ($line =~ /\bpr_warning\s*\(/) {
- if (WARN("PREFER_PR_LEVEL",
- "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~
- s/\bpr_warning\b/pr_warn/;
- }
- }
-
if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
my $orig = $1;
my $level = lc($orig);
($op eq '>' &&
$ca =~ /<\S+\@\S+$/))
{
- $ok = 1;
+ $ok = 1;
}
# for asm volatile statements
# closing brace should have a space following it when it has anything
# on the line
- if ($line =~ /}(?!(?:,|;|\)))\S/) {
+ if ($line =~ /}(?!(?:,|;|\)|\}))\S/) {
if (ERROR("SPACING",
"space required after that close brace '}'\n" . $herecurr) &&
$fix) {
# conditional.
substr($s, 0, length($c), '');
$s =~ s/\n.*//g;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if (length($c) && $s !~ /^\s*{?\s*\\*\s*$/ &&
$c !~ /}\s*while\s*/)
{
# if and else should not have general statements after it
if ($line =~ /^.\s*(?:}\s*)?else\b(.*)/) {
my $s = $1;
- $s =~ s/$;//g; # Remove any comments
+ $s =~ s/$;//g; # Remove any comments
if ($s !~ /^\s*(?:\sif|(?:{|)\s*\\?\s*$)/) {
ERROR("TRAILING_STATEMENTS",
"trailing statements should be on next line\n" . $herecurr);
while ($line =~ m{($Constant|$Lval)}g) {
my $var = $1;
-#gcc binary extension
- if ($var =~ /^$Binary$/) {
- if (WARN("GCC_BINARY_CONSTANT",
- "Avoid gcc v4.3+ binary constant extension: <$var>\n" . $herecurr) &&
- $fix) {
- my $hexval = sprintf("0x%x", oct($var));
- $fixed[$fixlinenr] =~
- s/\b$var\b/$hexval/;
- }
- }
-
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
#Ignore Page<foo> variants
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
-#Ignore SI style variants like nS, mV and dB (ie: max_uV, regulator_min_uA_show)
- $var !~ /^(?:[a-z_]*?)_?[a-z][A-Z](?:_[a-z_]+)?$/ &&
+#Ignore SI style variants like nS, mV and dB
+#(ie: max_uV, regulator_min_uA_show, RANGE_mA_VALUE)
+ $var !~ /^(?:[a-z0-9_]*|[A-Z0-9_]*)?_?[a-z][A-Z](?:_[a-z0-9_]+|_[A-Z0-9_]+)?$/ &&
#Ignore some three character SI units explicitly, like MiB and KHz
$var !~ /^(?:[a-z_]*?)_?(?:[KMGT]iB|[KMGT]?Hz)(?:_[a-z_]+)?$/) {
while ($var =~ m{($Ident)}g) {
{
}
- # Flatten any obvious string concatentation.
+ # Flatten any obvious string concatenation.
while ($dstat =~ s/($String)\s*$Ident/$1/ ||
$dstat =~ s/$Ident\s*($String)/$1/)
{
next if ($arg =~ /\.\.\./);
next if ($arg =~ /^type$/i);
my $tmp_stmt = $define_stmt;
- $tmp_stmt =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
+ $tmp_stmt =~ s/\b(sizeof|typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g;
$tmp_stmt =~ s/\#+\s*$arg\b//g;
$tmp_stmt =~ s/\b$arg\s*\#\#//g;
my $use_cnt = () = $tmp_stmt =~ /\b$arg\b/g;
my ($s, $c) = ctx_statement_block($linenr - 3, $realcnt, 0);
# print("line: <$line>\nprevline: <$prevline>\ns: <$s>\nc: <$c>\n\n\n");
- if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*(?:devm_)?(?:[kv][czm]alloc(?:_node|_array)?\b|kstrdup|kmemdup|(?:dev_)?alloc_skb)/) {
+ if ($s =~ /(?:^|\n)[ \+]\s*(?:$Type\s*)?\Q$testval\E\s*=\s*(?:\([^\)]*\)\s*)?\s*$allocFunctions\s*\(/ &&
+ $s !~ /\b__GFP_NOWARN\b/ ) {
WARN("OOM_MESSAGE",
"Possible unnecessary 'out of memory' message\n" . $hereprev);
}
# ignore udelay's < 10, however
if (! ($delay < 10) ) {
CHK("USLEEP_RANGE",
- "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
if ($delay > 2000) {
WARN("LONG_UDELAY",
if ($line =~ /\bmsleep\s*\((\d+)\);/) {
if ($1 < 20) {
WARN("MSLEEP",
- "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.txt\n" . $herecurr);
+ "msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst\n" . $herecurr);
}
}
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
+# Check for __attribute__ section, prefer __section
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
+ my $old = substr($rawline, $-[1], $+[1] - $-[1]);
+ my $new = substr($old, 1, -1);
+ if (WARN("PREFER_SECTION",
+ "__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
+ $fix) {
+ $fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
+ }
+ }
+
# Check for __attribute__ format(printf, prefer __printf
if ($realfile !~ m@\binclude/uapi/@ &&
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
for (my $count = $linenr; $count <= $lc; $count++) {
my $specifier;
my $extension;
+ my $qualifier;
my $bad_specifier = "";
my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
$fmt =~ s/%%//g;
- while ($fmt =~ /(\%[\*\d\.]*p(\w))/g) {
+ while ($fmt =~ /(\%[\*\d\.]*p(\w)(\w*))/g) {
$specifier = $1;
$extension = $2;
- if ($extension !~ /[SsBKRraEhMmIiUDdgVCbGNOx]/) {
+ $qualifier = $3;
+ if ($extension !~ /[SsBKRraEehMmIiUDdgVCbGNOxtf]/ ||
+ ($extension eq "f" &&
+ defined $qualifier && $qualifier !~ /^w/)) {
$bad_specifier = $specifier;
last;
}
my $ext_type = "Invalid";
my $use = "";
if ($bad_specifier =~ /p[Ff]/) {
- $ext_type = "Deprecated";
$use = " - use %pS instead";
$use =~ s/pS/ps/ if ($bad_specifier =~ /pf/);
}
my $max = $7;
if ($min eq $max) {
WARN("USLEEP_RANGE",
- "usleep_range should not use min == max args; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range should not use min == max args; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
} elsif ($min =~ /^\d+$/ && $max =~ /^\d+$/ &&
$min > $max) {
WARN("USLEEP_RANGE",
- "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.txt\n" . "$here\n$stat\n");
+ "usleep_range args reversed, use min then max; see Documentation/timers/timers-howto.rst\n" . "$here\n$stat\n");
}
}
}
# check for function declarations that have arguments without identifier names
+# while avoiding uninitialized_var(x)
if (defined $stat &&
- $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:$Ident|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
- $1 ne "void") {
- my $args = trim($1);
+ $stat =~ /^.\s*(?:extern\s+)?$Type\s*(?:($Ident)|\(\s*\*\s*$Ident\s*\))\s*\(\s*([^{]+)\s*\)\s*;/s &&
+ (!defined($1) ||
+ (defined($1) && $1 ne "uninitialized_var")) &&
+ $2 ne "void") {
+ my $args = trim($2);
while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) {
my $arg = trim($1);
- if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) {
+ if ($arg =~ /^$Type$/ &&
+ $arg !~ /enum\s+$Ident$/) {
WARN("FUNCTION_ARGUMENTS",
"function definition argument '$arg' should also have an identifier name\n" . $herecurr);
}
}
}
-# check for pointless casting of kmalloc return
- if ($line =~ /\*\s*\)\s*[kv][czm]alloc(_node){0,1}\b/) {
+# check for pointless casting of alloc functions
+ if ($line =~ /\*\s*\)\s*$allocFunctions\b/) {
WARN("UNNECESSARY_CASTS",
"unnecessary cast may hide bugs, see http://c-faq.com/malloc/mallocnocast.html\n" . $herecurr);
}
# alloc style
# p = alloc(sizeof(struct foo), ...) should be p = alloc(sizeof(*p), ...)
if ($perl_version_ok &&
- $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*([kv][mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
+ $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k|v)[mz]alloc(?:_node)?)\s*\(\s*(sizeof\s*\(\s*struct\s+$Lval\s*\))/) {
CHK("ALLOC_SIZEOF_STRUCT",
"Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr);
}
}
}
+# check for /* fallthrough */ like comment, prefer fallthrough;
+ my @fallthroughs = (
+ 'fallthrough',
+ '@fallthrough@',
+ 'lint -fallthrough[ \t]*',
+ 'intentional(?:ly)?[ \t]*fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)',
+ '(?:else,?\s*)?FALL(?:S | |-)?THR(?:OUGH|U|EW)[ \t.!]*(?:-[^\n\r]*)?',
+ 'Fall(?:(?:s | |-)[Tt]|t)hr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ 'fall(?:s | |-)?thr(?:ough|u|ew)[ \t.!]*(?:-[^\n\r]*)?',
+ );
+ if ($raw_comment ne '') {
+ foreach my $ft (@fallthroughs) {
+ if ($raw_comment =~ /$ft/) {
+ my $msg_level = \&WARN;
+ $msg_level = \&CHK if ($file);
+ &{$msg_level}("PREFER_FALLTHROUGH",
+ "Prefer 'fallthrough;' over fallthrough comment\n" . $herecurr);
+ last;
+ }
+ }
+ }
+
# check for switch/default statements without a break;
if ($perl_version_ok &&
defined $stat &&
}
}
-# check for bool bitfields
- if ($sline =~ /^.\s+bool\s*$Ident\s*:\s*\d+\s*;/) {
- WARN("BOOL_BITFIELD",
- "Avoid using bool as bitfield. Prefer bool bitfields as unsigned int or u<8|16|32>\n" . $herecurr);
- }
-
-# check for bool use in .h files
- if ($realfile =~ /\.h$/ &&
- $sline =~ /^.\s+bool\s*$Ident\s*(?::\s*d+\s*)?;/) {
- CHK("BOOL_MEMBER",
- "Avoid using bool structure members because of possible alignment issues - see: https://lkml.org/lkml/2017/11/21/384\n" . $herecurr);
- }
-
# check for semaphores initialized locked
if ($line =~ /^.\s*sema_init.+,\W?0\W?\)/) {
WARN("CONSIDER_COMPLETION",
"please use device_initcall() or more appropriate function instead of __initcall() (see include/linux/init.h)\n" . $herecurr);
}
+# check for spin_is_locked(), suggest lockdep instead
+ if ($line =~ /\bspin_is_locked\(/) {
+ WARN("USE_LOCKDEP",
+ "Where possible, use lockdep_assert_held instead of assertions based on spin_is_locked\n" . $herecurr);
+ }
+
+# check for deprecated apis
+ if ($line =~ /\b($deprecated_apis_search)\b\s*\(/) {
+ my $deprecated_api = $1;
+ my $new_api = $deprecated_apis{$deprecated_api};
+ WARN("DEPRECATED_API",
+ "Deprecated use of '$deprecated_api', prefer '$new_api' instead\n" . $herecurr);
+ }
+
# check for various structs that are normally const (ops, kgdb, device_tree)
# and avoid what seem like struct definitions 'struct foo {'
if ($line !~ /\bconst\b/ &&
"Using $1 should generally have parentheses around the comparison\n" . $herecurr);
}
+# nested likely/unlikely calls
+ if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) {
+ WARN("LIKELY_MISUSE",
+ "nested (un)?likely() calls, $1 already uses unlikely() internally\n" . $herecurr);
+ }
+
# whine mightly about in_atomic
if ($line =~ /\bin_atomic\s*\(/) {
if ($realfile =~ m@^drivers/@) {
"unknown module license " . $extracted_string . "\n" . $herecurr);
}
}
+
+# check for sysctl duplicate constants
+ if ($line =~ /\.extra[12]\s*=\s*&(zero|one|int_max)\b/) {
+ WARN("DUPLICATED_SYSCTL_CONST",
+ "duplicated sysctl range checking value '$1', consider using the shared one in include/linux/sysctl.h\n" . $herecurr);
+ }
}
# If we have no input at all, then there is nothing to report on
from os.path import dirname, exists, expandvars, islink, join, realpath
-VERSION = (12, 14, 0)
+VERSION = (14, 1, 0)
# File layout:
See Kconfig.load_config() as well.
srctree:
- The value of the $srctree environment variable when the configuration was
- loaded, or the empty string if $srctree wasn't set. This gives nice
+ The value the $srctree environment variable had when the Kconfig instance
+ was created, or the empty string if $srctree wasn't set. This gives nice
behavior with os.path.join(), which treats "" as the current directory,
without adding "./".
if multiple configurations are loaded with different values for $srctree.
config_prefix:
- The value of the $CONFIG_ environment variable when the configuration was
- loaded. This is the prefix used (and expected) on symbol names in .config
- files and C headers. Defaults to "CONFIG_". Used in the same way in the C
- tools.
-
- Like for srctree, only the value of $CONFIG_ when the configuration is
- loaded matters.
+ The value the CONFIG_ environment variable had when the Kconfig instance
+ was created, or "CONFIG_" if CONFIG_ wasn't set. This is the prefix used
+ (and expected) on symbol names in .config files and C headers. Used in
+ the same way in the C tools.
+
+ config_header:
+ The value the KCONFIG_CONFIG_HEADER environment variable had when the
+ Kconfig instance was created, or the empty string if
+ KCONFIG_CONFIG_HEADER wasn't set. This string is inserted verbatim at the
+ beginning of configuration files. See write_config().
+
+ header_header:
+ The value the KCONFIG_AUTOHEADER_HEADER environment variable had when the
+ Kconfig instance was created, or the empty string if
+ KCONFIG_AUTOHEADER_HEADER wasn't set. This string is inserted verbatim at
+ the beginning of header files. See write_autoconf().
filename/linenr:
The current parsing location, for use in Python preprocessor functions.
"_warn_assign_no_prompt",
"choices",
"comments",
+ "config_header",
"config_prefix",
"const_syms",
"defconfig_list",
"defined_syms",
"env_vars",
+ "header_header",
"kconfig_filenames",
"m",
"menus",
#
def __init__(self, filename="Kconfig", warn=True, warn_to_stderr=True,
- encoding="utf-8"):
+ encoding="utf-8", suppress_traceback=False):
"""
Creates a new Kconfig object by parsing Kconfig files.
Note that Kconfig files are not the same as .config files (which store
anyway.
Related PEP: https://www.python.org/dev/peps/pep-0538/
+
+ suppress_traceback (default: False):
+ Helper for tools. When True, any EnvironmentError or KconfigError
+ generated during parsing is caught, the exception message is printed
+ to stderr together with the command name, and sys.exit(1) is called
+ (which generates SystemExit).
+
+ This hides the Python traceback for "expected" errors like syntax
+ errors in Kconfig files.
+
+ Other exceptions besides EnvironmentError and KconfigError are still
+ propagated when suppress_traceback is True.
"""
+ try:
+ self._init(filename, warn, warn_to_stderr, encoding)
+ except (EnvironmentError, KconfigError) as e:
+ if suppress_traceback:
+ cmd = sys.argv[0] # Empty string if missing
+ if cmd:
+ cmd += ": "
+ # Some long exception messages have extra newlines for better
+ # formatting when reported as an unhandled exception. Strip
+ # them here.
+ sys.exit(cmd + str(e).strip())
+ raise
+
+ def _init(self, filename, warn, warn_to_stderr, encoding):
+ # See __init__()
+
self._encoding = encoding
self.srctree = os.getenv("srctree", "")
self._unset_match = _re_match(r"# {}([^ ]+) is not set".format(
self.config_prefix))
+ self.config_header = os.getenv("KCONFIG_CONFIG_HEADER", "")
+ self.header_header = os.getenv("KCONFIG_AUTOHEADER_HEADER", "")
+
self.syms = {}
self.const_syms = {}
self.defined_syms = []
self._readline = self._open(join(self.srctree, filename), "r").readline
try:
- # Parse the Kconfig files
- self._parse_block(None, self.top_node, self.top_node)
+ # Parse the Kconfig files. Returns the last node, which we
+ # terminate with '.next = None'.
+ self._parse_block(None, self.top_node, self.top_node).next = None
self.top_node.list = self.top_node.next
self.top_node.next = None
except UnicodeDecodeError as e:
self._warn("'{}' is not a valid value for the {} "
"symbol {}. Assignment ignored."
.format(val, TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym)),
+ sym.name_and_loc),
filename, linenr)
continue
if not match:
self._warn("malformed string literal in "
"assignment to {}. Assignment ignored."
- .format(_name_and_loc(sym)),
+ .format(sym.name_and_loc),
filename, linenr)
continue
user_val = sym.user_value
msg = '{} set more than once. Old value "{}", new value "{}".'.format(
- _name_and_loc(sym), user_val, new_val)
+ sym.name_and_loc, user_val, new_val)
if user_val == new_val:
if self.warn_assign_redun:
elif self.warn_assign_override:
self._warn(msg, filename, linenr)
- def write_autoconf(self, filename,
- header="/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
+ def load_allconfig(self, filename):
+ """
+ Helper for all*config. Loads (merges) the configuration file specified
+ by KCONFIG_ALLCONFIG, if any. See Documentation/kbuild/kconfig.txt in
+ the Linux kernel.
+
+ Disables warnings for duplicated assignments within configuration files
+ for the duration of the call
+ (kconf.warn_assign_override/warn_assign_redun = False), and restores
+ the previous warning settings at the end. The KCONFIG_ALLCONFIG
+ configuration file is expected to override symbols.
+
+ Exits with sys.exit() (which raises a SystemExit exception) and prints
+ an error to stderr if KCONFIG_ALLCONFIG is set but the configuration
+ file can't be opened.
+
+ filename:
+ Command-specific configuration filename - "allyes.config",
+ "allno.config", etc.
+ """
+ load_allconfig(self, filename)
+
+ def write_autoconf(self, filename=None, header=None):
r"""
Writes out symbol values as a C header file, matching the format used
by include/generated/autoconf.h in the kernel.
like the modification time and possibly triggering redundant work in
build tools.
- filename:
- Self-explanatory.
+ filename (default: None):
+ Path to write header to.
- header (default: "/* Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib) */\n"):
- Text that will be inserted verbatim at the beginning of the file. You
- would usually want it enclosed in '/* */' to make it a C comment,
- and include a final terminating newline.
+ If None (the default), the path in the environment variable
+ KCONFIG_AUTOHEADER is used if set, and "include/generated/autoconf.h"
+ otherwise. This is compatible with the C tools.
+
+ header (default: None):
+ Text inserted verbatim at the beginning of the file. You would
+ usually want it enclosed in '/* */' to make it a C comment, and
+ include a trailing newline.
+
+ If None (the default), the value of the environment variable
+ KCONFIG_AUTOHEADER_HEADER had when the Kconfig instance was created
+ will be used if it was set, and no header otherwise. See the
+ Kconfig.header_header attribute.
+
+ Returns a string with a message saying that the header got saved, or
+ that there were no changes to it. This is meant to reduce boilerplate
+ in tools, which can do e.g. print(kconf.write_autoconf()).
"""
- self._write_if_changed(filename, self._autoconf_contents(header))
+ if filename is None:
+ filename = os.getenv("KCONFIG_AUTOHEADER",
+ "include/generated/autoconf.h")
+
+ if self._write_if_changed(filename, self._autoconf_contents(header)):
+ return "Kconfig header saved to '{}'".format(filename)
+ return "No change to Kconfig header in '{}'".format(filename)
def _autoconf_contents(self, header):
# write_autoconf() helper. Returns the contents to write as a string,
- # with 'header' at the beginning.
+ # with 'header' or KCONFIG_AUTOHEADER_HEADER at the beginning.
- # "".join()ed later
- chunks = [header]
+ if header is None:
+ header = self.header_header
+
+ chunks = [header] # "".join()ed later
add = chunks.append
for sym in self.unique_defined_syms:
return "".join(chunks)
- def write_config(self, filename=None,
- header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n",
- save_old=True, verbose=None):
+ def write_config(self, filename=None, header=None, save_old=True,
+ verbose=None):
r"""
Writes out symbol values in the .config format. The format matches the
C implementation, including ordering.
(OSError/IOError). KconfigError is never raised here.
filename (default: None):
- Filename to save configuration to (a string).
+ Path to write configuration to (a string).
- If None (the default), the filename in the environment variable
+ If None (the default), the path in the environment variable
KCONFIG_CONFIG is used if set, and ".config" otherwise. See
standard_config_filename().
- header (default: "# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
- Text that will be inserted verbatim at the beginning of the file. You
- would usually want each line to start with '#' to make it a comment,
- and include a final terminating newline.
+ header (default: None):
+ Text inserted verbatim at the beginning of the file. You would
+ usually want each line to start with '#' to make it a comment, and
+ include a trailing newline.
+
+ if None (the default), the value of the environment variable
+ KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
+ be used if it was set, and no header otherwise. See the
+ Kconfig.config_header attribute.
save_old (default: True):
If True and <filename> already exists, a copy of it will be saved to
contents = self._config_contents(header)
if self._contents_eq(filename, contents):
- return "No change to '{}'".format(filename)
+ return "No change to configuration in '{}'".format(filename)
if save_old:
_save_old(filename)
def _config_contents(self, header):
# write_config() helper. Returns the contents to write as a string,
- # with 'header' at the beginning.
+ # with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
#
# More memory friendly would be to 'yield' the strings and
# "".join(_config_contents()), but it was a bit slower on my system.
for sym in self.unique_defined_syms:
sym._visited = False
- # Did we just print an '# end of ...' comment?
- after_end_comment = False
+ if header is None:
+ header = self.config_header
- # "".join()ed later
- chunks = [header]
+ chunks = [header] # "".join()ed later
add = chunks.append
+ # Did we just print an '# end of ...' comment?
+ after_end_comment = False
+
node = self.top_node
while 1:
# Jump to the next node with an iterative tree walk
add("\n#\n# {}\n#\n".format(node.prompt[0]))
after_end_comment = False
- def write_min_config(self, filename,
- header="# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
+ def write_min_config(self, filename, header=None):
"""
Writes out a "minimal" configuration file, omitting symbols whose value
matches their default value. The format matches the one produced by
(OSError/IOError). KconfigError is never raised here.
filename:
- Self-explanatory.
+ Path to write minimal configuration to.
- header (default: "# Generated by Kconfiglib (https://github.com/ulfalizer/Kconfiglib)\n"):
- Text that will be inserted verbatim at the beginning of the file. You
- would usually want each line to start with '#' to make it a comment,
- and include a final terminating newline.
+ header (default: None):
+ Text inserted verbatim at the beginning of the file. You would
+ usually want each line to start with '#' to make it a comment, and
+ include a final terminating newline.
- Returns a string with a message saying which file got saved. This is
- meant to reduce boilerplate in tools, which can do e.g.
+ if None (the default), the value of the environment variable
+ KCONFIG_CONFIG_HEADER had when the Kconfig instance was created will
+ be used if it was set, and no header otherwise. See the
+ Kconfig.config_header attribute.
+
+ Returns a string with a message saying the minimal configuration got
+ saved, or that there were no changes to it. This is meant to reduce
+ boilerplate in tools, which can do e.g.
print(kconf.write_min_config()).
"""
- contents = self._min_config_contents(header)
- if self._contents_eq(filename, contents):
- return "No change to '{}'".format(filename)
-
- with self._open(filename, "w") as f:
- f.write(contents)
-
- return "Minimal configuration saved to '{}'".format(filename)
+ if self._write_if_changed(filename, self._min_config_contents(header)):
+ return "Minimal configuration saved to '{}'".format(filename)
+ return "No change to minimal configuration in '{}'".format(filename)
def _min_config_contents(self, header):
# write_min_config() helper. Returns the contents to write as a string,
- # with 'header' at the beginning.
+ # with 'header' or KCONFIG_CONFIG_HEADER at the beginning.
- chunks = [header]
+ if header is None:
+ header = self.config_header
+
+ chunks = [header] # "".join()ed later
add = chunks.append
for sym in self.unique_defined_syms:
# it's part of a different construct
if self._reuse_tokens:
self._reuse_tokens = False
- # self._tokens_i is known to be 1 here, because _parse_properties()
- # leaves it like that when it can't recognize a line (or parses
- # a help text)
+ # self._tokens_i is known to be 1 here, because _parse_props()
+ # leaves it like that when it can't recognize a line (or parses a
+ # help text)
return True
# readline() returns '' over and over at EOF, which we rely on for help
self._tokens = self._tokenize(line)
# Initialize to 1 instead of 0 to factor out code from _parse_block()
- # and _parse_properties(). They immediately fetch self._tokens[0].
+ # and _parse_props(). They immediately fetch self._tokens[0].
self._tokens_i = 1
return True
# differs, but it breaks stuff like write_config("/dev/null"), which is
# used out there to force evaluation-related warnings to be generated.
# This simple version is pretty failsafe and portable.
+ #
+ # Returns True if the file has changed and is updated, and False
+ # otherwise.
- if not self._contents_eq(filename, contents):
- with self._open(filename, "w") as f:
- f.write(contents)
+ if self._contents_eq(filename, contents):
+ return False
+ with self._open(filename, "w") as f:
+ f.write(contents)
+ return True
def _contents_eq(self, filename, contents):
# Returns True if the contents of 'filename' is 'contents' (a string),
while 1:
match = _name_special_search(s, i)
- if match.group() == "$(":
- s, i = self._expand_macro(s, match.start(), ())
- else:
+ if match.group() != "$(":
return (s, match.start())
+ s, i = self._expand_macro(s, match.start(), ())
def _expand_str(self, s, i):
# Expands a quoted string starting at index 'i' in 's'. Handles both
# Returns the expanded 's' (including the part before the macro) and
# the index of the first character after the expanded macro in 's'.
- start = i
+ res = s[:i]
i += 2 # Skip over "$("
- # Start of current macro argument
- arg_start = i
-
- # Arguments of this macro call
- new_args = []
+ arg_start = i # Start of current macro argument
+ new_args = [] # Arguments of this macro call
+ nesting = 0 # Current parentheses nesting level
while 1:
match = _macro_special_search(s, i)
self._parse_error("missing end parenthesis in macro expansion")
- if match.group() == ")":
+ if match.group() == "(":
+ nesting += 1
+ i = match.end()
+
+ elif match.group() == ")":
+ if nesting:
+ nesting -= 1
+ i = match.end()
+ continue
+
# Found the end of the macro
new_args.append(s[arg_start:match.start()])
- prefix = s[:start]
-
# $(1) is replaced by the first argument to the function, etc.,
# provided at least that many arguments were passed
try:
# Does the macro look like an integer, with a corresponding
# argument? If so, expand it to the value of the argument.
- prefix += args[int(new_args[0])]
+ res += args[int(new_args[0])]
except (ValueError, IndexError):
# Regular variables are just functions without arguments,
# and also go through the function value path
- prefix += self._fn_val(new_args)
+ res += self._fn_val(new_args)
- return (prefix + s[match.end():],
- len(prefix))
+ return (res + s[match.end():], len(res))
elif match.group() == ",":
+ i = match.end()
+ if nesting:
+ continue
+
# Found the end of a macro argument
new_args.append(s[arg_start:match.start()])
- arg_start = i = match.end()
+ arg_start = i
else: # match.group() == "$("
# A nested macro call within the macro
#
# prev:
# The previous menu node. New nodes will be added after this one (by
- # modifying their 'next' pointer).
+ # modifying 'next' pointers).
#
# 'prev' is reused to parse a list of child menu nodes (for a menu or
# Choice): After parsing the children, the 'next' pointer is assigned
sym.nodes.append(node)
- self._parse_properties(node)
+ self._parse_props(node)
if node.is_menuconfig and not node.prompt:
self._warn("the menuconfig symbol {} has no prompt"
- .format(_name_and_loc(sym)))
+ .format(sym.name_and_loc))
# Equivalent to
#
self.menus.append(node)
- self._parse_properties(node)
+ self._parse_props(node)
self._parse_block(_T_ENDMENU, node, node)
node.list = node.next
self.comments.append(node)
- self._parse_properties(node)
+ self._parse_props(node)
prev.next = prev = node
choice.nodes.append(node)
- self._parse_properties(node)
+ self._parse_props(node)
self._parse_block(_T_ENDCHOICE, node, node)
node.list = node.next
"no corresponding 'menu'" if t0 is _T_ENDMENU else
"unrecognized construct")
- # End of file reached. Terminate the final node and return it.
+ # End of file reached. Return the last node.
if end_token:
raise KconfigError(
- "expected '{}' at end of '{}'"
+ "error: expected '{}' at end of '{}'"
.format("endchoice" if end_token is _T_ENDCHOICE else
"endif" if end_token is _T_ENDIF else
"endmenu",
self.filename))
- prev.next = None
return prev
def _parse_cond(self):
return expr
- def _parse_properties(self, node):
+ def _parse_props(self, node):
# Parses and adds properties to the MenuNode 'node' (type, 'prompt',
# 'default's, etc.) Properties are later copied up to symbols and
# choices in a separate pass after parsing, in e.g.
if t0 in _TYPE_TOKENS:
# Relies on '_T_BOOL is BOOL', etc., to save a conversion
- self._set_type(node, t0)
+ self._set_type(node.item, t0)
if self._tokens[1] is not None:
self._parse_prompt(node)
self._parse_cond()))
elif t0 in _DEF_TOKEN_TO_TYPE:
- self._set_type(node, _DEF_TOKEN_TO_TYPE[t0])
+ self._set_type(node.item, _DEF_TOKEN_TO_TYPE[t0])
node.defaults.append((self._parse_expr(False),
self._parse_cond()))
self._reuse_tokens = True
return
- def _set_type(self, node, new_type):
+ def _set_type(self, sc, new_type):
+ # Sets the type of 'sc' (symbol or choice) to 'new_type'
+
# UNKNOWN is falsy
- if node.item.orig_type and node.item.orig_type is not new_type:
+ if sc.orig_type and sc.orig_type is not new_type:
self._warn("{} defined with multiple types, {} will be used"
- .format(_name_and_loc(node.item),
- TYPE_TO_STR[new_type]))
+ .format(sc.name_and_loc, TYPE_TO_STR[new_type]))
- node.item.orig_type = new_type
+ sc.orig_type = new_type
def _parse_prompt(self, node):
# 'prompt' properties override each other within a single definition of
# multiple times
if node.prompt:
- self._warn(_name_and_loc(node.item) +
+ self._warn(node.item.name_and_loc +
" defined with multiple prompts in single location")
prompt = self._tokens[1]
self._parse_error("expected prompt string")
if prompt != prompt.strip():
- self._warn(_name_and_loc(node.item) +
+ self._warn(node.item.name_and_loc +
" has leading or trailing whitespace in its prompt")
# This avoid issues for e.g. reStructuredText documentation, where
def _parse_help(self, node):
if node.help is not None:
- self._warn(_name_and_loc(node.item) + " defined with more than "
+ self._warn(node.item.name_and_loc + " defined with more than "
"one help text -- only the last one will be used")
# Micro-optimization. This code is pretty hot.
self._line_after_help(line)
def _empty_help(self, node, line):
- self._warn(_name_and_loc(node.item) +
+ self._warn(node.item.name_and_loc +
" has 'help' but empty help text")
node.help = ""
if line:
# The calculated sets might be larger than necessary as we don't do any
# complex analysis of the expressions.
- make_depend_on = _make_depend_on # Micro-optimization
+ depend_on = _depend_on # Micro-optimization
# Only calculate _dependents for defined symbols. Constant and
# undefined symbols could theoretically be selected/implied, but it
# The prompt conditions
for node in sym.nodes:
if node.prompt:
- make_depend_on(sym, node.prompt[1])
+ depend_on(sym, node.prompt[1])
# The default values and their conditions
for value, cond in sym.defaults:
- make_depend_on(sym, value)
- make_depend_on(sym, cond)
+ depend_on(sym, value)
+ depend_on(sym, cond)
# The reverse and weak reverse dependencies
- make_depend_on(sym, sym.rev_dep)
- make_depend_on(sym, sym.weak_rev_dep)
+ depend_on(sym, sym.rev_dep)
+ depend_on(sym, sym.weak_rev_dep)
# The ranges along with their conditions
for low, high, cond in sym.ranges:
- make_depend_on(sym, low)
- make_depend_on(sym, high)
- make_depend_on(sym, cond)
+ depend_on(sym, low)
+ depend_on(sym, high)
+ depend_on(sym, cond)
# The direct dependencies. This is usually redundant, as the direct
# dependencies get propagated to properties, but it's needed to get
# invalidation solid for 'imply', which only checks the direct
# dependencies (even if there are no properties to propagate it
# to).
- make_depend_on(sym, sym.direct_dep)
+ depend_on(sym, sym.direct_dep)
# In addition to the above, choice symbols depend on the choice
# they're in, but that's handled automatically since the Choice is
# The prompt conditions
for node in choice.nodes:
if node.prompt:
- make_depend_on(choice, node.prompt[1])
+ depend_on(choice, node.prompt[1])
# The default symbol conditions
for _, cond in choice.defaults:
- make_depend_on(choice, cond)
+ depend_on(choice, cond)
def _add_choice_deps(self):
# Choices also depend on the choice symbols themselves, because the
if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
self._warn("{} selects the {} symbol {}, which is not "
"bool or tristate"
- .format(_name_and_loc(sym),
+ .format(sym.name_and_loc,
TYPE_TO_STR[target_sym.orig_type],
- _name_and_loc(target_sym)))
+ target_sym.name_and_loc))
for target_sym, _ in sym.implies:
if target_sym.orig_type not in _BOOL_TRISTATE_UNKNOWN:
self._warn("{} implies the {} symbol {}, which is not "
"bool or tristate"
- .format(_name_and_loc(sym),
+ .format(sym.name_and_loc,
TYPE_TO_STR[target_sym.orig_type],
- _name_and_loc(target_sym)))
+ target_sym.name_and_loc))
elif sym.orig_type: # STRING/INT/HEX
for default, _ in sym.defaults:
if default.__class__ is not Symbol:
raise KconfigError(
- "the {} symbol {} has a malformed default {} -- expected "
- "a single symbol"
- .format(TYPE_TO_STR[sym.orig_type], _name_and_loc(sym),
- expr_str(default)))
+ "the {} symbol {} has a malformed default {} -- "
+ "expected a single symbol"
+ .format(TYPE_TO_STR[sym.orig_type],
+ sym.name_and_loc, expr_str(default)))
if sym.orig_type is STRING:
if not default.is_constant and not default.nodes and \
# (and no symbol named 'foo' exists).
self._warn("style: quotes recommended around "
"default value for string symbol "
- + _name_and_loc(sym))
+ + sym.name_and_loc)
elif not num_ok(default, sym.orig_type): # INT/HEX
self._warn("the {0} symbol {1} has a non-{0} default {2}"
.format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym),
- _name_and_loc(default)))
+ sym.name_and_loc,
+ default.name_and_loc))
if sym.selects or sym.implies:
self._warn("the {} symbol {} has selects or implies"
.format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym)))
+ sym.name_and_loc))
else: # UNKNOWN
self._warn("{} defined without a type"
- .format(_name_and_loc(sym)))
+ .format(sym.name_and_loc))
if sym.ranges:
self._warn(
"the {} symbol {} has ranges, but is not int or hex"
.format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym)))
+ sym.name_and_loc))
else:
for low, high, _ in sym.ranges:
if not num_ok(low, sym.orig_type) or \
self._warn("the {0} symbol {1} has a non-{0} "
"range [{2}, {3}]"
.format(TYPE_TO_STR[sym.orig_type],
- _name_and_loc(sym),
- _name_and_loc(low),
- _name_and_loc(high)))
+ sym.name_and_loc,
+ low.name_and_loc,
+ high.name_and_loc))
def _check_choice_sanity(self):
# Checks various choice properties that are handiest to check after
def warn_select_imply(sym, expr, expr_type):
msg = "the choice symbol {} is {} by the following symbols, but " \
"select/imply has no effect on choice symbols" \
- .format(_name_and_loc(sym), expr_type)
+ .format(sym.name_and_loc, expr_type)
# si = select/imply
for si in split_expr(expr, OR):
- msg += "\n - " + _name_and_loc(split_expr(si, AND)[0])
+ msg += "\n - " + split_expr(si, AND)[0].name_and_loc
self._warn(msg)
for choice in self.unique_choices:
if choice.orig_type not in _BOOL_TRISTATE:
self._warn("{} defined with type {}"
- .format(_name_and_loc(choice),
+ .format(choice.name_and_loc,
TYPE_TO_STR[choice.orig_type]))
for node in choice.nodes:
if node.prompt:
break
else:
- self._warn(_name_and_loc(choice) + " defined without a prompt")
+ self._warn(choice.name_and_loc + " defined without a prompt")
for default, _ in choice.defaults:
if default.__class__ is not Symbol:
raise KconfigError(
"{} has a malformed default {}"
- .format(_name_and_loc(choice), expr_str(default)))
+ .format(choice.name_and_loc, expr_str(default)))
if default.choice is not choice:
self._warn("the default selection {} of {} is not "
"contained in the choice"
- .format(_name_and_loc(default),
- _name_and_loc(choice)))
+ .format(default.name_and_loc,
+ choice.name_and_loc))
for sym in choice.syms:
if sym.defaults:
self._warn("default on the choice symbol {} will have "
"no effect, as defaults do not affect choice "
- "symbols".format(_name_and_loc(sym)))
+ "symbols".format(sym.name_and_loc))
if sym.rev_dep is not sym.kconfig.n:
warn_select_imply(sym, sym.rev_dep, "selected")
if node.parent.item is choice:
if not node.prompt:
self._warn("the choice symbol {} has no prompt"
- .format(_name_and_loc(sym)))
+ .format(sym.name_and_loc))
elif node.prompt:
self._warn("the choice symbol {} is defined with a "
"prompt outside the choice"
- .format(_name_and_loc(sym)))
+ .format(sym.name_and_loc))
def _parse_error(self, msg):
- raise KconfigError("{}couldn't parse '{}': {}".format(
+ raise KconfigError("{}error: couldn't parse '{}': {}".format(
"" if self.filename is None else
"{}:{}: ".format(self.filename, self.linenr),
self._line.strip(), msg))
The type as given in the Kconfig file, without any magic applied. Used
when printing the symbol.
+ tri_value:
+ The tristate value of the symbol as an integer. One of 0, 1, 2,
+ representing n, m, y. Always 0 (n) for non-bool/tristate symbols.
+
+ This is the symbol value that's used outside of relation expressions
+ (A, !A, A && B, A || B).
+
str_value:
The value of the symbol as a string. Gives the value for string/int/hex
symbols. For bool/tristate symbols, gives "n", "m", or "y".
This is the symbol value that's used in relational expressions
(A = B, A != B, etc.)
- Gotcha: For int/hex symbols, the exact format of the value must often be
- preserved (e.g., when writing a .config file), hence why you can't get it
+ Gotcha: For int/hex symbols, the exact format of the value is often
+ preserved (e.g. when writing a .config file), hence why you can't get it
directly as an int. Do int(int_sym.str_value) or
int(hex_sym.str_value, 16) to get the integer value.
- tri_value:
- The tristate value of the symbol as an integer. One of 0, 1, 2,
- representing n, m, y. Always 0 (n) for non-bool/tristate symbols.
+ user_value:
+ The user value of the symbol. None if no user value has been assigned
+ (via Kconfig.load_config() or Symbol.set_value()).
- This is the symbol value that's used outside of relation expressions
- (A, !A, A && B, A || B).
+ Holds 0, 1, or 2 for bool/tristate symbols, and a string for the other
+ symbol types.
+
+ WARNING: Do not assign directly to this. It will break things. Use
+ Symbol.set_value().
assignable:
A tuple containing the tristate user values that can currently be
The visibility of the symbol. One of 0, 1, 2, representing n, m, y. See
the module documentation for an overview of symbol values and visibility.
- user_value:
- The user value of the symbol. None if no user value has been assigned
- (via Kconfig.load_config() or Symbol.set_value()).
-
- Holds 0, 1, or 2 for bool/tristate symbols, and a string for the other
- symbol types.
-
- WARNING: Do not assign directly to this. It will break things. Use
- Symbol.set_value().
-
config_string:
The .config assignment string that would get written out for the symbol
by Kconfig.write_config(). Returns the empty string if no .config
though you might get some special symbols and possibly some "redundant"
n-valued symbol entries in there.
+ name_and_loc:
+ Holds a string like
+
+ "MY_SYMBOL (defined at foo/Kconfig:12, bar/Kconfig:14)"
+
+ , giving the name of the symbol and its definition location(s).
+
+ If the symbol is undefined, the location is given as "(undefined)".
+
nodes:
A list of MenuNodes for this symbol. Will contain a single MenuNode for
most symbols. Undefined and constant symbols have an empty nodes list.
"being outside the active range ([{}, {}]) -- falling "
"back on defaults"
.format(num2str(user_val), TYPE_TO_STR[self.orig_type],
- _name_and_loc(self),
+ self.name_and_loc,
num2str(low), num2str(high)))
else:
# If the user value is well-formed and satisfies range
self.kconfig._warn(
"default value {} on {} clamped to {} due to "
"being outside the active range ([{}, {}])"
- .format(val_num, _name_and_loc(self),
+ .format(val_num, self.name_and_loc,
num2str(clamp), num2str(low),
num2str(high)))
self.kconfig._warn(
"The {} symbol {} is being evaluated in a logical context "
"somewhere. It will always evaluate to n."
- .format(TYPE_TO_STR[self.orig_type], _name_and_loc(self)))
+ .format(TYPE_TO_STR[self.orig_type], self.name_and_loc))
self._cached_tri_val = 0
return 0
return '{}{}="{}"\n' \
.format(self.kconfig.config_prefix, self.name, escape(val))
+ @property
+ def name_and_loc(self):
+ """
+ See the class documentation.
+ """
+ return self.name + " " + _locs(self)
+
def set_value(self, value):
"""
Sets the user value of the symbol.
value:
The user value to give to the symbol. For bool and tristate symbols,
n/m/y can be specified either as 0/1/2 (the usual format for tristate
- values in Kconfiglib) or as one of the strings "n"/"m"/"y". For other
- symbol types, pass a string.
+ values in Kconfiglib) or as one of the strings "n", "m", or "y". For
+ other symbol types, pass a string.
Note that the value for an int/hex symbol is passed as a string, e.g.
"123" or "0x0123". The format of this string is preserved in the
"assignment ignored"
.format(TRI_TO_STR[value] if value in TRI_TO_STR else
"'{}'".format(value),
- _name_and_loc(self), TYPE_TO_STR[self.orig_type]))
+ self.name_and_loc, TYPE_TO_STR[self.orig_type]))
return False
return
if self.kconfig._warn_assign_no_prompt:
- self.kconfig._warn(_name_and_loc(self) + " has no prompt, meaning "
+ self.kconfig._warn(self.name_and_loc + " has no prompt, meaning "
"user values have no effect on it")
def _str_default(self):
msg = "{} has direct dependencies {} with value {}, but is " \
"currently being {}-selected by the following symbols:" \
- .format(_name_and_loc(self), expr_str(self.direct_dep),
+ .format(self.name_and_loc, expr_str(self.direct_dep),
TRI_TO_STR[expr_value(self.direct_dep)],
TRI_TO_STR[expr_value(self.rev_dep)])
msg += "\n - {}, with value {}, direct dependencies {} " \
"(value: {})" \
- .format(_name_and_loc(selecting_sym),
+ .format(selecting_sym.name_and_loc,
selecting_sym.str_value,
expr_str(selecting_sym.direct_dep),
TRI_TO_STR[expr_value(selecting_sym.direct_dep)])
Corresponding attributes have the same name in the Symbol and Choice
classes, for consistency and compatibility.
+ str_value:
+ Like choice.tri_value, but gives the value as one of the strings
+ "n", "m", or "y"
+
+ user_value:
+ The value (mode) selected by the user through Choice.set_value(). Either
+ 0, 1, or 2, or None if the user hasn't selected a mode. See
+ Symbol.user_value.
+
+ WARNING: Do not assign directly to this. It will break things. Use
+ Choice.set_value() instead.
+
assignable:
See the symbol class documentation. Gives the assignable values (modes).
- visibility:
- See the Symbol class documentation. Acts on the value (mode).
-
selection:
The Symbol instance of the currently selected symbol. None if the Choice
is not in y mode or has no selected symbol (due to unsatisfied
WARNING: Do not assign directly to this. It will break things. Call
sym.set_value(2) on the choice symbol you want to select instead.
- user_value:
- The value (mode) selected by the user through Choice.set_value(). Either
- 0, 1, or 2, or None if the user hasn't selected a mode. See
- Symbol.user_value.
-
- WARNING: Do not assign directly to this. It will break things. Use
- Choice.set_value() instead.
-
user_selection:
The symbol selected by the user (by setting it to y). Ignored if the
choice is not in y mode, but still remembered so that the choice "snaps
WARNING: Do not assign directly to this. It will break things. Call
sym.set_value(2) on the choice symbol to be selected instead.
+ visibility:
+ See the Symbol class documentation. Acts on the value (mode).
+
+ name_and_loc:
+ Holds a string like
+
+ "<choice MY_CHOICE> (defined at foo/Kconfig:12)"
+
+ , giving the name of the choice and its definition location(s). If the
+ choice has no name (isn't defined with 'choice MY_CHOICE'), then it will
+ be shown as "<choice>" before the list of locations (always a single one
+ in that case).
+
syms:
List of symbols contained in the choice.
return self._cached_vis
@property
+ def name_and_loc(self):
+ """
+ See the class documentation.
+ """
+ # Reuse the expression format, which is '<choice (name, if any)>'.
+ return standard_sc_expr_str(self) + " " + _locs(self)
+
+ @property
def selection(self):
"""
See the class documentation.
"assignment ignored"
.format(TRI_TO_STR[value] if value in TRI_TO_STR else
"'{}'".format(value),
- _name_and_loc(self), TYPE_TO_STR[self.orig_type]))
+ self.name_and_loc, TYPE_TO_STR[self.orig_type]))
return False
self._cached_selection = _NO_CACHED_SELECTION
- # is_constant is checked by _make_depend_on(). Just set it to avoid
- # having to special-case choices.
+ # is_constant is checked by _depend_on(). Just set it to avoid having
+ # to special-case choices.
self.is_constant = self.is_optional = False
# See Kconfig._build_dep()
_unescape_sub = re.compile(r"\\(.)").sub
-def standard_kconfig():
+def standard_kconfig(description=None):
"""
- Helper for tools. Loads the top-level Kconfig specified as the first
- command-line argument, or "Kconfig" if there are no command-line arguments.
- Returns the Kconfig instance.
+ Argument parsing helper for tools that take a single optional Kconfig file
+ argument (default: Kconfig). Returns the Kconfig instance for the parsed
+ configuration. Uses argparse internally.
+
+ Exits with sys.exit() (which raises SystemExit) on errors.
- Exits with sys.exit() (which raises a SystemExit exception) and prints a
- usage note to stderr if more than one command-line argument is passed.
+ description (default: None):
+ The 'description' passed to argparse.ArgumentParser().
+ argparse.RawDescriptionHelpFormatter is used, so formatting is preserved.
"""
- if len(sys.argv) > 2:
- sys.exit("usage: {} [Kconfig]".format(sys.argv[0]))
+ import argparse
- # Only show backtraces for unexpected exceptions
- try:
- return Kconfig("Kconfig" if len(sys.argv) < 2 else sys.argv[1])
- except (EnvironmentError, KconfigError) as e:
- # Some long exception messages have extra newlines for better
- # formatting when reported as an unhandled exception. Strip them here.
- sys.exit(str(e).strip())
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description=description)
+
+ parser.add_argument(
+ "kconfig",
+ metavar="KCONFIG",
+ default="Kconfig",
+ nargs="?",
+ help="Top-level Kconfig file (default: Kconfig)")
+
+ return Kconfig(parser.parse_args().kconfig, suppress_traceback=True)
def standard_config_filename():
def load_allconfig(kconf, filename):
"""
- Helper for all*config. Loads (merges) the configuration file specified by
- KCONFIG_ALLCONFIG, if any. See Documentation/kbuild/kconfig.txt in the
- Linux kernel.
-
- Disables warnings for duplicated assignments within configuration files for
- the duration of the call (kconf.warn_assign_override/warn_assign_redun = False),
- and restores the previous warning settings at the end. The
- KCONFIG_ALLCONFIG configuration file is expected to override symbols.
-
- Exits with sys.exit() (which raises a SystemExit exception) and prints an
- error to stderr if KCONFIG_ALLCONFIG is set but the configuration file
- can't be opened.
-
- kconf:
- Kconfig instance to load the configuration in.
-
- filename:
- Command-specific configuration filename - "allyes.config",
- "allno.config", etc.
+ Use Kconfig.load_allconfig() instead, which was added in Kconfiglib 13.4.0.
+ Supported for backwards compatibility. Might be removed at some point after
+ a long period of deprecation warnings.
"""
allconfig = os.getenv("KCONFIG_ALLCONFIG")
if allconfig is None:
return vis
-def _make_depend_on(sc, expr):
+def _depend_on(sc, expr):
# Adds 'sc' (symbol or choice) as a "dependee" to all symbols in 'expr'.
# Constant symbols in 'expr' are skipped as they can never change value
# anyway.
if expr.__class__ is tuple:
# AND, OR, NOT, or relation
- _make_depend_on(sc, expr[1])
+ _depend_on(sc, expr[1])
# NOTs only have a single operand
if expr[0] is not NOT:
- _make_depend_on(sc, expr[2])
+ _depend_on(sc, expr[2])
elif not expr.is_constant:
# Non-constant symbol, or choice
pass
-def _name_and_loc(sc):
- # Helper for giving the symbol/choice name and location(s) in e.g. warnings
+def _locs(sc):
+ # Symbol/Choice.name_and_loc helper. Returns the "(defined at ...)" part of
+ # the string. 'sc' is a Symbol or Choice.
- # Reuse the expression format. That way choices show up as
- # '<choice (name, if any)>'
- name = standard_sc_expr_str(sc)
+ if sc.nodes:
+ return "(defined at {})".format(
+ ", ".join("{0.filename}:{0.linenr}".format(node)
+ for node in sc.nodes))
- if not sc.nodes:
- return name + " (undefined)"
-
- return "{} (defined at {})".format(
- name,
- ", ".join("{}:{}".format(node.filename, node.linenr)
- for node in sc.nodes))
+ return "(undefined)"
# Menu manipulation
msg += "the choice symbol "
msg += "{}, with definition...\n\n{}\n\n" \
- .format(_name_and_loc(item), item)
+ .format(item.name_and_loc, item)
# Small wart: Since we reuse the already calculated
# Symbol/Choice._dependents sets for recursive dependency detection, we
msg += "(imply-related dependencies: {})\n\n" \
.format(expr_str(item.rev_dep))
- msg += "...depends again on {}".format(_name_and_loc(loop[0]))
+ msg += "...depends again on " + loop[0].name_and_loc
raise KconfigError(msg)
def _shell_fn(kconf, _, command):
- # Only import as needed, to save some startup time
- import subprocess
+ import subprocess # Only import as needed, to save some startup time
stdout, stderr = subprocess.Popen(
command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE
# variable assignment
_assignment_rhs_match = _re_match(r"\s*(=|:=|\+=)\s*(.*)")
-# Special characters/strings while expanding a macro (')', ',', and '$(')
-_macro_special_search = _re_search(r"\)|,|\$\(")
+# Special characters/strings while expanding a macro ('(', ')', ',', and '$(')
+_macro_special_search = _re_search(r"\(|\)|,|\$\(")
# Special characters/strings while expanding a string (quotes, '\', and '$(')
_string_special_search = _re_search(r'"|\'|\\|\$\(')