summaryrefslogtreecommitdiffstats
path: root/scripts/dtc/srcpos.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-08-23 13:28:57 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-08-23 13:28:57 -0700
commit4352b8aee98005853aa63f57d6377282de17a33f (patch)
tree27614d7a9ef05c32d089004e104364ce42324837 /scripts/dtc/srcpos.c
downloadlinux-stable-4352b8aee98005853aa63f57d6377282de17a33f.tar.gz
linux-stable-4352b8aee98005853aa63f57d6377282de17a33f.zip
Merge tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linuxgrafted
Pull I3C updates from Alexandre Belloni: "A new driver this cycle, for the AMD AXI I3C controller. There are also new features such as IBI wakeup support, SETAASA device discovery and ACPI support for the the DAA methods, meaning we can now communicate with the SPD devices on DDR5 modules. New driver: - AMD AXI I3C master controller Subsystem: - I3C Common Command Code (CCC) handling improvements, especially around GET CCCs - SETAASA device discovery support - ACPI support for all existing DAA methods like SETDASA, SETNEWDA as well as I2C devices on I3C bus - IBI-based wakeup support Drivers: - dw: SETAASA support - mipi-i3c-hci: advertise IBI wakeup capability, AMD_PT I3C controller support, PIO queue management support for HCI v1.2 - renesas: improve suspend to RAM support, add runtime PM support" * tag 'i3c/for-7.3' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux: (70 commits) i3c: dw: reduce do_daa time if there's no client i3c: mipi-i3c-hci: Add support for AMD_PT I3C controller i3c: mipi-i3c-hci: Add PIO queue management support for HCI v1.2 i3c: mipi-i3c-hci: Fix missing STAT_IBI_STATUS_THLD in PIO mode i3c: dw: rename "pclk" to "apb" to match dt-binding i3c: dw: make struct dw_i3c_cmd smaller i3c: dw: use COMMAND_PORT_TRANSFER_ARG instead of hardcoding i3c: renesas: Don't register devices when ENTDAA times out i3c: master: dw-i3c-master: fix OD timing for first broadcast i3c: mipi-i3c-hci: Advertise IBI wakeup capability i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI i3c: master: Reject IBI requests from non-IBI-capable devices i3c: master: Add helper to query bus wakeup requirements i3c: master: Report wakeup events for IBIs i3c: master: Support IBI-based wakeup capability i3c: master: Fix potential UAF in i3c_device_match() i3c: master: Fix potential UAF in i3c_device_uevent() i3c: Make dev->desc locking assumptions explicit i3c: master: Fix use-after-free of master->this ...
Diffstat (limited to 'scripts/dtc/srcpos.c')
-rw-r--r--scripts/dtc/srcpos.c441
1 files changed, 441 insertions, 0 deletions
diff --git a/scripts/dtc/srcpos.c b/scripts/dtc/srcpos.c
new file mode 100644
index 000000000..fef892fb6
--- /dev/null
+++ b/scripts/dtc/srcpos.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+
+/* A node in our list of directories to search for source/include files */
+struct search_path {
+ struct search_path *next; /* next node in list, NULL for end */
+ const char *dirname; /* name of directory to search */
+};
+
+/* This is the list of directories that we search for source files */
+static struct search_path *search_path_head, **search_path_tail;
+
+/* Detect infinite include recursion. */
+#define MAX_SRCFILE_DEPTH (200)
+static int srcfile_depth; /* = 0 */
+
+static char *get_dirname(const char *path)
+{
+ const char *slash = strrchr(path, '/');
+
+ if (slash) {
+ int len = slash - path;
+ char *dir = xmalloc(len + 1);
+
+ memcpy(dir, path, len);
+ dir[len] = '\0';
+ return dir;
+ }
+ return NULL;
+}
+
+FILE *depfile; /* = NULL */
+struct srcfile_state *current_srcfile; /* = NULL */
+static char *initial_path; /* = NULL */
+static int initial_pathlen; /* = 0 */
+static bool initial_cpp = true;
+
+static void set_initial_path(char *fname)
+{
+ int i, len = strlen(fname);
+
+ xasprintf(&initial_path, "%s", fname);
+ initial_pathlen = 0;
+ for (i = 0; i != len; i++)
+ if (initial_path[i] == '/')
+ initial_pathlen++;
+}
+
+static char *shorten_to_initial_path(char *fname)
+{
+ char *p1, *p2, *prevslash1 = NULL;
+ int slashes = 0;
+
+ for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
+ if (*p1 != *p2)
+ break;
+ if (*p1 == '/') {
+ prevslash1 = p1;
+ slashes++;
+ }
+ }
+ p1 = prevslash1 + 1;
+ if (prevslash1) {
+ int diff = initial_pathlen - slashes, i, j;
+ int restlen = strlen(fname) - (p1 - fname);
+ char *res;
+
+ res = xmalloc((3 * diff) + restlen + 1);
+ for (i = 0, j = 0; i != diff; i++) {
+ res[j++] = '.';
+ res[j++] = '.';
+ res[j++] = '/';
+ }
+ strcpy(res + j, p1);
+ return res;
+ }
+ return NULL;
+}
+
+/**
+ * Returns true if the given path is an absolute one.
+ *
+ * On Windows, it either needs to begin with a forward slash or with a drive
+ * letter (e.g. "C:").
+ * On all other operating systems, it must begin with a forward slash to be
+ * considered an absolute path.
+ */
+static bool is_absolute_path(const char *path)
+{
+#ifdef WIN32
+ return (
+ path[0] == '/' ||
+ (((path[0] >= 'A' && path[0] <= 'Z') || (path[0] >= 'a' && path[0] <= 'z')) && path[1] == ':')
+ );
+#else
+ return (path[0] == '/');
+#endif
+}
+
+/**
+ * Try to open a file in a given directory.
+ *
+ * If the filename is an absolute path, then dirname is ignored. If it is a
+ * relative path, then we look in that directory for the file.
+ *
+ * @param dirname Directory to look in, or NULL for none
+ * @param fname Filename to look for
+ * @param fp Set to NULL if file did not open
+ * @return allocated filename on success (caller must free), NULL on failure
+ */
+static char *try_open(const char *dirname, const char *fname, FILE **fp)
+{
+ char *fullname;
+
+ if (!dirname || is_absolute_path(fname))
+ fullname = xstrdup(fname);
+ else
+ fullname = join_path(dirname, fname);
+
+ *fp = fopen(fullname, "rb");
+ if (!*fp) {
+ free(fullname);
+ fullname = NULL;
+ }
+
+ return fullname;
+}
+
+/**
+ * Open a file for read access
+ *
+ * If it is a relative filename, we search the full search path for it.
+ *
+ * @param fname Filename to open
+ * @param fp Returns pointer to opened FILE, or NULL on failure
+ * @return pointer to allocated filename, which caller must free
+ */
+static char *fopen_any_on_path(const char *fname, FILE **fp)
+{
+ const char *cur_dir = NULL;
+ struct search_path *node;
+ char *fullname;
+
+ /* Try current directory first */
+ assert(fp);
+ if (current_srcfile)
+ cur_dir = current_srcfile->dir;
+ fullname = try_open(cur_dir, fname, fp);
+
+ /* Failing that, try each search path in turn */
+ for (node = search_path_head; !*fp && node; node = node->next)
+ fullname = try_open(node->dirname, fname, fp);
+
+ return fullname;
+}
+
+FILE *srcfile_relative_open(const char *fname, char **fullnamep)
+{
+ FILE *f;
+ char *fullname;
+
+ if (streq(fname, "-")) {
+ f = stdin;
+ fullname = xstrdup("<stdin>");
+ } else {
+ fullname = fopen_any_on_path(fname, &f);
+ if (!f)
+ die("Couldn't open \"%s\": %s\n", fname,
+ strerror(errno));
+ }
+
+ if (depfile) {
+ fputc(' ', depfile);
+ fprint_path_escaped(depfile, fullname);
+ }
+
+ if (fullnamep)
+ *fullnamep = fullname;
+ else
+ free(fullname);
+
+ return f;
+}
+
+void srcfile_push(const char *fname)
+{
+ struct srcfile_state *srcfile;
+
+ if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
+ die("Includes nested too deeply");
+
+ srcfile = xmalloc(sizeof(*srcfile));
+
+ srcfile->f = srcfile_relative_open(fname, &srcfile->name);
+ srcfile->dir = get_dirname(srcfile->name);
+ srcfile->prev = current_srcfile;
+
+ srcfile->lineno = 1;
+ srcfile->colno = 1;
+
+ current_srcfile = srcfile;
+
+ if (srcfile_depth == 1)
+ set_initial_path(srcfile->name);
+}
+
+bool srcfile_pop(void)
+{
+ struct srcfile_state *srcfile = current_srcfile;
+
+ assert(srcfile);
+
+ current_srcfile = srcfile->prev;
+
+ if (fclose(srcfile->f))
+ die("Error closing \"%s\": %s\n", srcfile->name,
+ strerror(errno));
+
+ /* FIXME: We allow the srcfile_state structure to leak,
+ * because it could still be referenced from a location
+ * variable being carried through the parser somewhere. To
+ * fix this we could either allocate all the files from a
+ * table, or use a pool allocator. */
+
+ return current_srcfile ? true : false;
+}
+
+void srcfile_add_search_path(const char *dirname)
+{
+ struct search_path *node;
+
+ /* Create the node */
+ node = xmalloc(sizeof(*node));
+ node->next = NULL;
+ node->dirname = xstrdup(dirname);
+
+ /* Add to the end of our list */
+ if (search_path_tail)
+ *search_path_tail = node;
+ else
+ search_path_head = node;
+ search_path_tail = &node->next;
+}
+
+void srcpos_update(struct srcpos *pos, const char *text, int len)
+{
+ int i;
+
+ pos->file = current_srcfile;
+
+ pos->first_line = current_srcfile->lineno;
+ pos->first_column = current_srcfile->colno;
+
+ for (i = 0; i < len; i++)
+ if (text[i] == '\n') {
+ current_srcfile->lineno++;
+ current_srcfile->colno = 1;
+ } else {
+ current_srcfile->colno++;
+ }
+
+ pos->last_line = current_srcfile->lineno;
+ pos->last_column = current_srcfile->colno;
+}
+
+struct srcpos *
+srcpos_copy(struct srcpos *pos)
+{
+ struct srcpos *pos_new;
+ struct srcfile_state *srcfile_state;
+
+ if (!pos)
+ return NULL;
+
+ pos_new = xmalloc(sizeof(struct srcpos));
+ assert(pos->next == NULL);
+ memcpy(pos_new, pos, sizeof(struct srcpos));
+
+ /* allocate without free */
+ srcfile_state = xmalloc(sizeof(struct srcfile_state));
+ memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
+ pos_new->file = srcfile_state;
+
+ return pos_new;
+}
+
+struct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
+{
+ struct srcpos *p;
+
+ if (!pos)
+ return newtail;
+
+ for (p = pos; p->next != NULL; p = p->next);
+ p->next = newtail;
+ return pos;
+}
+
+void srcpos_free(struct srcpos *pos)
+{
+ struct srcpos *p_next;
+
+ while (pos) {
+ p_next = pos->next;
+ free(pos);
+ pos = p_next;
+ }
+}
+
+char *
+srcpos_string(struct srcpos *pos)
+{
+ const char *fname = "<no-file>";
+ char *pos_str;
+
+ if (pos->file && pos->file->name)
+ fname = pos->file->name;
+
+
+ if (pos->first_line != pos->last_line)
+ xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else if (pos->first_column != pos->last_column)
+ xasprintf(&pos_str, "%s:%d.%d-%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_column);
+ else
+ xasprintf(&pos_str, "%s:%d.%d", fname,
+ pos->first_line, pos->first_column);
+
+ return pos_str;
+}
+
+static char *
+srcpos_string_comment(struct srcpos *pos, bool first_line, int level)
+{
+ char *pos_str, *fresh_fname = NULL, *first, *rest;
+ const char *fname;
+
+ if (!pos) {
+ if (level > 1) {
+ xasprintf(&pos_str, "<no-file>:<no-line>");
+ return pos_str;
+ } else {
+ return NULL;
+ }
+ }
+
+ if (!pos->file)
+ fname = "<no-file>";
+ else if (!pos->file->name)
+ fname = "<no-filename>";
+ else if (level > 1)
+ fname = pos->file->name;
+ else {
+ fresh_fname = shorten_to_initial_path(pos->file->name);
+ if (fresh_fname)
+ fname = fresh_fname;
+ else
+ fname = pos->file->name;
+ }
+
+ if (level > 1)
+ xasprintf(&first, "%s:%d:%d-%d:%d", fname,
+ pos->first_line, pos->first_column,
+ pos->last_line, pos->last_column);
+ else
+ xasprintf(&first, "%s:%d", fname,
+ first_line ? pos->first_line : pos->last_line);
+
+ if (fresh_fname)
+ free(fresh_fname);
+
+ if (pos->next != NULL) {
+ rest = srcpos_string_comment(pos->next, first_line, level);
+ xasprintf(&pos_str, "%s, %s", first, rest);
+ free(first);
+ free(rest);
+ } else {
+ pos_str = first;
+ }
+
+ return pos_str;
+}
+
+char *srcpos_string_first(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, true, level);
+}
+
+char *srcpos_string_last(struct srcpos *pos, int level)
+{
+ return srcpos_string_comment(pos, false, level);
+}
+
+void srcpos_verror(struct srcpos *pos, const char *prefix,
+ const char *fmt, va_list va)
+{
+ char *srcstr;
+
+ srcstr = srcpos_string(pos);
+
+ fprintf(stderr, "%s: %s ", prefix, srcstr);
+ vfprintf(stderr, fmt, va);
+ fprintf(stderr, "\n");
+
+ free(srcstr);
+}
+
+void srcpos_error(struct srcpos *pos, const char *prefix,
+ const char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ srcpos_verror(pos, prefix, fmt, va);
+ va_end(va);
+}
+
+void srcpos_set_line(char *f, int l)
+{
+ current_srcfile->name = f;
+ current_srcfile->lineno = l;
+
+ if (initial_cpp) {
+ initial_cpp = false;
+ set_initial_path(f);
+ }
+}