l_comment.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* Lint-specific comment handling */
  7. #include <ctype.h>
  8. #include "lint.h"
  9. #ifdef LINT
  10. #include <alloc.h>
  11. #include "interface.h"
  12. #include "arith.h"
  13. #include "l_state.h"
  14. #include "l_comment.h"
  15. extern char loptions[];
  16. /* Since the lexical analyser does a one-token look-ahead, pseudo-
  17. comments are read too soon. This is remedied by first storing them
  18. in static variables and then moving them to the real variables
  19. one token later.
  20. */
  21. PRIVATE int notreached;
  22. PRIVATE int varargsN = -1;
  23. PRIVATE int argsused;
  24. PRIVATE int formatN;
  25. PRIVATE int formatVAR;
  26. PRIVATE char *format;
  27. PRIVATE char *prev_format;
  28. PRIVATE make_format();
  29. int LINTLIB; /* file is lint library */
  30. int s_NOTREACHED; /* statement not reached */
  31. int f_VARARGSn; /* function with variable # of args */
  32. int f_ARGSUSED; /* function does not use all args */
  33. int f_FORMATn; /* argument f_FORMATn is f_FORMAT */
  34. char *f_FORMAT;
  35. int f_FORMATvar; /* but the formal argument may be
  36. absent because of varargs.h */
  37. lint_init_comment()
  38. {
  39. LINTLIB = loptions['L'];
  40. }
  41. lint_comment_ahead()
  42. {
  43. s_NOTREACHED = notreached;
  44. notreached = 0;
  45. }
  46. lint_comment_function()
  47. {
  48. f_ARGSUSED = argsused | loptions['v'];
  49. argsused = 0;
  50. f_VARARGSn = varargsN;
  51. varargsN = -1;
  52. f_FORMATn = formatN;
  53. formatN = 0;
  54. f_FORMAT = format;
  55. if (format)
  56. prev_format = format;
  57. format = 0;
  58. f_FORMATvar = formatVAR;
  59. formatVAR = 0;
  60. }
  61. PRIVATE char buf[1000];
  62. PRIVATE char *bufpos; /* next free position in buf */
  63. lint_start_comment()
  64. {
  65. bufpos = &buf[0];
  66. }
  67. lint_comment_char(c)
  68. int c;
  69. {
  70. /* This function is called with every character between /_* and *_/ */
  71. if (bufpos - &buf[0] < sizeof(buf)-1)
  72. *bufpos++ = (char)c;
  73. }
  74. lint_end_comment()
  75. {
  76. *bufpos++ = '\0';
  77. bufpos = &buf[0];
  78. /* skip initial blanks */
  79. while (*bufpos && isspace(*bufpos)) {
  80. bufpos++;
  81. }
  82. /* now test for one of the pseudo-comments */
  83. if (strncmp(bufpos, "NOTREACHED", 10) == 0) {
  84. notreached = 1;
  85. }
  86. else
  87. if (strncmp(bufpos, "ARGSUSED", 8) == 0) {
  88. argsused = 1;
  89. }
  90. else
  91. if (strncmp(bufpos, "LINTLIBRARY", 11) == 0) {
  92. LINTLIB = 1;
  93. }
  94. else
  95. if (strncmp(bufpos, "VARARGS", 7) == 0) {
  96. bufpos += 7;
  97. varargsN = isdigit(*bufpos) ? atoi(bufpos) : 0;
  98. }
  99. else
  100. if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) {
  101. register int argn;
  102. bufpos += 6;
  103. argn = *bufpos++ - '0';
  104. varargsN = argn + 1;
  105. if (*bufpos == 'v') {
  106. /* something like FORMAT3v */
  107. formatVAR = 1;
  108. bufpos++;
  109. }
  110. make_format(argn, bufpos);
  111. }
  112. }
  113. /* We use a small FSA to skip layout inside formats, but to preserve
  114. a space between letters and digits.
  115. */
  116. #define NONE 0
  117. #define LETGIT 1
  118. #define LETGITSPACE 2
  119. PRIVATE
  120. make_format(argn, oldf)
  121. int argn;
  122. char *oldf;
  123. {
  124. register char *newf;
  125. register int last_stat;
  126. while (*oldf && *oldf != '$') {
  127. oldf++;
  128. }
  129. if (!*oldf) {
  130. /* no format given, repeat previous format */
  131. if (!prev_format) {
  132. warning("format missing and no previous format");
  133. }
  134. formatN = argn;
  135. format = prev_format;
  136. return;
  137. }
  138. if (*oldf++ != '$') {
  139. warning("no format in FORMAT pseudo-comment");
  140. format = 0;
  141. return;
  142. }
  143. /* there is a new format to be composed */
  144. newf = Malloc(strlen(oldf));
  145. /* certainly enough and probably not overly too much */
  146. formatN = argn;
  147. format = newf;
  148. last_stat = NONE;
  149. while (*oldf && *oldf != '$') {
  150. register char ch = *oldf++;
  151. if (isspace(ch)) {
  152. if (last_stat == LETGIT)
  153. last_stat = LETGITSPACE;
  154. }
  155. else
  156. if (isalnum(ch)) {
  157. switch (last_stat) {
  158. case NONE:
  159. last_stat = LETGIT;
  160. break;
  161. case LETGITSPACE:
  162. *newf++ = ' ';
  163. last_stat = LETGIT;
  164. break;
  165. }
  166. *newf++ = ch;
  167. }
  168. else {
  169. last_stat = NONE;
  170. *newf++ = ch;
  171. }
  172. }
  173. if (*oldf != '$') {
  174. warning("no end of format in FORMAT pseudo-comment");
  175. format = 0;
  176. return;
  177. }
  178. *newf++ = '\0';
  179. }
  180. #endif /* LINT */