]>
Commit | Line | Data |
---|---|---|
28f540f4 | 1 | /* |
a7ab6ec8 | 2 | * From: @(#)rpc_scan.c 1.11 89/02/22 |
cb636bb2 | 3 | * |
a7ab6ec8 UD |
4 | * Copyright (c) 2010, Oracle America, Inc. |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions are | |
7 | * met: | |
cbd3dceb | 8 | * |
a7ab6ec8 UD |
9 | * * Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | |
11 | * * Redistributions in binary form must reproduce the above | |
12 | * copyright notice, this list of conditions and the following | |
13 | * disclaimer in the documentation and/or other materials | |
14 | * provided with the distribution. | |
15 | * * Neither the name of the "Oracle America, Inc." nor the names of its | |
16 | * contributors may be used to endorse or promote products derived | |
17 | * from this software without specific prior written permission. | |
cbd3dceb | 18 | * |
a7ab6ec8 UD |
19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
22 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
23 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
24 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
25 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE | |
26 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
27 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
28 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
0d204b0a | 31 | */ |
0d204b0a UD |
32 | |
33 | /* | |
e7fd8a39 UD |
34 | * rpc_scan.c, Scanner for the RPC protocol compiler |
35 | * Copyright (C) 1987, Sun Microsystems, Inc. | |
28f540f4 RM |
36 | */ |
37 | #include <stdio.h> | |
38 | #include <ctype.h> | |
0d204b0a | 39 | #include <string.h> |
4360eafd | 40 | #include <libintl.h> |
28f540f4 | 41 | #include "rpc_scan.h" |
0d204b0a | 42 | #include "rpc_parse.h" |
28f540f4 | 43 | #include "rpc_util.h" |
0d204b0a | 44 | #include "proto.h" |
28f540f4 RM |
45 | |
46 | #define startcomment(where) (where[0] == '/' && where[1] == '*') | |
47 | #define endcomment(where) (where[-1] == '*' && where[0] == '/') | |
48 | ||
e7fd8a39 UD |
49 | static int pushed = 0; /* is a token pushed */ |
50 | static token lasttok; /* last token, if pushed */ | |
28f540f4 | 51 | |
e7fd8a39 UD |
52 | static void unget_token (token * tokp); |
53 | static void findstrconst (const char **str, const char **val); | |
54 | static void findchrconst (const char **str, const char **val); | |
55 | static void findconst (const char **str, const char **val); | |
56 | static void findkind (const char **mark, token * tokp); | |
57 | static int cppline (const char *line); | |
58 | static int directive (const char *line); | |
59 | static void printdirective (const char *line); | |
60 | static void docppline (const char *line, int *lineno, const char **fname); | |
0d204b0a | 61 | |
28f540f4 | 62 | /* |
e7fd8a39 | 63 | * scan expecting 1 given token |
28f540f4 RM |
64 | */ |
65 | void | |
e7fd8a39 | 66 | scan (tok_kind expect, token * tokp) |
28f540f4 | 67 | { |
e7fd8a39 UD |
68 | get_token (tokp); |
69 | if (tokp->kind != expect) | |
880f421f | 70 | expected1 (expect); |
28f540f4 RM |
71 | } |
72 | ||
73 | /* | |
e7fd8a39 | 74 | * scan expecting any of the 2 given tokens |
28f540f4 RM |
75 | */ |
76 | void | |
e7fd8a39 | 77 | scan2 (tok_kind expect1, tok_kind expect2, token * tokp) |
28f540f4 | 78 | { |
e7fd8a39 UD |
79 | get_token (tokp); |
80 | if (tokp->kind != expect1 && tokp->kind != expect2) | |
81 | { | |
82 | expected2 (expect1, expect2); | |
83 | } | |
28f540f4 RM |
84 | } |
85 | ||
86 | /* | |
e7fd8a39 | 87 | * scan expecting any of the 3 given token |
28f540f4 RM |
88 | */ |
89 | void | |
e7fd8a39 | 90 | scan3 (tok_kind expect1, tok_kind expect2, tok_kind expect3, token * tokp) |
28f540f4 | 91 | { |
e7fd8a39 UD |
92 | get_token (tokp); |
93 | if (tokp->kind != expect1 && tokp->kind != expect2 | |
94 | && tokp->kind != expect3) | |
95 | { | |
96 | expected3 (expect1, expect2, expect3); | |
97 | } | |
28f540f4 RM |
98 | } |
99 | ||
28f540f4 | 100 | /* |
e7fd8a39 | 101 | * scan expecting a constant, possibly symbolic |
28f540f4 RM |
102 | */ |
103 | void | |
880f421f | 104 | scan_num (token *tokp) |
28f540f4 | 105 | { |
e7fd8a39 UD |
106 | get_token (tokp); |
107 | switch (tokp->kind) | |
108 | { | |
109 | case TOK_IDENT: | |
110 | break; | |
111 | default: | |
880f421f | 112 | error (_("constant or identifier expected")); |
e7fd8a39 | 113 | } |
28f540f4 RM |
114 | } |
115 | ||
28f540f4 | 116 | /* |
e7fd8a39 | 117 | * Peek at the next token |
28f540f4 RM |
118 | */ |
119 | void | |
880f421f | 120 | peek (token *tokp) |
28f540f4 | 121 | { |
e7fd8a39 UD |
122 | get_token (tokp); |
123 | unget_token (tokp); | |
28f540f4 RM |
124 | } |
125 | ||
28f540f4 | 126 | /* |
e7fd8a39 | 127 | * Peek at the next token and scan it if it matches what you expect |
28f540f4 RM |
128 | */ |
129 | int | |
880f421f | 130 | peekscan (tok_kind expect, token *tokp) |
28f540f4 | 131 | { |
e7fd8a39 UD |
132 | peek (tokp); |
133 | if (tokp->kind == expect) | |
134 | { | |
135 | get_token (tokp); | |
880f421f | 136 | return 1; |
e7fd8a39 | 137 | } |
880f421f | 138 | return 0; |
28f540f4 RM |
139 | } |
140 | ||
28f540f4 | 141 | /* |
e7fd8a39 | 142 | * Get the next token, printing out any directive that are encountered. |
28f540f4 RM |
143 | */ |
144 | void | |
880f421f | 145 | get_token (token *tokp) |
28f540f4 | 146 | { |
e7fd8a39 UD |
147 | int commenting; |
148 | ||
149 | if (pushed) | |
150 | { | |
151 | pushed = 0; | |
152 | *tokp = lasttok; | |
153 | return; | |
154 | } | |
155 | commenting = 0; | |
156 | for (;;) | |
157 | { | |
158 | if (*where == 0) | |
159 | { | |
160 | for (;;) | |
161 | { | |
162 | if (!fgets (curline, MAXLINESIZE, fin)) | |
163 | { | |
164 | tokp->kind = TOK_EOF; | |
165 | *curline = 0; | |
166 | where = curline; | |
167 | return; | |
168 | } | |
169 | linenum++; | |
170 | if (commenting) | |
171 | { | |
172 | break; | |
28f540f4 | 173 | } |
e7fd8a39 UD |
174 | else if (cppline (curline)) |
175 | { | |
176 | docppline (curline, &linenum, | |
177 | &infilename); | |
178 | } | |
179 | else if (directive (curline)) | |
180 | { | |
181 | printdirective (curline); | |
182 | } | |
183 | else | |
184 | { | |
185 | break; | |
186 | } | |
187 | } | |
188 | where = curline; | |
28f540f4 | 189 | } |
e7fd8a39 UD |
190 | else if (isspace (*where)) |
191 | { | |
192 | while (isspace (*where)) | |
193 | { | |
194 | where++; /* eat */ | |
195 | } | |
196 | } | |
197 | else if (commenting) | |
198 | { | |
199 | for (where++; *where; where++) | |
200 | { | |
201 | if (endcomment (where)) | |
202 | { | |
203 | where++; | |
204 | commenting--; | |
205 | break; | |
28f540f4 | 206 | } |
e7fd8a39 UD |
207 | } |
208 | } | |
209 | else if (startcomment (where)) | |
210 | { | |
211 | where += 2; | |
212 | commenting++; | |
213 | } | |
214 | else | |
215 | { | |
216 | break; | |
28f540f4 | 217 | } |
e7fd8a39 UD |
218 | } |
219 | ||
220 | /* | |
221 | * 'where' is not whitespace, comment or directive Must be a token! | |
222 | */ | |
223 | switch (*where) | |
224 | { | |
225 | case ':': | |
226 | tokp->kind = TOK_COLON; | |
227 | where++; | |
228 | break; | |
229 | case ';': | |
230 | tokp->kind = TOK_SEMICOLON; | |
231 | where++; | |
232 | break; | |
233 | case ',': | |
234 | tokp->kind = TOK_COMMA; | |
235 | where++; | |
236 | break; | |
237 | case '=': | |
238 | tokp->kind = TOK_EQUAL; | |
239 | where++; | |
240 | break; | |
241 | case '*': | |
242 | tokp->kind = TOK_STAR; | |
243 | where++; | |
244 | break; | |
245 | case '[': | |
246 | tokp->kind = TOK_LBRACKET; | |
247 | where++; | |
248 | break; | |
249 | case ']': | |
250 | tokp->kind = TOK_RBRACKET; | |
251 | where++; | |
252 | break; | |
253 | case '{': | |
254 | tokp->kind = TOK_LBRACE; | |
255 | where++; | |
256 | break; | |
257 | case '}': | |
258 | tokp->kind = TOK_RBRACE; | |
259 | where++; | |
260 | break; | |
261 | case '(': | |
262 | tokp->kind = TOK_LPAREN; | |
263 | where++; | |
264 | break; | |
265 | case ')': | |
266 | tokp->kind = TOK_RPAREN; | |
267 | where++; | |
268 | break; | |
269 | case '<': | |
270 | tokp->kind = TOK_LANGLE; | |
271 | where++; | |
272 | break; | |
273 | case '>': | |
274 | tokp->kind = TOK_RANGLE; | |
275 | where++; | |
276 | break; | |
277 | ||
278 | case '"': | |
279 | tokp->kind = TOK_STRCONST; | |
280 | findstrconst (&where, &tokp->str); | |
281 | break; | |
282 | case '\'': | |
283 | tokp->kind = TOK_CHARCONST; | |
284 | findchrconst (&where, &tokp->str); | |
285 | break; | |
286 | ||
287 | case '-': | |
288 | case '0': | |
289 | case '1': | |
290 | case '2': | |
291 | case '3': | |
292 | case '4': | |
293 | case '5': | |
294 | case '6': | |
295 | case '7': | |
296 | case '8': | |
297 | case '9': | |
298 | tokp->kind = TOK_IDENT; | |
299 | findconst (&where, &tokp->str); | |
300 | break; | |
301 | ||
302 | default: | |
303 | if (!(isalpha (*where) || *where == '_')) | |
304 | { | |
305 | char buf[100]; | |
306 | char *p; | |
307 | ||
308 | s_print (buf, _("illegal character in file: ")); | |
309 | p = buf + strlen (buf); | |
310 | if (isprint (*where)) | |
311 | { | |
312 | s_print (p, "%c", *where); | |
313 | } | |
314 | else | |
315 | { | |
316 | s_print (p, "%d", *where); | |
317 | } | |
318 | error (buf); | |
319 | } | |
320 | findkind (&where, tokp); | |
321 | break; | |
322 | } | |
28f540f4 RM |
323 | } |
324 | ||
0d204b0a | 325 | static void |
e7fd8a39 | 326 | unget_token (token * tokp) |
28f540f4 | 327 | { |
e7fd8a39 UD |
328 | lasttok = *tokp; |
329 | pushed = 1; | |
28f540f4 RM |
330 | } |
331 | ||
0d204b0a | 332 | static void |
e7fd8a39 | 333 | findstrconst (const char **str, const char **val) |
28f540f4 | 334 | { |
e7fd8a39 UD |
335 | const char *p; |
336 | char *tmp; | |
337 | int size; | |
338 | ||
339 | p = *str; | |
340 | do | |
341 | { | |
342 | p++; | |
343 | } | |
344 | while (*p && *p != '"'); | |
345 | if (*p == 0) | |
346 | { | |
347 | error (_("unterminated string constant")); | |
348 | } | |
349 | p++; | |
350 | size = p - *str; | |
351 | tmp = alloc (size + 1); | |
352 | strncpy (tmp, *str, size); | |
353 | tmp[size] = 0; | |
354 | *val = tmp; | |
355 | *str = p; | |
28f540f4 RM |
356 | } |
357 | ||
0d204b0a | 358 | static void |
e7fd8a39 | 359 | findchrconst (const char **str, const char **val) |
28f540f4 | 360 | { |
e7fd8a39 UD |
361 | const char *p; |
362 | char *tmp; | |
363 | int size; | |
364 | ||
365 | p = *str; | |
366 | do | |
367 | { | |
368 | p++; | |
369 | } | |
370 | while (*p && *p != '\''); | |
371 | if (*p == 0) | |
372 | { | |
373 | error (_("unterminated string constant")); | |
374 | } | |
375 | p++; | |
376 | size = p - *str; | |
377 | if (size != 3) | |
378 | { | |
379 | error (_("empty char string")); | |
380 | } | |
381 | tmp = alloc (size + 1); | |
382 | strncpy (tmp, *str, size); | |
383 | tmp[size] = 0; | |
384 | *val = tmp; | |
385 | *str = p; | |
0d204b0a UD |
386 | } |
387 | ||
388 | static void | |
e7fd8a39 | 389 | findconst (const char **str, const char **val) |
0d204b0a | 390 | { |
e7fd8a39 UD |
391 | const char *p; |
392 | char *tmp; | |
393 | int size; | |
394 | ||
395 | p = *str; | |
396 | if (*p == '0' && *(p + 1) == 'x') | |
397 | { | |
398 | p++; | |
399 | do | |
400 | { | |
401 | p++; | |
28f540f4 | 402 | } |
e7fd8a39 UD |
403 | while (isxdigit (*p)); |
404 | } | |
405 | else | |
406 | { | |
407 | do | |
408 | { | |
409 | p++; | |
410 | } | |
411 | while (isdigit (*p)); | |
412 | } | |
413 | size = p - *str; | |
414 | tmp = alloc (size + 1); | |
415 | strncpy (tmp, *str, size); | |
416 | tmp[size] = 0; | |
417 | *val = tmp; | |
418 | *str = p; | |
28f540f4 RM |
419 | } |
420 | ||
e7fd8a39 UD |
421 | static const token symbols[] = |
422 | { | |
423 | {TOK_CONST, "const"}, | |
424 | {TOK_UNION, "union"}, | |
425 | {TOK_SWITCH, "switch"}, | |
426 | {TOK_CASE, "case"}, | |
427 | {TOK_DEFAULT, "default"}, | |
428 | {TOK_STRUCT, "struct"}, | |
429 | {TOK_TYPEDEF, "typedef"}, | |
430 | {TOK_ENUM, "enum"}, | |
431 | {TOK_OPAQUE, "opaque"}, | |
432 | {TOK_BOOL, "bool"}, | |
433 | {TOK_VOID, "void"}, | |
434 | {TOK_CHAR, "char"}, | |
435 | {TOK_INT, "int"}, | |
436 | {TOK_UNSIGNED, "unsigned"}, | |
437 | {TOK_SHORT, "short"}, | |
438 | {TOK_LONG, "long"}, | |
ce64ae6b | 439 | {TOK_HYPER, "hyper"}, |
e7fd8a39 UD |
440 | {TOK_FLOAT, "float"}, |
441 | {TOK_DOUBLE, "double"}, | |
442 | {TOK_STRING, "string"}, | |
443 | {TOK_PROGRAM, "program"}, | |
444 | {TOK_VERSION, "version"}, | |
445 | {TOK_EOF, "??????"}, | |
28f540f4 RM |
446 | }; |
447 | ||
0d204b0a | 448 | static void |
b13927da | 449 | findkind (const char **mark, token *tokp) |
28f540f4 | 450 | { |
e7fd8a39 | 451 | int len; |
b13927da | 452 | const token *s; |
e7fd8a39 UD |
453 | const char *str; |
454 | char *tmp; | |
455 | ||
456 | str = *mark; | |
457 | for (s = symbols; s->kind != TOK_EOF; s++) | |
458 | { | |
459 | len = strlen (s->str); | |
460 | if (strncmp (str, s->str, len) == 0) | |
461 | { | |
462 | if (!isalnum (str[len]) && str[len] != '_') | |
463 | { | |
464 | tokp->kind = s->kind; | |
465 | tokp->str = s->str; | |
466 | *mark = str + len; | |
467 | return; | |
468 | } | |
28f540f4 | 469 | } |
e7fd8a39 UD |
470 | } |
471 | tokp->kind = TOK_IDENT; | |
472 | for (len = 0; isalnum (str[len]) || str[len] == '_'; len++); | |
473 | tmp = alloc (len + 1); | |
474 | strncpy (tmp, str, len); | |
475 | tmp[len] = 0; | |
476 | tokp->str = tmp; | |
477 | *mark = str + len; | |
28f540f4 RM |
478 | } |
479 | ||
0d204b0a | 480 | static int |
e7fd8a39 | 481 | cppline (const char *line) |
28f540f4 | 482 | { |
e7fd8a39 | 483 | return line == curline && *line == '#'; |
28f540f4 RM |
484 | } |
485 | ||
0d204b0a | 486 | static int |
e7fd8a39 | 487 | directive (const char *line) |
28f540f4 | 488 | { |
e7fd8a39 | 489 | return line == curline && *line == '%'; |
28f540f4 RM |
490 | } |
491 | ||
0d204b0a | 492 | static void |
e7fd8a39 | 493 | printdirective (const char *line) |
28f540f4 | 494 | { |
e7fd8a39 | 495 | f_print (fout, "%s", line + 1); |
28f540f4 RM |
496 | } |
497 | ||
0d204b0a | 498 | static void |
e7fd8a39 | 499 | docppline (const char *line, int *lineno, const char **fname) |
28f540f4 | 500 | { |
e7fd8a39 UD |
501 | char *file; |
502 | int num; | |
503 | char *p; | |
504 | ||
505 | line++; | |
506 | while (isspace (*line)) | |
507 | { | |
508 | line++; | |
509 | } | |
510 | num = atoi (line); | |
511 | while (isdigit (*line)) | |
512 | { | |
513 | line++; | |
514 | } | |
515 | while (isspace (*line)) | |
516 | { | |
517 | line++; | |
518 | } | |
519 | if (*line != '"') | |
520 | { | |
521 | error (_("preprocessor error")); | |
522 | } | |
523 | line++; | |
524 | p = file = alloc (strlen (line) + 1); | |
525 | while (*line && *line != '"') | |
526 | { | |
527 | *p++ = *line++; | |
528 | } | |
529 | if (*line == 0) | |
530 | { | |
531 | error (_("preprocessor error")); | |
532 | } | |
533 | *p = 0; | |
534 | if (*file == 0) | |
535 | { | |
0292b0dd | 536 | free (file); |
e7fd8a39 UD |
537 | *fname = NULL; |
538 | } | |
539 | else | |
540 | { | |
541 | *fname = file; | |
542 | } | |
543 | *lineno = num - 1; | |
28f540f4 | 544 | } |