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