read_config_header.c 3.0 KB

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