xref: /kernel/linux/linux-5.10/scripts/dtc/srcpos.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#define _GNU_SOURCE
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <stdio.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include "dtc.h"
118c2ecf20Sopenharmony_ci#include "srcpos.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci/* A node in our list of directories to search for source/include files */
148c2ecf20Sopenharmony_cistruct search_path {
158c2ecf20Sopenharmony_ci	struct search_path *next;	/* next node in list, NULL for end */
168c2ecf20Sopenharmony_ci	const char *dirname;		/* name of directory to search */
178c2ecf20Sopenharmony_ci};
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* This is the list of directories that we search for source files */
208c2ecf20Sopenharmony_cistatic struct search_path *search_path_head, **search_path_tail;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* Detect infinite include recursion. */
238c2ecf20Sopenharmony_ci#define MAX_SRCFILE_DEPTH     (100)
248c2ecf20Sopenharmony_cistatic int srcfile_depth; /* = 0 */
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_cistatic char *get_dirname(const char *path)
278c2ecf20Sopenharmony_ci{
288c2ecf20Sopenharmony_ci	const char *slash = strrchr(path, '/');
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	if (slash) {
318c2ecf20Sopenharmony_ci		int len = slash - path;
328c2ecf20Sopenharmony_ci		char *dir = xmalloc(len + 1);
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci		memcpy(dir, path, len);
358c2ecf20Sopenharmony_ci		dir[len] = '\0';
368c2ecf20Sopenharmony_ci		return dir;
378c2ecf20Sopenharmony_ci	}
388c2ecf20Sopenharmony_ci	return NULL;
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ciFILE *depfile; /* = NULL */
428c2ecf20Sopenharmony_cistruct srcfile_state *current_srcfile; /* = NULL */
438c2ecf20Sopenharmony_cistatic char *initial_path; /* = NULL */
448c2ecf20Sopenharmony_cistatic int initial_pathlen; /* = 0 */
458c2ecf20Sopenharmony_cistatic bool initial_cpp = true;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_cistatic void set_initial_path(char *fname)
488c2ecf20Sopenharmony_ci{
498c2ecf20Sopenharmony_ci	int i, len = strlen(fname);
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci	xasprintf(&initial_path, "%s", fname);
528c2ecf20Sopenharmony_ci	initial_pathlen = 0;
538c2ecf20Sopenharmony_ci	for (i = 0; i != len; i++)
548c2ecf20Sopenharmony_ci		if (initial_path[i] == '/')
558c2ecf20Sopenharmony_ci			initial_pathlen++;
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic char *shorten_to_initial_path(char *fname)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	char *p1, *p2, *prevslash1 = NULL;
618c2ecf20Sopenharmony_ci	int slashes = 0;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	for (p1 = fname, p2 = initial_path; *p1 && *p2; p1++, p2++) {
648c2ecf20Sopenharmony_ci		if (*p1 != *p2)
658c2ecf20Sopenharmony_ci			break;
668c2ecf20Sopenharmony_ci		if (*p1 == '/') {
678c2ecf20Sopenharmony_ci			prevslash1 = p1;
688c2ecf20Sopenharmony_ci			slashes++;
698c2ecf20Sopenharmony_ci		}
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci	p1 = prevslash1 + 1;
728c2ecf20Sopenharmony_ci	if (prevslash1) {
738c2ecf20Sopenharmony_ci		int diff = initial_pathlen - slashes, i, j;
748c2ecf20Sopenharmony_ci		int restlen = strlen(fname) - (p1 - fname);
758c2ecf20Sopenharmony_ci		char *res;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci		res = xmalloc((3 * diff) + restlen + 1);
788c2ecf20Sopenharmony_ci		for (i = 0, j = 0; i != diff; i++) {
798c2ecf20Sopenharmony_ci			res[j++] = '.';
808c2ecf20Sopenharmony_ci			res[j++] = '.';
818c2ecf20Sopenharmony_ci			res[j++] = '/';
828c2ecf20Sopenharmony_ci		}
838c2ecf20Sopenharmony_ci		strcpy(res + j, p1);
848c2ecf20Sopenharmony_ci		return res;
858c2ecf20Sopenharmony_ci	}
868c2ecf20Sopenharmony_ci	return NULL;
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci/**
908c2ecf20Sopenharmony_ci * Try to open a file in a given directory.
918c2ecf20Sopenharmony_ci *
928c2ecf20Sopenharmony_ci * If the filename is an absolute path, then dirname is ignored. If it is a
938c2ecf20Sopenharmony_ci * relative path, then we look in that directory for the file.
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * @param dirname	Directory to look in, or NULL for none
968c2ecf20Sopenharmony_ci * @param fname		Filename to look for
978c2ecf20Sopenharmony_ci * @param fp		Set to NULL if file did not open
988c2ecf20Sopenharmony_ci * @return allocated filename on success (caller must free), NULL on failure
998c2ecf20Sopenharmony_ci */
1008c2ecf20Sopenharmony_cistatic char *try_open(const char *dirname, const char *fname, FILE **fp)
1018c2ecf20Sopenharmony_ci{
1028c2ecf20Sopenharmony_ci	char *fullname;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (!dirname || fname[0] == '/')
1058c2ecf20Sopenharmony_ci		fullname = xstrdup(fname);
1068c2ecf20Sopenharmony_ci	else
1078c2ecf20Sopenharmony_ci		fullname = join_path(dirname, fname);
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	*fp = fopen(fullname, "rb");
1108c2ecf20Sopenharmony_ci	if (!*fp) {
1118c2ecf20Sopenharmony_ci		free(fullname);
1128c2ecf20Sopenharmony_ci		fullname = NULL;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	return fullname;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/**
1198c2ecf20Sopenharmony_ci * Open a file for read access
1208c2ecf20Sopenharmony_ci *
1218c2ecf20Sopenharmony_ci * If it is a relative filename, we search the full search path for it.
1228c2ecf20Sopenharmony_ci *
1238c2ecf20Sopenharmony_ci * @param fname	Filename to open
1248c2ecf20Sopenharmony_ci * @param fp	Returns pointer to opened FILE, or NULL on failure
1258c2ecf20Sopenharmony_ci * @return pointer to allocated filename, which caller must free
1268c2ecf20Sopenharmony_ci */
1278c2ecf20Sopenharmony_cistatic char *fopen_any_on_path(const char *fname, FILE **fp)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	const char *cur_dir = NULL;
1308c2ecf20Sopenharmony_ci	struct search_path *node;
1318c2ecf20Sopenharmony_ci	char *fullname;
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci	/* Try current directory first */
1348c2ecf20Sopenharmony_ci	assert(fp);
1358c2ecf20Sopenharmony_ci	if (current_srcfile)
1368c2ecf20Sopenharmony_ci		cur_dir = current_srcfile->dir;
1378c2ecf20Sopenharmony_ci	fullname = try_open(cur_dir, fname, fp);
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	/* Failing that, try each search path in turn */
1408c2ecf20Sopenharmony_ci	for (node = search_path_head; !*fp && node; node = node->next)
1418c2ecf20Sopenharmony_ci		fullname = try_open(node->dirname, fname, fp);
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci	return fullname;
1448c2ecf20Sopenharmony_ci}
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ciFILE *srcfile_relative_open(const char *fname, char **fullnamep)
1478c2ecf20Sopenharmony_ci{
1488c2ecf20Sopenharmony_ci	FILE *f;
1498c2ecf20Sopenharmony_ci	char *fullname;
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	if (streq(fname, "-")) {
1528c2ecf20Sopenharmony_ci		f = stdin;
1538c2ecf20Sopenharmony_ci		fullname = xstrdup("<stdin>");
1548c2ecf20Sopenharmony_ci	} else {
1558c2ecf20Sopenharmony_ci		fullname = fopen_any_on_path(fname, &f);
1568c2ecf20Sopenharmony_ci		if (!f)
1578c2ecf20Sopenharmony_ci			die("Couldn't open \"%s\": %s\n", fname,
1588c2ecf20Sopenharmony_ci			    strerror(errno));
1598c2ecf20Sopenharmony_ci	}
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	if (depfile)
1628c2ecf20Sopenharmony_ci		fprintf(depfile, " %s", fullname);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	if (fullnamep)
1658c2ecf20Sopenharmony_ci		*fullnamep = fullname;
1668c2ecf20Sopenharmony_ci	else
1678c2ecf20Sopenharmony_ci		free(fullname);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	return f;
1708c2ecf20Sopenharmony_ci}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_civoid srcfile_push(const char *fname)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	struct srcfile_state *srcfile;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
1778c2ecf20Sopenharmony_ci		die("Includes nested too deeply");
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ci	srcfile = xmalloc(sizeof(*srcfile));
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	srcfile->f = srcfile_relative_open(fname, &srcfile->name);
1828c2ecf20Sopenharmony_ci	srcfile->dir = get_dirname(srcfile->name);
1838c2ecf20Sopenharmony_ci	srcfile->prev = current_srcfile;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	srcfile->lineno = 1;
1868c2ecf20Sopenharmony_ci	srcfile->colno = 1;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	current_srcfile = srcfile;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (srcfile_depth == 1)
1918c2ecf20Sopenharmony_ci		set_initial_path(srcfile->name);
1928c2ecf20Sopenharmony_ci}
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_cibool srcfile_pop(void)
1958c2ecf20Sopenharmony_ci{
1968c2ecf20Sopenharmony_ci	struct srcfile_state *srcfile = current_srcfile;
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_ci	assert(srcfile);
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci	current_srcfile = srcfile->prev;
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci	if (fclose(srcfile->f))
2038c2ecf20Sopenharmony_ci		die("Error closing \"%s\": %s\n", srcfile->name,
2048c2ecf20Sopenharmony_ci		    strerror(errno));
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci	/* FIXME: We allow the srcfile_state structure to leak,
2078c2ecf20Sopenharmony_ci	 * because it could still be referenced from a location
2088c2ecf20Sopenharmony_ci	 * variable being carried through the parser somewhere.  To
2098c2ecf20Sopenharmony_ci	 * fix this we could either allocate all the files from a
2108c2ecf20Sopenharmony_ci	 * table, or use a pool allocator. */
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ci	return current_srcfile ? true : false;
2138c2ecf20Sopenharmony_ci}
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_civoid srcfile_add_search_path(const char *dirname)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	struct search_path *node;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	/* Create the node */
2208c2ecf20Sopenharmony_ci	node = xmalloc(sizeof(*node));
2218c2ecf20Sopenharmony_ci	node->next = NULL;
2228c2ecf20Sopenharmony_ci	node->dirname = xstrdup(dirname);
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	/* Add to the end of our list */
2258c2ecf20Sopenharmony_ci	if (search_path_tail)
2268c2ecf20Sopenharmony_ci		*search_path_tail = node;
2278c2ecf20Sopenharmony_ci	else
2288c2ecf20Sopenharmony_ci		search_path_head = node;
2298c2ecf20Sopenharmony_ci	search_path_tail = &node->next;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_civoid srcpos_update(struct srcpos *pos, const char *text, int len)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	int i;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	pos->file = current_srcfile;
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	pos->first_line = current_srcfile->lineno;
2398c2ecf20Sopenharmony_ci	pos->first_column = current_srcfile->colno;
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++)
2428c2ecf20Sopenharmony_ci		if (text[i] == '\n') {
2438c2ecf20Sopenharmony_ci			current_srcfile->lineno++;
2448c2ecf20Sopenharmony_ci			current_srcfile->colno = 1;
2458c2ecf20Sopenharmony_ci		} else {
2468c2ecf20Sopenharmony_ci			current_srcfile->colno++;
2478c2ecf20Sopenharmony_ci		}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci	pos->last_line = current_srcfile->lineno;
2508c2ecf20Sopenharmony_ci	pos->last_column = current_srcfile->colno;
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistruct srcpos *
2548c2ecf20Sopenharmony_cisrcpos_copy(struct srcpos *pos)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	struct srcpos *pos_new;
2578c2ecf20Sopenharmony_ci	struct srcfile_state *srcfile_state;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	if (!pos)
2608c2ecf20Sopenharmony_ci		return NULL;
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci	pos_new = xmalloc(sizeof(struct srcpos));
2638c2ecf20Sopenharmony_ci	assert(pos->next == NULL);
2648c2ecf20Sopenharmony_ci	memcpy(pos_new, pos, sizeof(struct srcpos));
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* allocate without free */
2678c2ecf20Sopenharmony_ci	srcfile_state = xmalloc(sizeof(struct srcfile_state));
2688c2ecf20Sopenharmony_ci	memcpy(srcfile_state, pos->file, sizeof(struct srcfile_state));
2698c2ecf20Sopenharmony_ci	pos_new->file = srcfile_state;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	return pos_new;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_cistruct srcpos *srcpos_extend(struct srcpos *pos, struct srcpos *newtail)
2758c2ecf20Sopenharmony_ci{
2768c2ecf20Sopenharmony_ci	struct srcpos *p;
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	if (!pos)
2798c2ecf20Sopenharmony_ci		return newtail;
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	for (p = pos; p->next != NULL; p = p->next);
2828c2ecf20Sopenharmony_ci	p->next = newtail;
2838c2ecf20Sopenharmony_ci	return pos;
2848c2ecf20Sopenharmony_ci}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_cichar *
2878c2ecf20Sopenharmony_cisrcpos_string(struct srcpos *pos)
2888c2ecf20Sopenharmony_ci{
2898c2ecf20Sopenharmony_ci	const char *fname = "<no-file>";
2908c2ecf20Sopenharmony_ci	char *pos_str;
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	if (pos->file && pos->file->name)
2938c2ecf20Sopenharmony_ci		fname = pos->file->name;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	if (pos->first_line != pos->last_line)
2978c2ecf20Sopenharmony_ci		xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
2988c2ecf20Sopenharmony_ci			  pos->first_line, pos->first_column,
2998c2ecf20Sopenharmony_ci			  pos->last_line, pos->last_column);
3008c2ecf20Sopenharmony_ci	else if (pos->first_column != pos->last_column)
3018c2ecf20Sopenharmony_ci		xasprintf(&pos_str, "%s:%d.%d-%d", fname,
3028c2ecf20Sopenharmony_ci			  pos->first_line, pos->first_column,
3038c2ecf20Sopenharmony_ci			  pos->last_column);
3048c2ecf20Sopenharmony_ci	else
3058c2ecf20Sopenharmony_ci		xasprintf(&pos_str, "%s:%d.%d", fname,
3068c2ecf20Sopenharmony_ci			  pos->first_line, pos->first_column);
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	return pos_str;
3098c2ecf20Sopenharmony_ci}
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_cistatic char *
3128c2ecf20Sopenharmony_cisrcpos_string_comment(struct srcpos *pos, bool first_line, int level)
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	char *pos_str, *fname, *first, *rest;
3158c2ecf20Sopenharmony_ci	bool fresh_fname = false;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	if (!pos) {
3188c2ecf20Sopenharmony_ci		if (level > 1) {
3198c2ecf20Sopenharmony_ci			xasprintf(&pos_str, "<no-file>:<no-line>");
3208c2ecf20Sopenharmony_ci			return pos_str;
3218c2ecf20Sopenharmony_ci		} else {
3228c2ecf20Sopenharmony_ci			return NULL;
3238c2ecf20Sopenharmony_ci		}
3248c2ecf20Sopenharmony_ci	}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_ci	if (!pos->file)
3278c2ecf20Sopenharmony_ci		fname = "<no-file>";
3288c2ecf20Sopenharmony_ci	else if (!pos->file->name)
3298c2ecf20Sopenharmony_ci		fname = "<no-filename>";
3308c2ecf20Sopenharmony_ci	else if (level > 1)
3318c2ecf20Sopenharmony_ci		fname = pos->file->name;
3328c2ecf20Sopenharmony_ci	else {
3338c2ecf20Sopenharmony_ci		fname = shorten_to_initial_path(pos->file->name);
3348c2ecf20Sopenharmony_ci		if (fname)
3358c2ecf20Sopenharmony_ci			fresh_fname = true;
3368c2ecf20Sopenharmony_ci		else
3378c2ecf20Sopenharmony_ci			fname = pos->file->name;
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (level > 1)
3418c2ecf20Sopenharmony_ci		xasprintf(&first, "%s:%d:%d-%d:%d", fname,
3428c2ecf20Sopenharmony_ci			  pos->first_line, pos->first_column,
3438c2ecf20Sopenharmony_ci			  pos->last_line, pos->last_column);
3448c2ecf20Sopenharmony_ci	else
3458c2ecf20Sopenharmony_ci		xasprintf(&first, "%s:%d", fname,
3468c2ecf20Sopenharmony_ci			  first_line ? pos->first_line : pos->last_line);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	if (fresh_fname)
3498c2ecf20Sopenharmony_ci		free(fname);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	if (pos->next != NULL) {
3528c2ecf20Sopenharmony_ci		rest = srcpos_string_comment(pos->next, first_line, level);
3538c2ecf20Sopenharmony_ci		xasprintf(&pos_str, "%s, %s", first, rest);
3548c2ecf20Sopenharmony_ci		free(first);
3558c2ecf20Sopenharmony_ci		free(rest);
3568c2ecf20Sopenharmony_ci	} else {
3578c2ecf20Sopenharmony_ci		pos_str = first;
3588c2ecf20Sopenharmony_ci	}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	return pos_str;
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cichar *srcpos_string_first(struct srcpos *pos, int level)
3648c2ecf20Sopenharmony_ci{
3658c2ecf20Sopenharmony_ci	return srcpos_string_comment(pos, true, level);
3668c2ecf20Sopenharmony_ci}
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_cichar *srcpos_string_last(struct srcpos *pos, int level)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	return srcpos_string_comment(pos, false, level);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_civoid srcpos_verror(struct srcpos *pos, const char *prefix,
3748c2ecf20Sopenharmony_ci		   const char *fmt, va_list va)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	char *srcstr;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	srcstr = srcpos_string(pos);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	fprintf(stderr, "%s: %s ", prefix, srcstr);
3818c2ecf20Sopenharmony_ci	vfprintf(stderr, fmt, va);
3828c2ecf20Sopenharmony_ci	fprintf(stderr, "\n");
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	free(srcstr);
3858c2ecf20Sopenharmony_ci}
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_civoid srcpos_error(struct srcpos *pos, const char *prefix,
3888c2ecf20Sopenharmony_ci		  const char *fmt, ...)
3898c2ecf20Sopenharmony_ci{
3908c2ecf20Sopenharmony_ci	va_list va;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	va_start(va, fmt);
3938c2ecf20Sopenharmony_ci	srcpos_verror(pos, prefix, fmt, va);
3948c2ecf20Sopenharmony_ci	va_end(va);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_civoid srcpos_set_line(char *f, int l)
3988c2ecf20Sopenharmony_ci{
3998c2ecf20Sopenharmony_ci	current_srcfile->name = f;
4008c2ecf20Sopenharmony_ci	current_srcfile->lineno = l;
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	if (initial_cpp) {
4038c2ecf20Sopenharmony_ci		initial_cpp = false;
4048c2ecf20Sopenharmony_ci		set_initial_path(f);
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci}
407