variables.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. #include "region.h"
  6. #include "reporting.h"
  7. #include "stringport.h"
  8. #include "tokenizer.h"
  9. #include "variables.h"
  10. char variable_name[TOK_MAX];
  11. char *read_var_error;
  12. char *expand_variables(region *r, char *tok, int t)
  13. {
  14. char *stok, *o, *val;
  15. int alloc_len;
  16. int i, l;
  17. stok = tok;
  18. alloc_len = t+1;
  19. o = region_malloc(r, alloc_len);
  20. i = 0;
  21. while (*tok) {
  22. if (*tok == '$') {
  23. if (!(tok = read_variable_prefix(tok))) {
  24. report("Problem parsing variable inside token [%s] at character [%d]. %s.\n", stok, i, read_var_error);
  25. return NULL;
  26. }
  27. if (!(val = getenv(variable_name))) {
  28. report("Reference to an undefined variable inside token [%s] at character [%d]\n", stok, i);
  29. return NULL;
  30. }
  31. l = strlen(val);
  32. alloc_len += l;
  33. if (alloc_len > TOK_MAX) {
  34. report("Variable expansion blew up token size too large.");
  35. return NULL;
  36. }
  37. o = region_realloc(r, o, alloc_len);
  38. memcpy(o + i, val, l);
  39. i += l;
  40. }
  41. else {
  42. o[i++] = *tok++;
  43. }
  44. }
  45. o[i] = '\0';
  46. return o;
  47. }
  48. int variable_character(char c)
  49. {
  50. return c == '_' || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9');
  51. }
  52. char *read_variable_prefix(char *tok)
  53. {
  54. int i;
  55. int bracket;
  56. assert(*tok == '$');
  57. tok++;
  58. // NOTE: We don't bother to bounds check here
  59. // because tok is already <= the size of a token
  60. //
  61. // ...lets see if this ever bites?
  62. bracket = 0;
  63. if (*tok == '{') {
  64. bracket = 1;
  65. tok++;
  66. }
  67. i = 0;
  68. while (variable_character(*tok)) {
  69. if (i == 0 && ('0' <= *tok && *tok <= '9')) {
  70. read_var_error = "var must not start with a digit";
  71. return NULL;
  72. }
  73. variable_name[i++] = *tok++;
  74. }
  75. if (bracket && *tok++ != '}') {
  76. read_var_error = "missing '}'";
  77. return NULL;
  78. }
  79. variable_name[i] = '\0';
  80. if (!i) {
  81. read_var_error = "length 0 variable";
  82. return NULL;
  83. }
  84. return tok;
  85. }