srcpos.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License as
  6. * published by the Free Software Foundation; either version 2 of the
  7. * License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  17. * USA
  18. */
  19. #define _GNU_SOURCE
  20. #include <stdio.h>
  21. #include "dtc.h"
  22. #include "srcpos.h"
  23. /* A node in our list of directories to search for source/include files */
  24. struct search_path {
  25. struct search_path *next; /* next node in list, NULL for end */
  26. const char *dirname; /* name of directory to search */
  27. };
  28. /* This is the list of directories that we search for source files */
  29. static struct search_path *search_path_head, **search_path_tail;
  30. static char *get_dirname(const char *path)
  31. {
  32. const char *slash = strrchr(path, '/');
  33. if (slash) {
  34. int len = slash - path;
  35. char *dir = xmalloc(len + 1);
  36. memcpy(dir, path, len);
  37. dir[len] = '\0';
  38. return dir;
  39. }
  40. return NULL;
  41. }
  42. FILE *depfile; /* = NULL */
  43. struct srcfile_state *current_srcfile; /* = NULL */
  44. /* Detect infinite include recursion. */
  45. #define MAX_SRCFILE_DEPTH (100)
  46. static int srcfile_depth; /* = 0 */
  47. /**
  48. * Try to open a file in a given directory.
  49. *
  50. * If the filename is an absolute path, then dirname is ignored. If it is a
  51. * relative path, then we look in that directory for the file.
  52. *
  53. * @param dirname Directory to look in, or NULL for none
  54. * @param fname Filename to look for
  55. * @param fp Set to NULL if file did not open
  56. * @return allocated filename on success (caller must free), NULL on failure
  57. */
  58. static char *try_open(const char *dirname, const char *fname, FILE **fp)
  59. {
  60. char *fullname;
  61. if (!dirname || fname[0] == '/')
  62. fullname = xstrdup(fname);
  63. else
  64. fullname = join_path(dirname, fname);
  65. *fp = fopen(fullname, "rb");
  66. if (!*fp) {
  67. free(fullname);
  68. fullname = NULL;
  69. }
  70. return fullname;
  71. }
  72. /**
  73. * Open a file for read access
  74. *
  75. * If it is a relative filename, we search the full search path for it.
  76. *
  77. * @param fname Filename to open
  78. * @param fp Returns pointer to opened FILE, or NULL on failure
  79. * @return pointer to allocated filename, which caller must free
  80. */
  81. static char *fopen_any_on_path(const char *fname, FILE **fp)
  82. {
  83. const char *cur_dir = NULL;
  84. struct search_path *node;
  85. char *fullname;
  86. /* Try current directory first */
  87. assert(fp);
  88. if (current_srcfile)
  89. cur_dir = current_srcfile->dir;
  90. fullname = try_open(cur_dir, fname, fp);
  91. /* Failing that, try each search path in turn */
  92. for (node = search_path_head; !*fp && node; node = node->next)
  93. fullname = try_open(node->dirname, fname, fp);
  94. return fullname;
  95. }
  96. FILE *srcfile_relative_open(const char *fname, char **fullnamep)
  97. {
  98. FILE *f;
  99. char *fullname;
  100. if (streq(fname, "-")) {
  101. f = stdin;
  102. fullname = xstrdup("<stdin>");
  103. } else {
  104. fullname = fopen_any_on_path(fname, &f);
  105. if (!f)
  106. die("Couldn't open \"%s\": %s\n", fname,
  107. strerror(errno));
  108. }
  109. if (depfile)
  110. fprintf(depfile, " %s", fullname);
  111. if (fullnamep)
  112. *fullnamep = fullname;
  113. else
  114. free(fullname);
  115. return f;
  116. }
  117. void srcfile_push(const char *fname)
  118. {
  119. struct srcfile_state *srcfile;
  120. if (srcfile_depth++ >= MAX_SRCFILE_DEPTH)
  121. die("Includes nested too deeply");
  122. srcfile = xmalloc(sizeof(*srcfile));
  123. srcfile->f = srcfile_relative_open(fname, &srcfile->name);
  124. srcfile->dir = get_dirname(srcfile->name);
  125. srcfile->prev = current_srcfile;
  126. srcfile->lineno = 1;
  127. srcfile->colno = 1;
  128. current_srcfile = srcfile;
  129. }
  130. bool srcfile_pop(void)
  131. {
  132. struct srcfile_state *srcfile = current_srcfile;
  133. assert(srcfile);
  134. current_srcfile = srcfile->prev;
  135. if (fclose(srcfile->f))
  136. die("Error closing \"%s\": %s\n", srcfile->name,
  137. strerror(errno));
  138. /* FIXME: We allow the srcfile_state structure to leak,
  139. * because it could still be referenced from a location
  140. * variable being carried through the parser somewhere. To
  141. * fix this we could either allocate all the files from a
  142. * table, or use a pool allocator. */
  143. return current_srcfile ? true : false;
  144. }
  145. void srcfile_add_search_path(const char *dirname)
  146. {
  147. struct search_path *node;
  148. /* Create the node */
  149. node = xmalloc(sizeof(*node));
  150. node->next = NULL;
  151. node->dirname = xstrdup(dirname);
  152. /* Add to the end of our list */
  153. if (search_path_tail)
  154. *search_path_tail = node;
  155. else
  156. search_path_head = node;
  157. search_path_tail = &node->next;
  158. }
  159. /*
  160. * The empty source position.
  161. */
  162. struct srcpos srcpos_empty = {
  163. .first_line = 0,
  164. .first_column = 0,
  165. .last_line = 0,
  166. .last_column = 0,
  167. .file = NULL,
  168. };
  169. void srcpos_update(struct srcpos *pos, const char *text, int len)
  170. {
  171. int i;
  172. pos->file = current_srcfile;
  173. pos->first_line = current_srcfile->lineno;
  174. pos->first_column = current_srcfile->colno;
  175. for (i = 0; i < len; i++)
  176. if (text[i] == '\n') {
  177. current_srcfile->lineno++;
  178. current_srcfile->colno = 1;
  179. } else {
  180. current_srcfile->colno++;
  181. }
  182. pos->last_line = current_srcfile->lineno;
  183. pos->last_column = current_srcfile->colno;
  184. }
  185. struct srcpos *
  186. srcpos_copy(struct srcpos *pos)
  187. {
  188. struct srcpos *pos_new;
  189. pos_new = xmalloc(sizeof(struct srcpos));
  190. memcpy(pos_new, pos, sizeof(struct srcpos));
  191. return pos_new;
  192. }
  193. char *
  194. srcpos_string(struct srcpos *pos)
  195. {
  196. const char *fname = "<no-file>";
  197. char *pos_str;
  198. if (pos->file && pos->file->name)
  199. fname = pos->file->name;
  200. if (pos->first_line != pos->last_line)
  201. xasprintf(&pos_str, "%s:%d.%d-%d.%d", fname,
  202. pos->first_line, pos->first_column,
  203. pos->last_line, pos->last_column);
  204. else if (pos->first_column != pos->last_column)
  205. xasprintf(&pos_str, "%s:%d.%d-%d", fname,
  206. pos->first_line, pos->first_column,
  207. pos->last_column);
  208. else
  209. xasprintf(&pos_str, "%s:%d.%d", fname,
  210. pos->first_line, pos->first_column);
  211. return pos_str;
  212. }
  213. void srcpos_verror(struct srcpos *pos, const char *prefix,
  214. const char *fmt, va_list va)
  215. {
  216. char *srcstr;
  217. srcstr = srcpos_string(pos);
  218. fprintf(stderr, "%s: %s ", prefix, srcstr);
  219. vfprintf(stderr, fmt, va);
  220. fprintf(stderr, "\n");
  221. free(srcstr);
  222. }
  223. void srcpos_error(struct srcpos *pos, const char *prefix,
  224. const char *fmt, ...)
  225. {
  226. va_list va;
  227. va_start(va, fmt);
  228. srcpos_verror(pos, prefix, fmt, va);
  229. va_end(va);
  230. }
  231. void srcpos_set_line(char *f, int l)
  232. {
  233. current_srcfile->name = f;
  234. current_srcfile->lineno = l;
  235. }