061dbbfa8df680f0ba14f05959ac79f852ad9106
[portablexdr.git] / rpcgen_scan.l
1 /* -*- C -*-
2  * rpcgen - Generate XDR bindings automatically.
3  * Copyright (C) 2008 Red Hat Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19
20 %{
21 #include <config.h>
22 #include "rpcgen_parse.h"
23 #include "rpcgen_int.h"
24 %}
25
26 %option noyywrap
27 %option nounput
28 %option yylineno
29
30 HEXLIT     "0x"[0-9a-fA-F]+
31 DECLIT     0|[1-9][0-9]*
32 INTLIT     {HEXLIT}|{DECLIT}
33 IDENT      [a-zA-Z_][a-zA-Z_0-9]*
34 WS         [[:space:]]+
35
36 %x cstring
37
38 %%
39
40  /* # lineno "filename"
41   * cpp itself sets file and line numbers using these directives.  We
42   * have to parse this ourselves, since these could occur anywhere in
43   * the input, eg. in the middle of a struct definition.
44   */
45 ^"#".*\n    {
46   char *filename;
47   int lineno;
48
49   /* Allocate enough space to store the returned filename string. */
50   filename = malloc (strlen (yytext));
51   if (filename == NULL) perrorf ("malloc");
52
53   if (sscanf (yytext+2, "%d \"%[^\"]\"", &lineno, filename) == 2) {
54     yylineno = lineno - 1;
55     free (input_filename);
56     input_filename = filename;
57   }
58   else free (filename);
59  }
60
61  /* Anything on a line beginning with % is passed to the output.  Again
62   * we have to handle this within the scanner.
63   */
64 ^"%".*\n   fputs (yytext+1, yyout);
65
66  /* C string constants. */
67 \"         start_string(); BEGIN (cstring);
68 <cstring>{
69   \"       BEGIN (INITIAL); yylval.str = end_string(); return STRLIT;
70
71   \n       error ("unterminated string constant");
72   <<EOF>>  error ("unterminated string constant");
73
74   \\[0-7]{1,3} {
75     /* octal escape sequence */
76     int result;
77
78     (void) sscanf (yytext + 1, "%o", &result);
79
80     if (result > 0xff)
81       error ("octal constant is out of range");
82
83     add_char (result);
84   }
85
86   /* Does C allow these?? Maybe confusing it with OCaml.
87   \\x[0-9a-fA-F]{2} {
88     int result;
89
90     (void) sscanf( yytext + 1, "%x", &result );
91
92     add_char (result);
93   } */
94
95   \\[0-9]+ {
96     /* generate error - bad escape sequence; something
97      * like '\48' or '\0777777'
98      */
99     error ("bad escape sequence: %s\n", yytext);
100   }
101
102   \\n  add_char ('\n');
103   \\t  add_char ('\t');
104   \\r  add_char ('\r');
105   \\b  add_char ('\b');
106   \\f  add_char ('\f');
107
108   /* Backslash followed by a literal newline character. */
109   \\\n add_char ('\n');
110
111   /* Unrecognised escape character - should be an error? */
112   \\.  add_char (yytext[1]);
113
114   [^\\\n\"]+ {
115     add_string (yytext);
116   }
117 }
118
119  /* Keywords. */
120 struct     return STRUCT;
121 enum       return ENUM;
122 const      return CONST;
123 typedef    return TYPEDEF;
124 union      return UNION;
125 switch     return SWITCH;
126 case       return CASE;
127 default    return DEFAULT;
128 program    return PROGRAM;
129
130 unsigned   return UNSIGNED;
131 signed     return SIGNED;
132 char       return CHAR;
133 short      return SHORT;
134 int        return INT;
135 hyper      return HYPER;
136 double     return DOUBLE;
137 string     return STRING;
138 opaque     return OPAQUE;
139
140 void       return VOID;
141
142  /* Identifiers. */
143 {IDENT}    { yylval.str = strdup (yytext); return IDENT; }
144
145  /* Numeric constants are tricky to scan accurately, so keep them as
146   * strings and pass them through directly to the C compiler.
147   */
148 {INTLIT}   { yylval.str = strdup (yytext); return INTLIT; }
149
150  /* Single characters with special meaning. */
151 ":"|";"|","|"{"|"}"|"("|")"|"["|"]"|"<"|">"|"="|"*" return yytext[0];
152
153  /* Ignore whitespace. */
154 {WS}
155
156  /* Anything else is an error. */
157 .          error ("invalid character in input near '%c'", yytext[0]);