It is often inconvenient to place device tree files in the same directory
as their includes, or to specify the full path to include files.

An example of this is in U-Boot where we have a .dtsi file for each SOC
type, and this is included by the board .dts file. We need to either use
a mechanism like:

/include/ ARCH_CPU_DTS

with sed or cpp to perform the replacement with the correct path, or
we must specify the full path in the file:

/include/ "../../arch/arm/dts/tegra20.dtsi"

The first option is not desirable since it requires anyone compiling the
file to first pre-process it. The second is not desirable since it
introduces a path which is project-specific into a file which is supposed
to be a hardware description. For example Linux and U-Boot are unlikely to
put these include files in the same place.

It is much more convenient to specify the search patch on the command line
as is done with C pre-processors, for example.

Introduce a -i option to add to the list of search paths used to find
source and include files.

We cannot use -I as it is already in use. Other suggestions welcome.

Signed-off-by: Simon Glass <s...@chromium.org>
---
 dtc.c                                  |    8 +++-
 srcpos.c                               |   86 +++++++++++++++++++++++++++++---
 srcpos.h                               |   35 +++++++++++++
 tests/run_tests.sh                     |    9 +++
 tests/search_dir/search_test.dtsi      |    4 ++
 tests/search_dir/search_test2.dtsi     |    3 +
 tests/search_dir_b/search_test_b.dtsi  |    4 ++
 tests/search_dir_b/search_test_b2.dtsi |    5 ++
 tests/search_paths.dts                 |    6 ++
 tests/search_paths_b.dts               |    6 ++
 10 files changed, 158 insertions(+), 8 deletions(-)
 create mode 100644 tests/search_dir/search_test.dtsi
 create mode 100644 tests/search_dir/search_test2.dtsi
 create mode 100644 tests/search_dir_b/search_test_b.dtsi
 create mode 100644 tests/search_dir_b/search_test_b2.dtsi
 create mode 100644 tests/search_paths.dts
 create mode 100644 tests/search_paths_b.dts

diff --git a/dtc.c b/dtc.c
index 7a0c605..83aef32 100644
--- a/dtc.c
+++ b/dtc.c
@@ -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);
diff --git a/srcpos.c b/srcpos.c
index 36a38e9..dacec92 100644
--- a/srcpos.c
+++ b/srcpos.c
@@ -24,6 +24,9 @@
 #include "dtc.h"
 #include "srcpos.h"
 
+/* 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 +50,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 (called 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 +117,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 +174,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.
  */
diff --git a/srcpos.h b/srcpos.h
index ce980ca..4a0bcb5 100644
--- a/srcpos.h
+++ b/srcpos.h
@@ -30,13 +30,48 @@ struct srcfile_state {
        struct srcfile_state *prev;
 };
 
+/* A 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 */
+};
+
 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 a561433..c7e9b83 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -412,6 +412,15 @@ 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
 }
 
 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_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_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"
+
+/ {
+};
-- 
1.7.7.3

_______________________________________________
devicetree-discuss mailing list
devicetree-discuss@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/devicetree-discuss

Reply via email to