3 #include "sane-ctype.h"
8 /* on line, no non-whitespace yet. */
10 /* Last was non-whitespace. */
11 #define PS_LAST_NOT_WS 1
12 /* Last was whitespace, non-ws seen. */
13 #define PS_WHITESPACE 2
14 /* Last was newline. */
16 /* Last was Carriage return. */
20 /* On non-comment line. */
21 #define PS2_NOT_COMMENT 1
22 /* On comment line. */
30 /* Main parser status. */
32 /* Secondary parser status. */
36 /* Number of class to parse. */
38 /* Number of fields. */
40 /* Number of locals. */
42 /* Max number of locals. */
44 /* Allocated size of instructions. */
45 size_t p_ins_allocated
;
46 /* Real size of instructions. */
52 /* Have value for field. 0 = no, 1 = zero, 2 = nonzero. */
53 unsigned p_have_field_value
;
56 #define CARRIAGE_RETURN 13
65 /*****************************************************************************/
66 struct parser
* parser_create()
68 struct parser
* parser
;
69 parser
= malloc(sizeof(struct parser
));
71 fprintf(stderr
, "Out of memory!\n");
76 parser
->p_status
= PS_INITIAL
;
77 parser
->p_status2
= PS2_INITIAL
;
78 parser
->p_backslash
= 0;
79 parser
->p_classnum
= 0;
82 parser
->p_maxlocals
= 0;
83 parser
->p_ins_allocated
= 0;
84 parser
->p_ins_size
= 0;
87 parser
->p_have_field_value
= 0;
92 /*****************************************************************************/
93 void parser_destroy(struct parser
* parser
)
99 /*****************************************************************************/
100 static void parser_input3(struct parser
* parser
, char input
)
103 if(parser
->p_field
== 2) {
104 fprintf(stderr
, "Line %zu: Illegal character <%02X> "
105 "in class body.\n", parser
->p_line
, input
);
109 parser
->p_have_field_value
= 0;
110 } else if(input
== LINEFEED
) {
111 if(parser
->p_field
< 1) {
112 fprintf(stderr
, "Line %zu: Truncated class "
113 "description.\n", parser
->p_line
);
117 if(parser
->p_locals
> parser
->p_maxlocals
)
118 parser
->p_maxlocals
= parser
->p_locals
;
121 class = class_make(parser
->p_fields
, parser
->p_locals
,
122 parser
->p_ins
, parser
->p_ins_size
);
123 class_register(class);
125 parser
->p_ins
= NULL
;
126 parser
->p_ins_allocated
= 0;
127 parser
->p_ins_size
= 0;
128 parser
->p_have_field_value
= 0;
130 parser
->p_fields
= 0;
131 parser
->p_locals
= 0;
132 } else if(parser
->p_field
< 2) {
133 if(input
< ZERO
&& input
> NINE
) {
134 fprintf(stderr
, "Line %zu: Illegal character <%02X> "
135 "in numeric value.\n", parser
->p_line
,
140 if(parser
->p_have_field_value
== 1) {
141 fprintf(stderr
, "Line %zu: Invalid numeric "
142 "value.\n", parser
->p_line
);
148 if(parser
->p_field
== 0)
149 parser
->p_fields
= 10 * parser
->p_fields
+
152 parser
->p_locals
= 10 * parser
->p_locals
+
171 fprintf(stderr
, "Line %zu: Invalid instruction "
172 "<%02X>.\n", parser
->p_line
, input
);
175 if(parser
->p_ins_size
== parser
->p_ins_allocated
) {
176 if(parser
->p_ins_allocated
== 0)
177 parser
->p_ins_allocated
= 2;
178 parser
->p_ins_allocated
= parser
->p_ins_allocated
*
180 parser
->p_ins
= realloc(parser
->p_ins
,
181 parser
->p_ins_allocated
);
183 fprintf(stderr
, "Out of memory.\n");
187 parser
->p_ins
[parser
->p_ins_size
++] = input
;
191 /*****************************************************************************/
192 static void parser_input2(struct parser
* parser
, char input
)
194 /* Here, we got to handle comments and backslashes. */
195 if(parser
->p_backslash
&& (input
== LINEFEED
|| input
== SPACE
))
197 parser
->p_backslash
= (input
== BACKSLASH
);
198 if(input
== BACKSLASH
)
201 switch(parser
->p_status2
) {
204 parser
->p_status2
= PS2_COMMENT
;
206 parser
->p_status2
= PS2_NOT_COMMENT
;
207 parser_input3(parser
, input
);
210 case PS2_NOT_COMMENT
:
211 parser_input3(parser
, input
);
214 if(input
== LINEFEED
)
215 parser
->p_status2
= PS2_INITIAL
;
220 /*****************************************************************************/
221 void parser_input(struct parser
* parser
, char input
)
223 /* We need to clean up input so that whitespaces are normalized. */
224 unsigned is_space
= sane_isspace((unsigned char)input
);
225 unsigned is_newline
= sane_isnewline((unsigned char)input
);
227 switch(parser
->p_status
) {
230 parser
->p_status
= ((input
== CARRIAGE_RETURN
) ?
231 PS_LAST_CR
: PS_NEWLINE
);
233 } else if(is_space
) {
236 parser
->p_status
= PS_LAST_NOT_WS
;
237 parser_input2(parser
, input
);
242 parser_input2(parser
, LINEFEED
);
243 parser
->p_status
= ((input
== CARRIAGE_RETURN
) ?
244 PS_LAST_CR
: PS_NEWLINE
);
246 } else if(is_space
) {
247 parser
->p_status
= PS_WHITESPACE
;
249 parser_input2(parser
, input
);
254 parser_input2(parser
, LINEFEED
);
255 parser
->p_status
= ((input
== CARRIAGE_RETURN
) ?
256 PS_LAST_CR
: PS_NEWLINE
);
258 } else if(is_space
) {
261 parser
->p_status
= PS_LAST_NOT_WS
;
262 parser_input2(parser
, SPACE
);
263 parser_input2(parser
, input
);
268 parser
->p_status
= ((input
== CARRIAGE_RETURN
) ?
269 PS_LAST_CR
: PS_NEWLINE
);
271 } else if(is_space
) {
272 parser
->p_status
= PS_INITIAL
;
274 parser
->p_status
= PS_LAST_NOT_WS
;
275 parser_input2(parser
, input
);
280 parser
->p_status
= ((input
== CARRIAGE_RETURN
) ?
281 PS_LAST_CR
: PS_NEWLINE
);
282 if(input
!= LINEFEED
)
284 } else if(is_space
) {
285 parser
->p_status
= PS_INITIAL
;
287 parser
->p_status
= PS_LAST_NOT_WS
;
288 parser_input2(parser
, input
);
294 /*****************************************************************************/
295 void parser_eof(struct parser
* parser
)
297 if(parser
->p_status
== PS_LAST_NOT_WS
||
298 parser
->p_status
== PS_WHITESPACE
)
299 parser_input2(parser
, LINEFEED
);
302 /*****************************************************************************/
303 size_t parser_maxlocals(struct parser
* parser
)
305 return parser
->p_maxlocals
;