replace.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* PREPROCESSOR: MACRO-TEXT REPLACEMENT ROUTINES */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include "debug.h" /* UF */
  10. #include "pathlength.h" /* UF */
  11. #include "textsize.h" /* UF */
  12. #include <alloc.h>
  13. #include <assert.h>
  14. #include "idf.h"
  15. #include "input.h"
  16. #include "macro.h"
  17. #include "LLlex.h"
  18. #include "class.h"
  19. #include "interface.h"
  20. extern int InputLevel;
  21. static struct mlist *ReplList; /* list of currently active macros */
  22. static char *macro2buffer(struct idf *idef, char **actpars, int *siztext);
  23. static void macro_func(struct idf *idef);
  24. char *long2str(long value, int base); /* External lib */
  25. int replace(struct idf *idef)
  26. {
  27. /* replace() is called by the lexical analyzer to perform
  28. macro replacement. "idef" is the description of the
  29. identifier which leads to the replacement. If the
  30. optional actual parameters of the macro are OK, the text
  31. of the macro is prepared to serve as an input buffer,
  32. which is pushed onto the input stack.
  33. replace() returns 1 if the replacement succeeded and 0 if
  34. some error has occurred.
  35. */
  36. struct macro *mac = idef->id_macro;
  37. char c;
  38. char **actpars;
  39. char *reptext;
  40. struct mlist *repl;
  41. int size;
  42. if (mac->mc_flag & NOREPLACE) {
  43. warning("macro %s is recursive", idef->id_text);
  44. return 0;
  45. }
  46. if (mac->mc_nps != -1) { /* with parameter list */
  47. if (mac->mc_flag & FUNC) {
  48. /* must be "defined".
  49. Unfortunately, the next assertion
  50. will not compile ...
  51. assert( ! strcmp("defined", idef->id_text));
  52. */
  53. if (! AccDefined)
  54. return 0;
  55. }
  56. if (++mac->mc_count > 100) {
  57. /* 100 must be some number in Parameters */
  58. warning("macro %s is assumed recursive",
  59. idef->id_text);
  60. return 0;
  61. }
  62. LoadChar(c);
  63. c = skipspaces(c,! (mac->mc_flag & FUNC));
  64. if (c != '(') { /* no replacement if no () */
  65. PushBack();
  66. if (! (mac->mc_flag & FUNC)) {
  67. warning("macro %s needs arguments",
  68. idef->id_text);
  69. return 0;
  70. }
  71. }
  72. if (mac->mc_flag & FUNC) {
  73. struct idf *param;
  74. char *nam;
  75. UnknownIdIsZero = 0;
  76. nam = GetIdentifier();
  77. if (nam) {
  78. param = findidf(nam);
  79. }
  80. else param = 0;
  81. UnknownIdIsZero = 1;
  82. if (c == '(') {
  83. LoadChar(c);
  84. c = skipspaces(c, 0);
  85. if (c != ')') error(") missing");
  86. }
  87. if (! nam) {
  88. error("identifier missing");
  89. }
  90. repl = new_mlist();
  91. if (param && param->id_macro)
  92. reptext = "1 ";
  93. else
  94. reptext = "0 ";
  95. InsertText(reptext, 2);
  96. InputLevel++;
  97. repl->m_level = InputLevel;
  98. repl->next = ReplList;
  99. ReplList = repl;
  100. repl->m_mac = mac;
  101. if (nam) free(nam);
  102. return 1;
  103. }
  104. actpars = getactuals(idef); /* get act.param. list */
  105. }
  106. repl = new_mlist();
  107. repl->m_mac = mac;
  108. if (mac->mc_flag & FUNC) /* this macro leads to special action */
  109. macro_func(idef);
  110. if (mac->mc_nps <= 0) {
  111. reptext = mac->mc_text;
  112. size = mac->mc_length;
  113. mac->mc_flag |= NOREPLACE; /* a file called __FILE__ ??? */
  114. }
  115. else {
  116. reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
  117. repl->m_repl = reptext;
  118. }
  119. InsertText(reptext, size);
  120. InputLevel++;
  121. repl->m_level = InputLevel;
  122. repl->next = ReplList;
  123. ReplList = repl;
  124. return 1;
  125. }
  126. char FilNamBuf[PATHLENGTH];
  127. static void macro_func(struct idf *idef)
  128. {
  129. /* macro_func() performs the special actions needed with some
  130. macros. These macros are __FILE__ and __LINE__ which
  131. replacement texts must be evaluated at the time they are
  132. used.
  133. */
  134. struct macro *mac = idef->id_macro;
  135. switch (idef->id_text[2]) { /* This switch is very blunt... */
  136. case 'F' : /* __FILE__ */
  137. mac->mc_length = strlen(FileName) + 2;
  138. mac->mc_text = FilNamBuf;
  139. mac->mc_text[0] = '"';
  140. strcpy(&(mac->mc_text[1]), FileName);
  141. strcat(mac->mc_text, "\"");
  142. break;
  143. case 'L' : /* __LINE__ */
  144. {
  145. mac->mc_text = long2str((long) LineNumber, 10);
  146. mac->mc_length = strlen(mac->mc_text);
  147. break;
  148. }
  149. default :
  150. crash("(macro_func)");
  151. }
  152. }
  153. static char *macro2buffer(struct idf *idef, char **actpars, int *siztext)
  154. {
  155. /* Macro2buffer() turns the macro replacement text, as it is
  156. stored, into an input buffer, while each occurrence of the
  157. non-ascii formal parameter mark is replaced by its
  158. corresponding actual parameter specified in the actual
  159. parameter list actpars. A pointer to the beginning of the
  160. constructed text is returned, while *siztext is filled
  161. with its length.
  162. If there are no parameters, this function behaves
  163. the same as strcpy().
  164. */
  165. unsigned int size = idef->id_macro->mc_length + ITEXTSIZE;
  166. char *text = Malloc(size);
  167. int pos = 0;
  168. char *ptr = idef->id_macro->mc_text;
  169. while (*ptr) {
  170. if (*ptr & FORMALP) { /* non-asc formal param. mark */
  171. int n = *ptr++ & 0177;
  172. char *p;
  173. assert(n != 0);
  174. /* copy the text of the actual parameter
  175. into the replacement text
  176. */
  177. for (p = actpars[n - 1]; *p; p++) {
  178. text[pos++] = *p;
  179. if (pos == size)
  180. text = Realloc(text, size <<= 1);
  181. }
  182. }
  183. else {
  184. text[pos++] = *ptr++;
  185. if (pos == size)
  186. text = Realloc(text, size <<= 1);
  187. }
  188. }
  189. text[pos] = '\0';
  190. *siztext = pos;
  191. return Realloc(text, pos+1);
  192. }
  193. void DoUnstack()
  194. {
  195. Unstacked = 1;
  196. }
  197. void EnableMacros()
  198. {
  199. struct mlist *p = ReplList, *prev = 0;
  200. assert(Unstacked > 0);
  201. while (p) {
  202. struct mlist *nxt = p->next;
  203. if (p->m_level > InputLevel) {
  204. p->m_mac->mc_flag &= ~NOREPLACE;
  205. if (p->m_mac->mc_count) p->m_mac->mc_count--;
  206. if (p->m_repl) free(p->m_repl);
  207. if (! prev) ReplList = nxt;
  208. else prev->next = nxt;
  209. free_mlist(p);
  210. }
  211. else prev = p;
  212. p = nxt;
  213. }
  214. Unstacked = 0;
  215. }