diff options
-rw-r--r-- | dtc.c | 8 | ||||
-rw-r--r-- | srcpos.c | 92 | ||||
-rw-r--r-- | srcpos.h | 29 | ||||
-rwxr-xr-x | tests/run_tests.sh | 11 | ||||
-rw-r--r-- | tests/search_dir/search_test.dtsi | 4 | ||||
-rw-r--r-- | tests/search_dir/search_test2.dtsi | 3 | ||||
-rw-r--r-- | tests/search_dir_b/search_paths_subdir.dts | 6 | ||||
-rw-r--r-- | tests/search_dir_b/search_test_b.dtsi | 4 | ||||
-rw-r--r-- | tests/search_dir_b/search_test_b2.dtsi | 5 | ||||
-rw-r--r-- | tests/search_dir_b/search_test_c.dtsi | 2 | ||||
-rw-r--r-- | tests/search_paths.dts | 6 | ||||
-rw-r--r-- | tests/search_paths_b.dts | 6 |
12 files changed, 168 insertions, 8 deletions
@@ -82,6 +82,8 @@ static void __attribute__ ((noreturn)) usage(void) fprintf(stderr, "\t\tSet the physical boot cpu\n"); fprintf(stderr, "\t-f\n"); fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n"); + fprintf(stderr, "\t-i\n"); + fprintf(stderr, "\t\tAdd a path to search for include files\n"); fprintf(stderr, "\t-s\n"); fprintf(stderr, "\t\tSort nodes and properties before outputting (only useful for\n\t\tcomparing trees)\n"); fprintf(stderr, "\t-v\n"); @@ -113,7 +115,8 @@ int main(int argc, char *argv[]) minsize = 0; padsize = 0; - while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:vH:s")) != EOF) { + while ((opt = getopt(argc, argv, "hI:O:o:V:d:R:S:p:fqb:i:vH:s")) + != EOF) { switch (opt) { case 'I': inform = optarg; @@ -148,6 +151,9 @@ int main(int argc, char *argv[]) case 'b': cmdline_boot_cpuid = strtoll(optarg, NULL, 0); break; + case 'i': + srcfile_add_search_path(optarg); + break; case 'v': printf("Version: %s\n", DTC_VERSION); exit(0); @@ -24,6 +24,15 @@ #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; + static char *dirname(const char *path) { @@ -47,6 +56,64 @@ struct srcfile_state *current_srcfile; /* = NULL */ #define MAX_SRCFILE_DEPTH (100) static int srcfile_depth; /* = 0 */ + +/** + * 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, "r"); + 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; @@ -56,13 +123,7 @@ FILE *srcfile_relative_open(const char *fname, char **fullnamep) f = stdin; fullname = xstrdup("<stdin>"); } else { - if (!current_srcfile || !current_srcfile->dir - || (fname[0] == '/')) - fullname = xstrdup(fname); - else - fullname = join_path(current_srcfile->dir, fname); - - f = fopen(fullname, "r"); + fullname = fopen_any_on_path(fname, &f); if (!f) die("Couldn't open \"%s\": %s\n", fname, strerror(errno)); @@ -119,6 +180,23 @@ int srcfile_pop(void) return current_srcfile ? 1 : 0; } +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; +} + /* * The empty source position. */ @@ -33,10 +33,39 @@ struct srcfile_state { extern FILE *depfile; /* = NULL */ extern struct srcfile_state *current_srcfile; /* = NULL */ +/** + * Open a source file. + * + * If the source file is a relative pathname, then it is searched for in the + * current directory (the directory of the last source file read) and after + * that in the search path. + * + * We work through the search path in order from the first path specified to + * the last. + * + * If the file is not found, then this function does not return, but calls + * die(). + * + * @param fname Filename to search + * @param fullnamep If non-NULL, it is set to the allocated filename of the + * file that was opened. The caller is then responsible + * for freeing the pointer. + * @return pointer to opened FILE + */ FILE *srcfile_relative_open(const char *fname, char **fullnamep); + void srcfile_push(const char *fname); int srcfile_pop(void); +/** + * Add a new directory to the search path for input files + * + * The new path is added at the end of the list. + * + * @param dirname Directory to add + */ +void srcfile_add_search_path(const char *dirname); + struct srcpos { int first_line; int first_column; diff --git a/tests/run_tests.sh b/tests/run_tests.sh index deffae3..e470b82 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -412,6 +412,17 @@ dtc_tests () { # Dependencies run_dtc_test -I dts -O dtb -o dependencies.test.dtb -d dependencies.test.d dependencies.dts run_wrap_test cmp dependencies.test.d dependencies.cmp + + # Search paths + run_wrap_error_test $DTC -I dts -O dtb -o search_paths.dtb search_paths.dts + run_dtc_test -i search_dir -I dts -O dtb -o search_paths.dtb \ + search_paths.dts + run_wrap_error_test $DTC -i search_dir_b -I dts -O dtb \ + -o search_paths_b.dtb search_paths_b.dts + run_dtc_test -i search_dir_b -i search_dir -I dts -O dtb \ + -o search_paths_b.dtb search_paths_b.dts + run_dtc_test -I dts -O dtb -o search_paths_subdir.dtb \ + search_dir_b/search_paths_subdir.dts } cmp_tests () { diff --git a/tests/search_dir/search_test.dtsi b/tests/search_dir/search_test.dtsi new file mode 100644 index 0000000..217fb80 --- /dev/null +++ b/tests/search_dir/search_test.dtsi @@ -0,0 +1,4 @@ +/include/ "search_test2.dtsi" + +/ { +}; diff --git a/tests/search_dir/search_test2.dtsi b/tests/search_dir/search_test2.dtsi new file mode 100644 index 0000000..7b9099e --- /dev/null +++ b/tests/search_dir/search_test2.dtsi @@ -0,0 +1,3 @@ + +/ { +}; diff --git a/tests/search_dir_b/search_paths_subdir.dts b/tests/search_dir_b/search_paths_subdir.dts new file mode 100644 index 0000000..5c5c962 --- /dev/null +++ b/tests/search_dir_b/search_paths_subdir.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test_c.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_b.dtsi b/tests/search_dir_b/search_test_b.dtsi new file mode 100644 index 0000000..b06a7d6 --- /dev/null +++ b/tests/search_dir_b/search_test_b.dtsi @@ -0,0 +1,4 @@ +/include/ "search_test_b2.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_b2.dtsi b/tests/search_dir_b/search_test_b2.dtsi new file mode 100644 index 0000000..2526b43 --- /dev/null +++ b/tests/search_dir_b/search_test_b2.dtsi @@ -0,0 +1,5 @@ + +/include/ "search_test.dtsi" + +/ { +}; diff --git a/tests/search_dir_b/search_test_c.dtsi b/tests/search_dir_b/search_test_c.dtsi new file mode 100644 index 0000000..336d7a2 --- /dev/null +++ b/tests/search_dir_b/search_test_c.dtsi @@ -0,0 +1,2 @@ +/ { +}; diff --git a/tests/search_paths.dts b/tests/search_paths.dts new file mode 100644 index 0000000..a2bf179 --- /dev/null +++ b/tests/search_paths.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test.dtsi" + +/ { +}; diff --git a/tests/search_paths_b.dts b/tests/search_paths_b.dts new file mode 100644 index 0000000..6ace6e2 --- /dev/null +++ b/tests/search_paths_b.dts @@ -0,0 +1,6 @@ +/dts-v1/; + +/include/ "search_test_b.dtsi" + +/ { +}; |