mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-01-17 06:32:16 +01:00
Synchronize local copy of DTC with Linux 6.17 . This includes the
following picked and squashed commits from Linux kernel. The squash
was necessary, since the DTC here contains changes which were also
part of DTC in Linux alraedy, and the squash helped resolve those
without going back and forth with the changes.
The following commits from Linux are picked:
8f324cd712df7 # scripts/dtc: consolidate include path options in Makefile
b5b3d9b63b0ee # scripts/dtc: Add yamltree.c to dtc sources
7d97a76f226d6 # scripts/dtc: Update to upstream version v1.4.7-14-gc86da84d30e4
ea6f243be74e5 # scripts/dtc: Update to upstream version v1.4.7-57-gf267e674d145
02d435d4eccd8 # scripts/dtc: Update to upstream version v1.5.0-23-g87963ee20693
6e321b7637396 # scripts/dtc: Update to upstream version v1.5.0-30-g702c1b6c0e73
9f19ec91a7a35 # scripts/dtc: dtx_diff - add color output support
8287d642f38d1 # scripts/dtc: Update to upstream version v1.5.1-22-gc40aeb60b47a
4c52deef9225d # scripts/dtc: Revert "yamltree: Ensure consistent bracketing of properties with phandles"
5d3827e1452ed # scripts/dtc: Remove unused makefile fragments
40dd266887654 # scripts/dtc: Update to upstream version v1.6.0-2-g87a656ae5ff9
8d4cf6b6acb59 # scripts/dtc: use pkg-config to include <yaml.h> in non-standard path
b9bf9ace5ae90 # scripts/dtc: Update to upstream version v1.6.0-11-g9d7888cbf19c
69a883b6f5ac0 # scripts/dtc: dtx_diff - make help text formatting consistent
8f829108b8aed # scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting
b39b4342ac495 # scripts/dtc: Update to upstream version v1.6.0-31-gcbca977ea121
93c6424c486b3 # scripts: dtc: Fetch fdtoverlay.c from external DTC project
0dd574a1d75c3 # scripts/dtc: Update to upstream version v1.6.0-51-g183df9e9c2b9
ec38b5df8a231 # scripts: dtc: Build fdtoverlay tool
a0c8c431411f5 # scripts: dtc: Remove the unused fdtdump.c file
e7dc653d4e890 # scripts/dtc: Add missing fdtoverlay to gitignore
d2bf5d2e3f09c # scripts/dtc: Update to upstream version v1.6.1-19-g0a3a9d3449c8
a60878f5532d0 # scripts/dtc: dtx_diff: remove broken example from help text
8b739d8658a9b # scripts/dtc: Call pkg-config POSIXly correct
b6eeafa67df00 # scripts/dtc: Update to upstream version v1.6.1-63-g55778a03df61
f96cc4c787588 # scripts/dtc: Update to upstream version v1.6.1-66-gabbd523bae6e
09ab9c092ef2b # scripts/dtc: Update to upstream version v1.7.0-93-g1df7b047fe43
ded8a5a498f2d # scripts/dtc: Update to upstream version v1.7.0-95-gbcd02b523429
ee6ff6fca7e71 # scripts/dtc: Update to upstream version v1.7.2-35-g52f07dcca47c
This also includes forward port of U-Boot commit
e8c2d25845c7 ("libfdt: Revert 6dcb8ba4 from upstream libfdt")
to avoid binary size growth.
Signed-off-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
421 lines
8.8 KiB
C
421 lines
8.8 KiB
C
// 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;
|
|
}
|
|
|
|
/**
|
|
* 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 || fname[0] == '/')
|
|
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);
|
|
}
|
|
}
|