read_config_header.c 3.2 KB

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