summaryrefslogtreecommitdiffstats
path: root/scripts/dtc/srcpos.c
diff options
context:
space:
mode:
authorZeng Chi <zengchi@kylinos.cn>2026-09-21 18:24:42 +0800
committerSean Christopherson <seanjc@google.com>2026-09-22 08:36:16 -0700
commit119e9db233ad0f4cbd4cfb9f9385a7bca378b37d (patch)
tree660d50d4139cb750fbde1ae3432452c20726c99d /scripts/dtc/srcpos.c
downloadlinux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.tar.gz
linux-stable-119e9db233ad0f4cbd4cfb9f9385a7bca378b37d.zip
KVM: Don't pre-reserve xarray entries when storing empty/NULL attributesgrafted
Skip the xarray reservation loop when clearing all memory attributes, as storing NULL only erases the entry and never needs to allocate, so no reservation (and no cleanup of a failed one) is required in that case. Suggested-by: Sean Christopherson <seanjc@google.com> Cc: David Ballesteros <davimaba.v@proton.me> Signed-off-by: Zeng Chi <zengchi@kylinos.cn> Link: https://patch.msgid.link/20260921102442.1232375-1-zeng_chi911@163.com [sean: split to separate patch] Signed-off-by: Sean Christopherson <seanjc@google.com>
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);
+ }
+}