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