read_config_header.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include <ccan/err/err.h>
  2. #include <ccan/str/str.h>
  3. #include "read_config_header.h"
  4. #include "tools.h"
  5. #include <string.h>
  6. /* Get an identifier token. */
  7. char *get_symbol_token(void *ctx, const char **line)
  8. {
  9. unsigned int toklen;
  10. char *ret;
  11. *line += strspn(*line, " \t");
  12. toklen = strspn(*line, IDENT_CHARS);
  13. if (!toklen)
  14. return NULL;
  15. ret = tal_strndup(ctx, *line, toklen);
  16. *line += toklen;
  17. return ret;
  18. }
  19. /* Get token if it's equal to token. */
  20. bool get_token(const char **line, const char *token)
  21. {
  22. unsigned int toklen;
  23. *line += strspn(*line, " \t");
  24. if (cisalnum(token[0]) || token[0] == '_')
  25. toklen = strspn(*line, IDENT_CHARS);
  26. else {
  27. /* FIXME: real tokenizer handles ++ and other multi-chars. */
  28. toklen = strlen(token);
  29. }
  30. if (toklen == strlen(token) && !strncmp(*line, token, toklen)) {
  31. *line += toklen;
  32. return true;
  33. }
  34. return false;
  35. }
  36. static char *demangle_string(char *string)
  37. {
  38. unsigned int i;
  39. const char mapfrom[] = "abfnrtv";
  40. const char mapto[] = "\a\b\f\n\r\t\v";
  41. if (!strchr(string, '"'))
  42. return NULL;
  43. string = strchr(string, '"') + 1;
  44. if (!strrchr(string, '"'))
  45. return NULL;
  46. *strrchr(string, '"') = '\0';
  47. for (i = 0; i < strlen(string); i++) {
  48. if (string[i] == '\\') {
  49. char repl;
  50. unsigned len = 0;
  51. const char *p = strchr(mapfrom, string[i+1]);
  52. if (p) {
  53. repl = mapto[p - mapfrom];
  54. len = 1;
  55. } else if (strlen(string+i+1) >= 3) {
  56. if (string[i+1] == 'x') {
  57. repl = (string[i+2]-'0')*16
  58. + string[i+3]-'0';
  59. len = 3;
  60. } else if (cisdigit(string[i+1])) {
  61. repl = (string[i+2]-'0')*8*8
  62. + (string[i+3]-'0')*8
  63. + (string[i+4]-'0');
  64. len = 3;
  65. }
  66. }
  67. if (len == 0) {
  68. repl = string[i+1];
  69. len = 1;
  70. }
  71. string[i] = repl;
  72. memmove(string + i + 1, string + i + len + 1,
  73. strlen(string + i + len + 1) + 1);
  74. }
  75. }
  76. return string;
  77. }
  78. char *read_config_header(const char *ccan_dir,
  79. const char **compiler, const char **cflags,
  80. bool verbose)
  81. {
  82. char *fname = tal_fmt(NULL, "%s/config.h", ccan_dir);
  83. char **lines;
  84. unsigned int i;
  85. char *config_header;
  86. config_header = tal_grab_file(NULL, fname, NULL);
  87. tal_free(fname);
  88. if (!config_header)
  89. goto out;
  90. lines = tal_strsplit(config_header, config_header, "\n", STR_EMPTY_OK);
  91. for (i = 0; i < tal_count(lines) - 1; i++) {
  92. char *sym;
  93. const char **line = (const char **)&lines[i];
  94. if (!get_token(line, "#"))
  95. continue;
  96. if (!get_token(line, "define"))
  97. continue;
  98. sym = get_symbol_token(lines, line);
  99. if (streq(sym, "CCAN_COMPILER") && !compiler) {
  100. *compiler = demangle_string(lines[i]);
  101. if (!*compiler)
  102. errx(1, "%s:%u:could not parse CCAN_COMPILER",
  103. fname, i+1);
  104. if (verbose)
  105. printf("%s: compiler set to '%s'\n",
  106. fname, *compiler);
  107. } else if (streq(sym, "CCAN_CFLAGS") && !cflags) {
  108. *cflags = demangle_string(lines[i]);
  109. if (!*cflags)
  110. errx(1, "%s:%u:could not parse CCAN_CFLAGS",
  111. fname, i+1);
  112. if (verbose)
  113. printf("%s: compiler flags set to '%s'\n",
  114. fname, *cflags);
  115. }
  116. }
  117. out:
  118. if (!*compiler)
  119. *compiler = CCAN_COMPILER;
  120. if (!*cflags)
  121. *cflags = CCAN_CFLAGS;
  122. return config_header;
  123. }