Pristine Ack-5.5
[Ack-5.5.git] / util / cpp / scan.c
1 /* $Id: scan.c,v 1.9 1994/06/24 10:19:00 ceriel Exp $ */
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: SCANNER FOR THE ACTUAL PARAMETERS OF MACROS    */
7
8 /*      This file contains the function getactuals() which scans an actual
9         parameter list and splits it up into a list of strings, each one
10         representing an actual parameter.
11 */
12
13 #include        "lapbuf.h"      /* UF */
14 #include        "nparams.h"     /* UF */
15
16 #include        "input.h"
17 #include        "class.h"
18 #include        "idf.h"
19 #include        "macro.h"
20 #include        "interface.h"
21 #include        "file_info.h"
22
23 #define EOS             '\0'
24 #define overflow()      (fatal("actual parameter buffer overflow"))
25
26 PRIVATE char apbuf[LAPBUF]; /* temporary storage for actual parameters  */
27 PRIVATE char *actparams[NPARAMS]; /* pointers to the text of the actuals */
28 PRIVATE char *aptr;     /* pointer to last inserted character in apbuf  */
29
30 #define copy(ch)        ((aptr < &apbuf[LAPBUF]) ? (*aptr++ = ch) : overflow())
31
32 PRIVATE int nr_of_params;       /* number of actuals read until now     */
33
34 PRIVATE char **
35 getactuals(idef)
36         struct idf *idef;
37 {
38         /*      getactuals() collects the actual parameters and turns them
39                 into a list of strings, a pointer to which is returned.
40         */
41         register acnt = idef->id_macro->mc_nps;
42
43         nr_of_params = 0;
44         actparams[0] = aptr = &apbuf[0];
45         copyact('(', ')', 0);   /* read the actual parameters   */
46         copy(EOS);              /* mark the end of it all       */
47
48         if (!nr_of_params++)    {               /* 0 or 1 parameter     */
49                 /* there could be a ( <spaces, comment, ...> )
50                 */
51                 register char *p = actparams[0];
52
53                 while ((class(*p) == STSKIP) || (*p == '\n')) {
54                                 ++p;
55                 }
56
57                 if (!*p) {      /* the case () : 0 parameters   */
58                         nr_of_params--;
59                 }
60         }
61
62         if (nr_of_params != acnt)       {
63                 /*      argument mismatch: too many or too few
64                         actual parameters.
65                 */
66                 warning("argument mismatch, %s", idef->id_text);
67
68                 while (nr_of_params < acnt) {
69                         /*      too few paraeters: remaining actuals are ""
70                         */
71                         actparams[nr_of_params] = "";
72                         nr_of_params++;
73                 }
74         }
75
76         return actparams;
77 }
78
79 PRIVATE
80 copyact(ch1, ch2, level)
81         char ch1, ch2;
82         int level;
83 {
84         /*      copyact() is taken from Ceriel Jacobs' LLgen, with
85                 permission.  Its task is to build a list of actuals
86                 parameters, which list is surrounded by '(' and ')' and in
87                 which the parameters are separated by ',' if there are
88                 more than 1. The balancing of '(',')' and '[',']' and
89                 '{','}' is taken care of by calling this function
90                 recursively. At each level, copyact() reads the input,
91                 upto the corresponding closing bracket.
92
93                 Opening bracket is ch1, closing bracket is ch2. If
94                 level != 0, copy opening and closing parameters too.
95         */
96         register int ch;                /* Current char */
97         register int match;             /* used to read strings */
98
99         if (level) {
100                 copy(ch1);
101         }
102
103         for (;;)        {
104                 LoadChar(ch);
105
106                 if (ch == ch2)  {
107                         if (level) {
108                                 copy(ch);
109                         }
110                         return;
111                 }
112
113                 switch(ch)      {
114
115 #ifdef __MATCHING_PAR__
116                 case ')':
117                 case '}':
118                 case ']':
119                         error("unbalanced parenthesis");
120                         break;
121 #endif /* __MATCHING_PAR__ */
122
123                 case '(':
124                         copyact('(', ')', level+1);
125                         break;
126
127 #ifdef __MATCHING_PAR__
128                 case '{':
129                         /*      example:
130                                         #define declare(v, t)   t v
131                                         declare(v, union{int i, j; float r;});
132                         */
133                         copyact('{', '}', level+1);
134                         break;
135
136                 case '[':
137                         copyact('[', ']', level+1);
138                         break;
139 #endif /* __MATCHING_PAR__ */
140
141                 case '\n':
142                         LineNumber++;
143                         LoadChar(ch);
144                         while (ch == '#')       {
145                                 /*      This piece of code needs some
146                                         explanation: consider the call of
147                                         the macro defined as:
148                                                 #define sum(b,c) (b + c)
149                                         in the following form:
150                                                 sum(
151                                                 #include my_phone_number
152                                                 ,2)
153                                         in which case the include must be
154                                         interpreted as such.
155                                 */
156                                 domacro();      /* has read nl, vt or ff */
157                                 LoadChar(ch);
158                                 /* Loop, for another control line */
159                         }
160
161                         PushBack();
162                         copy(' ');
163                         break;
164
165                 case '/':
166                         LoadChar(ch);
167
168                         if (ch == '*')  {       /* skip comment */
169                                 skipcomment();
170                                 continue;
171                         }
172
173                         PushBack();
174                         copy('/');
175                         break;
176
177                 case ',':
178                         if (!level)     {
179                                 /* next parameter encountered */
180                                 copy(EOS);
181
182                                 if (++nr_of_params >= NPARAMS) {
183                                         fatal("(getact) too many actuals");
184                                 }
185
186                                 actparams[nr_of_params] = aptr;
187                         }
188                         else    {
189                                 copy(ch);
190                         }
191                         break;
192
193                 case '\'':
194                 case '"' :
195                         /*      watch out for brackets in strings, they do
196                                 not count !
197                         */
198                         match = ch;
199                         copy(ch);
200                         LoadChar(ch);
201                         while (ch != EOI)       {
202                                 if (ch == match) {
203                                         break;
204                                 }
205
206                                 if (ch == '\\') {
207                                         copy(ch);
208                                         LoadChar(ch);
209                                 }
210                                 else
211                                 if (ch == '\n') {
212                                         LineNumber++;
213                                         error("newline in string");
214                                         copy(match);
215                                         break;
216                                 }
217
218                                 copy(ch);
219                                 LoadChar(ch);
220                         }
221
222                         if (ch == match)        {
223                                 copy(ch);
224                                 break;
225                         }
226                         /* Fall through */
227
228                 case EOI :
229                         error("unterminated macro call");
230                         return;
231
232                 default:
233                         copy(ch);
234                         break;
235                 }
236         }
237 }