lib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*
  2. * 'sparse' library helper routines.
  3. *
  4. * Copyright (C) 2003 Transmeta Corp.
  5. * 2003-2004 Linus Torvalds
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include <ctype.h>
  26. #include <errno.h>
  27. #include <fcntl.h>
  28. #include <stdarg.h>
  29. #include <stddef.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <unistd.h>
  34. #include <assert.h>
  35. #include <sys/types.h>
  36. #include "lib.h"
  37. #include "allocate.h"
  38. #include "token.h"
  39. #include "parse.h"
  40. #include "symbol.h"
  41. #include "expression.h"
  42. #include "evaluate.h"
  43. #include "scope.h"
  44. #include "linearize.h"
  45. #include "target.h"
  46. #include "machine.h"
  47. #include "version.h"
  48. #include "bits.h"
  49. static int prettify(const char **fnamep)
  50. {
  51. const char *name = *fnamep;
  52. int len = strlen(name);
  53. if (len > 2 && !memcmp(name, "./", 2)) {
  54. name += 2;
  55. len -= 2;
  56. }
  57. *fnamep = name;
  58. return len;
  59. }
  60. static const char *show_include_chain(int stream, const char *base)
  61. {
  62. static char buffer[200];
  63. int len = 0;
  64. while ((stream = stream_prev(stream)) >= 0) {
  65. const char *p = stream_name(stream);
  66. int pretty_len;
  67. if (p == base)
  68. break;
  69. pretty_len = prettify(&p);
  70. if (pretty_len <= 0)
  71. break;
  72. /*
  73. * At worst, we'll need " (through %s, ...)" in addition to the
  74. * new filename
  75. */
  76. if (pretty_len + len + 20 > sizeof(buffer)) {
  77. if (!len)
  78. return "";
  79. memcpy(buffer+len, ", ...", 5);
  80. len += 5;
  81. break;
  82. }
  83. if (!len) {
  84. memcpy(buffer, " (through ", 10);
  85. len = 10;
  86. } else {
  87. buffer[len++] = ',';
  88. buffer[len++] = ' ';
  89. }
  90. memcpy(buffer+len, p, pretty_len);
  91. len += pretty_len;
  92. }
  93. if (!len)
  94. return "";
  95. buffer[len] = ')';
  96. buffer[len+1] = 0;
  97. return buffer;
  98. }
  99. static const char *show_stream_name(struct position pos)
  100. {
  101. const char *name = stream_name(pos.stream);
  102. static const char *last;
  103. if (name == base_filename)
  104. return name;
  105. if (name == last)
  106. return name;
  107. last = name;
  108. fprintf(stderr, "%s: note: in included file%s:\n",
  109. base_filename,
  110. show_include_chain(pos.stream, base_filename));
  111. return name;
  112. }
  113. static void do_warn(const char *type, struct position pos, const char * fmt, va_list args)
  114. {
  115. static char buffer[512];
  116. /* Shut up warnings if position is bad_token.pos */
  117. if (pos.type == TOKEN_BAD)
  118. return;
  119. vsprintf(buffer, fmt, args);
  120. fflush(stdout);
  121. fprintf(stderr, "%s:%d:%d: %s%s%s\n",
  122. show_stream_name(pos), pos.line, pos.pos,
  123. diag_prefix, type, buffer);
  124. }
  125. static int show_info = 1;
  126. void info(struct position pos, const char * fmt, ...)
  127. {
  128. va_list args;
  129. if (!show_info)
  130. return;
  131. va_start(args, fmt);
  132. do_warn("", pos, fmt, args);
  133. va_end(args);
  134. }
  135. static void do_error(struct position pos, const char * fmt, va_list args)
  136. {
  137. static int errors = 0;
  138. die_if_error = 1;
  139. show_info = 1;
  140. /* Shut up warnings if position is bad_token.pos */
  141. if (pos.type == TOKEN_BAD)
  142. return;
  143. /* Shut up warnings after an error */
  144. has_error |= ERROR_CURR_PHASE;
  145. if (errors > fmax_errors) {
  146. static int once = 0;
  147. show_info = 0;
  148. if (once)
  149. return;
  150. fmt = "too many errors";
  151. once = 1;
  152. }
  153. do_warn("error: ", pos, fmt, args);
  154. errors++;
  155. }
  156. void warning(struct position pos, const char * fmt, ...)
  157. {
  158. va_list args;
  159. if (Wsparse_error) {
  160. va_start(args, fmt);
  161. do_error(pos, fmt, args);
  162. va_end(args);
  163. return;
  164. }
  165. if (!fmax_warnings || has_error) {
  166. show_info = 0;
  167. return;
  168. }
  169. if (!--fmax_warnings) {
  170. show_info = 0;
  171. fmt = "too many warnings";
  172. }
  173. va_start(args, fmt);
  174. do_warn("warning: ", pos, fmt, args);
  175. va_end(args);
  176. }
  177. void sparse_error(struct position pos, const char * fmt, ...)
  178. {
  179. va_list args;
  180. va_start(args, fmt);
  181. do_error(pos, fmt, args);
  182. va_end(args);
  183. }
  184. void expression_error(struct expression *expr, const char *fmt, ...)
  185. {
  186. va_list args;
  187. va_start(args, fmt);
  188. do_error(expr->pos, fmt, args);
  189. va_end(args);
  190. expr->ctype = &bad_ctype;
  191. }
  192. NORETURN_ATTR
  193. void error_die(struct position pos, const char * fmt, ...)
  194. {
  195. va_list args;
  196. va_start(args, fmt);
  197. do_warn("error: ", pos, fmt, args);
  198. va_end(args);
  199. exit(1);
  200. }
  201. NORETURN_ATTR
  202. void die(const char *fmt, ...)
  203. {
  204. va_list args;
  205. static char buffer[512];
  206. va_start(args, fmt);
  207. vsnprintf(buffer, sizeof(buffer), fmt, args);
  208. va_end(args);
  209. fprintf(stderr, "%s%s\n", diag_prefix, buffer);
  210. exit(1);
  211. }
  212. ////////////////////////////////////////////////////////////////////////////////
  213. static struct token *pre_buffer_begin = NULL;
  214. static struct token **pre_buffer_next = &pre_buffer_begin;
  215. void add_pre_buffer(const char *fmt, ...)
  216. {
  217. va_list args;
  218. unsigned int size;
  219. struct token *begin, *end;
  220. char buffer[4096];
  221. va_start(args, fmt);
  222. size = vsnprintf(buffer, sizeof(buffer), fmt, args);
  223. va_end(args);
  224. begin = tokenize_buffer(buffer, size, &end);
  225. *pre_buffer_next = begin;
  226. pre_buffer_next = &end->next;
  227. }
  228. static void create_builtin_stream(void)
  229. {
  230. // Temporary hack
  231. add_pre_buffer("#define _Pragma(x)\n");
  232. /* add the multiarch include directories, if any */
  233. if (multiarch_dir && *multiarch_dir) {
  234. add_pre_buffer("#add_system \"/usr/include/%s\"\n", multiarch_dir);
  235. add_pre_buffer("#add_system \"/usr/local/include/%s\"\n", multiarch_dir);
  236. }
  237. /* We add compiler headers path here because we have to parse
  238. * the arguments to get it, falling back to default. */
  239. add_pre_buffer("#add_system \"%s/include\"\n", gcc_base_dir);
  240. add_pre_buffer("#add_system \"%s/include-fixed\"\n", gcc_base_dir);
  241. add_pre_buffer("#define __builtin_stdarg_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
  242. add_pre_buffer("#define __builtin_va_start(a,b) ((a) = (__builtin_va_list)(&(b)))\n");
  243. add_pre_buffer("#define __builtin_ms_va_start(a,b) ((a) = (__builtin_ms_va_list)(&(b)))\n");
  244. add_pre_buffer("#define __builtin_va_arg(arg,type) ({ type __va_arg_ret = *(type *)(arg); arg += sizeof(type); __va_arg_ret; })\n");
  245. add_pre_buffer("#define __builtin_va_alist (*(void *)0)\n");
  246. add_pre_buffer("#define __builtin_va_arg_incr(x) ((x) + 1)\n");
  247. add_pre_buffer("#define __builtin_va_copy(dest, src) ({ dest = src; (void)0; })\n");
  248. add_pre_buffer("#define __builtin_ms_va_copy(dest, src) ({ dest = src; (void)0; })\n");
  249. add_pre_buffer("#define __builtin_va_end(arg)\n");
  250. add_pre_buffer("#define __builtin_ms_va_end(arg)\n");
  251. add_pre_buffer("#define __builtin_va_arg_pack()\n");
  252. }
  253. static struct symbol_list *sparse_tokenstream(struct token *token)
  254. {
  255. int builtin = token && !token->pos.stream;
  256. // Preprocess the stream
  257. token = preprocess(token);
  258. if (dump_macro_defs || dump_macros_only) {
  259. if (!builtin)
  260. dump_macro_definitions();
  261. if (dump_macros_only)
  262. return NULL;
  263. }
  264. if (preprocess_only) {
  265. while (!eof_token(token)) {
  266. int prec = 1;
  267. struct token *next = token->next;
  268. const char *separator = "";
  269. if (next->pos.whitespace)
  270. separator = " ";
  271. if (next->pos.newline) {
  272. separator = "\n\t\t\t\t\t";
  273. prec = next->pos.pos;
  274. if (prec > 4)
  275. prec = 4;
  276. }
  277. printf("%s%.*s", show_token(token), prec, separator);
  278. token = next;
  279. }
  280. putchar('\n');
  281. return NULL;
  282. }
  283. // Parse the resulting C code
  284. while (!eof_token(token))
  285. token = external_declaration(token, &translation_unit_used_list, NULL);
  286. return translation_unit_used_list;
  287. }
  288. static struct symbol_list *sparse_file(const char *filename)
  289. {
  290. int fd;
  291. struct token *token;
  292. if (strcmp(filename, "-") == 0) {
  293. fd = 0;
  294. } else {
  295. fd = open(filename, O_RDONLY);
  296. if (fd < 0)
  297. die("No such file: %s", filename);
  298. }
  299. base_filename = filename;
  300. // Tokenize the input stream
  301. token = tokenize(NULL, filename, fd, NULL, includepath);
  302. close(fd);
  303. return sparse_tokenstream(token);
  304. }
  305. /*
  306. * This handles the "-include" directive etc: we're in global
  307. * scope, and all types/macros etc will affect all the following
  308. * files.
  309. *
  310. * NOTE NOTE NOTE! "#undef" of anything in this stage will
  311. * affect all subsequent files too, i.e. we can have non-local
  312. * behaviour between files!
  313. */
  314. static struct symbol_list *sparse_initial(void)
  315. {
  316. int i;
  317. // Prepend any "include" file to the stream.
  318. // We're in global scope, it will affect all files!
  319. for (i = 0; i < cmdline_include_nr; i++)
  320. add_pre_buffer("#argv_include \"%s\"\n", cmdline_include[i]);
  321. return sparse_tokenstream(pre_buffer_begin);
  322. }
  323. struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **filelist)
  324. {
  325. char **args;
  326. struct symbol_list *list;
  327. base_filename = "command-line";
  328. // Initialize symbol stream first, so that we can add defines etc
  329. init_symbols();
  330. // initialize the default target to the native 'machine'
  331. target_config(MACH_NATIVE);
  332. args = argv;
  333. for (;;) {
  334. char *arg = *++args;
  335. if (!arg)
  336. break;
  337. if (arg[0] == '-' && arg[1]) {
  338. args = handle_switch(arg+1, args);
  339. continue;
  340. }
  341. add_ptr_list(filelist, arg);
  342. }
  343. handle_switch_finalize();
  344. // Redirect stdout if needed
  345. if (dump_macro_defs || preprocess_only)
  346. do_output = 1;
  347. if (do_output && outfile && strcmp(outfile, "-")) {
  348. if (!freopen(outfile, "w", stdout))
  349. die("error: cannot open %s: %s", outfile, strerror(errno));
  350. }
  351. if (fdump_ir == 0)
  352. fdump_ir = PASS_FINAL;
  353. list = NULL;
  354. if (filelist) {
  355. // Initialize type system
  356. target_init();
  357. init_ctype();
  358. predefined_macros();
  359. create_builtin_stream();
  360. init_builtins(0);
  361. list = sparse_initial();
  362. /*
  363. * Protect the initial token allocations, since
  364. * they need to survive all the others
  365. */
  366. protect_token_alloc();
  367. }
  368. /*
  369. * Evaluate the complete symbol list
  370. * Note: This is not needed for normal cases.
  371. * These symbols should only be predefined defines and
  372. * declaratons which will be evaluated later, when needed.
  373. * This is also the case when a file is directly included via
  374. * '-include <file>' on the command line *AND* the file only
  375. * contains defines, declarations and inline definitions.
  376. * However, in the rare cases where the given file should
  377. * contain some definitions, these will never be evaluated
  378. * and thus won't be able to be linearized correctly.
  379. * Hence the evaluate_symbol_list() here under.
  380. */
  381. evaluate_symbol_list(list);
  382. return list;
  383. }
  384. struct symbol_list * sparse_keep_tokens(char *filename)
  385. {
  386. struct symbol_list *res;
  387. /* Clear previous symbol list */
  388. translation_unit_used_list = NULL;
  389. new_file_scope();
  390. res = sparse_file(filename);
  391. /* And return it */
  392. return res;
  393. }
  394. struct symbol_list * __sparse(char *filename)
  395. {
  396. struct symbol_list *res;
  397. res = sparse_keep_tokens(filename);
  398. /* Drop the tokens for this file after parsing */
  399. clear_token_alloc();
  400. /* And return it */
  401. return res;
  402. }
  403. struct symbol_list * sparse(char *filename)
  404. {
  405. struct symbol_list *res = __sparse(filename);
  406. if (has_error & ERROR_CURR_PHASE)
  407. has_error = ERROR_PREV_PHASE;
  408. /* Evaluate the complete symbol list */
  409. evaluate_symbol_list(res);
  410. return res;
  411. }