Handy for sharing declarations between libraries.
---
 forward.h          |  1 +
 prototype.c        |  2 +-
 read_config_file.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 read_config_file.h |  3 +-
 4 files changed, 87 insertions(+), 5 deletions(-)

diff --git a/forward.h b/forward.h
index 58d8f05..7bdc98c 100644
--- a/forward.h
+++ b/forward.h
@@ -33,6 +33,7 @@ struct param;
 struct param_enum;
 struct process;
 struct protolib;
+struct protolib_cache;
 struct prototype;
 struct timedelta;
 struct value;
diff --git a/prototype.c b/prototype.c
index 22e54c4..b09f945 100644
--- a/prototype.c
+++ b/prototype.c
@@ -639,7 +639,7 @@ protolib_cache_file(struct protolib_cache *cache,
 
        struct protolib *new_plib = build_default_config(cache, filename);
        if (new_plib == NULL
-           || read_config_file(stream, filename, new_plib) < 0) {
+           || read_config_file(stream, filename, cache, new_plib) < 0) {
                fclose(stream);
                if (own_filename)
                        free((char *) filename);
diff --git a/read_config_file.c b/read_config_file.c
index 56e3519..77cf976 100644
--- a/read_config_file.c
+++ b/read_config_file.c
@@ -217,6 +217,42 @@ parse_char(struct locus *loc, char **str, char expected)
        return 0;
 }
 
+static char *
+parse_string_literal(struct locus *loc, char **str)
+{
+       if (parse_char(loc, str, '"') < 0)
+               return NULL;
+
+       size_t len = strcspn(*str, "\"\n\\");
+       char terminator = (*str)[len];
+
+       if (terminator == '\0' || terminator == '\n') {
+               report_error(loc->filename, loc->line_no, "unmatched quote");
+               return NULL;
+       }
+
+       if (terminator == '\\') {
+               /* Strings are currently only used for filenames, where
+                * there's usually nothing to escape. Nevertheless, we reserve
+                * the backslash in case strings become used in other contexts
+                * where escaping is necessary. */
+               report_error(loc->filename, loc->line_no,
+                            "backslashes in string literals reserved for 
future use");
+               return NULL;
+       }
+
+       char *result = malloc(len + 1);
+       if (!result) {
+               report_error(loc->filename, loc->line_no,
+                            "malloc: %s", strerror(errno));
+               return NULL;
+       }
+       memcpy(result, *str, len);
+       result[len] = '\0';
+       (*str) += len + 1;
+       return result;
+}
+
 static struct expr_node *parse_argnum(struct locus *loc,
                                      char **str, int *ownp, int zero);
 
@@ -1060,8 +1096,46 @@ void_to_hidden_int(struct prototype *proto, struct param 
*param, void *data)
        return CBS_CONT;
 }
 
+static void
+parse_import(struct protolib_cache *cache, struct protolib *plib,
+             struct locus *loc, char **str)
+{
+       (*str) += strlen("import");
+       eat_spaces(str);
+
+       char *file_name = parse_string_literal(loc, str);
+       if (!file_name)
+               return;
+
+       eat_spaces(str);
+       if (parse_char(loc, str, ';') < 0) {
+               free(file_name);
+               return;
+       }
+
+       struct protolib *imported;
+
+       if (protolib_cache_maybe_load(cache, file_name, 1, true, &imported) < 
0) {
+               free(file_name);
+               return;
+       }
+
+       if (!imported) {
+               report_error(loc->filename, loc->line_no,
+                            "\"%s.conf\" not found", file_name);
+               free(file_name);
+               return;
+       }
+
+       if (protolib_add_import(plib, imported) < 0) {
+               report_error(loc->filename, loc->line_no,
+                            "import failed");
+       }
+}
+
 static int
-process_line(struct protolib *plib, struct locus *loc, char *buf)
+process_line(struct protolib_cache *cache, struct protolib *plib,
+             struct locus *loc, char *buf)
 {
        char *str = buf;
 
@@ -1072,6 +1146,11 @@ process_line(struct protolib *plib, struct locus *loc, 
char *buf)
        if (*str == ';' || *str == 0 || *str == '\n' || *str == '#')
                return 0;
 
+       if (strncmp(str, "import ", 7) == 0) {
+               parse_import(cache, plib, loc, &str);
+               return 0;
+       }
+
        if (strncmp(str, "typedef ", 8) == 0) {
                parse_typedef(plib, loc, &str);
                return 0;
@@ -1206,7 +1285,8 @@ process_line(struct protolib *plib, struct locus *loc, 
char *buf)
 }
 
 int
-read_config_file(FILE *stream, const char *path, struct protolib *plib)
+read_config_file(FILE *stream, const char *path,
+                 struct protolib_cache *cache, struct protolib *plib)
 {
        debug(DEBUG_FUNCTION, "Reading config file `%s'...", path);
 
@@ -1215,7 +1295,7 @@ read_config_file(FILE *stream, const char *path, struct 
protolib *plib)
        size_t len = 0;
        while (getline(&line, &len, stream) >= 0) {
                loc.line_no++;
-               process_line(plib, &loc, line);
+               process_line(cache, plib, &loc, line);
        }
 
        free(line);
diff --git a/read_config_file.h b/read_config_file.h
index 5a72a05..f5fc738 100644
--- a/read_config_file.h
+++ b/read_config_file.h
@@ -23,6 +23,7 @@
 
 #include "forward.h"
 
-int read_config_file(FILE *stream, const char *name, struct protolib *plib);
+int read_config_file(FILE *stream, const char *name,
+                     struct protolib_cache *cache, struct protolib *plib);
 
 #endif /* READ_CONFIG_FILE_H */
-- 
1.8.5.6


_______________________________________________
Ltrace-devel mailing list
[email protected]
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/ltrace-devel

Reply via email to