replace.c 4.9 KB

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