Rename .cc files to .cpp
[mesa.git] / glsl_parser_extras.cpp
1 /*
2 * Copyright © 2008, 2009 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33
34 #include "ast.h"
35 #include "glsl_parser_extras.h"
36 #include "glsl_parser.tab.h"
37 #include "symbol_table.h"
38
39 void
40 _mesa_glsl_error(YYLTYPE *locp, void *state, const char *fmt, ...)
41 {
42 char buf[1024];
43 int len;
44 va_list ap;
45
46 (void) state;
47 len = snprintf(buf, sizeof(buf), "%u:%u(%u): error: ",
48 locp->source, locp->first_line, locp->first_column);
49
50 va_start(ap, fmt);
51 vsnprintf(buf + len, sizeof(buf) - len, fmt, ap);
52 va_end(ap);
53
54 printf("%s\n", buf);
55 }
56
57
58 ast_node::~ast_node()
59 {
60 /* empty */
61 }
62
63
64 void
65 _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
66 {
67 if (q->constant)
68 printf("const ");
69
70 if (q->invariant)
71 printf("invariant ");
72
73 if (q->attribute)
74 printf("attribute ");
75
76 if (q->varying)
77 printf("varying ");
78
79 if (q->in && q->out)
80 printf("inout ");
81 else {
82 if (q->in)
83 printf("in ");
84
85 if (q->out)
86 printf("out ");
87 }
88
89 if (q->centroid)
90 printf("centroid ");
91 if (q->uniform)
92 printf("uniform ");
93 if (q->smooth)
94 printf("smooth ");
95 if (q->flat)
96 printf("flat ");
97 if (q->noperspective)
98 printf("noperspective ");
99 }
100
101
102 void
103 ast_node::print(void) const
104 {
105 printf("node_%d ", type);
106 }
107
108
109 ast_node::ast_node(void)
110 {
111 make_empty_list(this);
112 }
113
114 void
115 ast_type_specifier::print(void) const
116 {
117 switch (type_specifier) {
118 case ast_void: printf("void "); break;
119 case ast_float: printf("float "); break;
120 case ast_int: printf("int "); break;
121 case ast_uint: printf("uint "); break;
122 case ast_bool: printf("bool "); break;
123 case ast_vec2: printf("vec2 "); break;
124 case ast_vec3: printf("vec3 "); break;
125 case ast_vec4: printf("vec4 "); break;
126 case ast_bvec2: printf("bvec2 "); break;
127 case ast_bvec3: printf("bvec3 "); break;
128 case ast_bvec4: printf("bvec4 "); break;
129 case ast_ivec2: printf("ivec2 "); break;
130 case ast_ivec3: printf("ivec3 "); break;
131 case ast_ivec4: printf("ivec4 "); break;
132 case ast_uvec2: printf("uvec2 "); break;
133 case ast_uvec3: printf("uvec3 "); break;
134 case ast_uvec4: printf("uvec4 "); break;
135 case ast_mat2: printf("mat2 "); break;
136 case ast_mat2x3: printf("mat2x3 "); break;
137 case ast_mat2x4: printf("mat2x4 "); break;
138 case ast_mat3x2: printf("mat3x2 "); break;
139 case ast_mat3: printf("mat3 "); break;
140 case ast_mat3x4: printf("mat3x4 "); break;
141 case ast_mat4x2: printf("mat4x2 "); break;
142 case ast_mat4x3: printf("mat4x3 "); break;
143 case ast_mat4: printf("mat4 "); break;
144 case ast_sampler1d: printf("sampler1d "); break;
145 case ast_sampler2d: printf("sampler2d "); break;
146 case ast_sampler3d: printf("sampler3d "); break;
147 case ast_samplercube: printf("samplercube "); break;
148 case ast_sampler1dshadow: printf("sampler1dshadow "); break;
149 case ast_sampler2dshadow: printf("sampler2dshadow "); break;
150 case ast_samplercubeshadow: printf("samplercubeshadow "); break;
151 case ast_sampler1darray: printf("sampler1darray "); break;
152 case ast_sampler2darray: printf("sampler2darray "); break;
153 case ast_sampler1darrayshadow: printf("sampler1darrayshadow "); break;
154 case ast_sampler2darrayshadow: printf("sampler2darrayshadow "); break;
155 case ast_isampler1d: printf("isampler1d "); break;
156 case ast_isampler2d: printf("isampler2d "); break;
157 case ast_isampler3d: printf("isampler3d "); break;
158 case ast_isamplercube: printf("isamplercube "); break;
159 case ast_isampler1darray: printf("isampler1darray "); break;
160 case ast_isampler2darray: printf("isampler2darray "); break;
161 case ast_usampler1d: printf("usampler1d "); break;
162 case ast_usampler2d: printf("usampler2d "); break;
163 case ast_usampler3d: printf("usampler3d "); break;
164 case ast_usamplercube: printf("usamplercube "); break;
165 case ast_usampler1darray: printf("usampler1darray "); break;
166 case ast_usampler2darray: printf("usampler2darray "); break;
167
168 case ast_struct:
169 structure->print();
170 break;
171
172 case ast_type_name: printf("%s ", type_name); break;
173 }
174
175 if (is_array) {
176 printf("[ ");
177
178 if (array_size) {
179 array_size->print();
180 }
181
182 printf("] ");
183 }
184 }
185
186 static void
187 ast_opt_array_size_print(bool is_array, const ast_expression *array_size)
188 {
189 if (is_array) {
190 printf("[ ");
191
192 if (array_size)
193 array_size->print();
194
195 printf("] ");
196 }
197 }
198
199
200 ast_type_specifier::ast_type_specifier(int specifier)
201 {
202 type_specifier = ast_types(specifier);
203 }
204
205
206 void
207 ast_compound_statement::print(void) const
208 {
209 const struct simple_node *ptr;
210
211 printf("{\n");
212
213 foreach(ptr, & statements) {
214 _mesa_ast_print(ptr);
215 }
216
217 printf("}\n");
218 }
219
220
221 ast_compound_statement::ast_compound_statement(int new_scope,
222 ast_node *statements)
223 {
224 this->new_scope = new_scope;
225 make_empty_list(& this->statements);
226
227 if (statements != NULL) {
228 /* This seems odd, but it works. The simple_list is,
229 * basically, a circular list. insert_at_tail adds
230 * the specified node to the list before the current
231 * head.
232 */
233 insert_at_tail((struct simple_node *) statements,
234 & this->statements);
235 }
236 }
237
238
239 void
240 ast_expression::print(void) const
241 {
242 static const char *const operators[] = {
243 "=",
244 "+",
245 "-",
246 "+",
247 "-",
248 "*",
249 "/",
250 "%",
251 "<<",
252 ">>",
253 "<",
254 ">",
255 "<=",
256 ">=",
257 "==",
258 "!=",
259 "&",
260 "^",
261 "|",
262 "~",
263 "&&",
264 "^^",
265 "!",
266
267 "*=",
268 "/=",
269 "%=",
270 "+=",
271 "-=",
272 "<<=",
273 ">>=",
274 "&=",
275 "^=",
276 "|=",
277
278 "?:",
279 "++",
280 "--",
281 "++",
282 "--",
283 ".",
284 };
285
286
287 switch (oper) {
288 case ast_assign:
289 case ast_add:
290 case ast_sub:
291 case ast_mul:
292 case ast_div:
293 case ast_mod:
294 case ast_lshift:
295 case ast_rshift:
296 case ast_less:
297 case ast_greater:
298 case ast_lequal:
299 case ast_gequal:
300 case ast_equal:
301 case ast_nequal:
302 case ast_bit_and:
303 case ast_bit_xor:
304 case ast_bit_or:
305 case ast_logic_and:
306 case ast_logic_xor:
307 case ast_logic_or:
308 case ast_mul_assign:
309 case ast_div_assign:
310 case ast_mod_assign:
311 case ast_add_assign:
312 case ast_sub_assign:
313 case ast_ls_assign:
314 case ast_rs_assign:
315 case ast_and_assign:
316 case ast_xor_assign:
317 case ast_or_assign:
318 subexpressions[0]->print();
319 printf("%s ", operators[oper]);
320 subexpressions[1]->print();
321 break;
322
323 case ast_field_selection:
324 subexpressions[0]->print();
325 printf(". %s ", primary_expression.identifier);
326 break;
327
328 case ast_plus:
329 case ast_neg:
330 case ast_bit_not:
331 case ast_logic_not:
332 case ast_pre_inc:
333 case ast_pre_dec:
334 printf("%s ", operators[oper]);
335 subexpressions[0]->print();
336 break;
337
338 case ast_post_inc:
339 case ast_post_dec:
340 subexpressions[0]->print();
341 printf("%s ", operators[oper]);
342 break;
343
344 case ast_conditional:
345 subexpressions[0]->print();
346 printf("? ");
347 subexpressions[1]->print();
348 printf(": ");
349 subexpressions[1]->print();
350 break;
351
352 case ast_array_index:
353 subexpressions[0]->print();
354 printf("[ ");
355 subexpressions[1]->print();
356 printf("] ");
357 break;
358
359 case ast_function_call: {
360 ast_expression *parameters = subexpressions[1];
361
362 subexpressions[0]->print();
363 printf("( ");
364
365 if (parameters != NULL) {
366 struct simple_node *ptr;
367
368 parameters->print();
369 foreach (ptr, (struct simple_node *) parameters) {
370 printf(", ");
371 _mesa_ast_print(ptr);
372 }
373 }
374
375 printf(") ");
376 break;
377 }
378
379 case ast_identifier:
380 printf("%s ", primary_expression.identifier);
381 break;
382
383 case ast_int_constant:
384 printf("%d ", primary_expression.int_constant);
385 break;
386
387 case ast_uint_constant:
388 printf("%u ", primary_expression.uint_constant);
389 break;
390
391 case ast_float_constant:
392 printf("%f ", primary_expression.float_constant);
393 break;
394
395 case ast_bool_constant:
396 printf("%s ",
397 primary_expression.bool_constant
398 ? "true" : "false");
399 break;
400
401 case ast_sequence: {
402 struct simple_node *ptr;
403 struct simple_node *const head = first_elem(& expressions);
404
405 printf("( ");
406 foreach (ptr, & expressions) {
407 if (ptr != head)
408 printf(", ");
409
410 _mesa_ast_print(ptr);
411 }
412 printf(") ");
413 break;
414 }
415 }
416 }
417
418 ast_expression::ast_expression(int oper,
419 ast_expression *ex0,
420 ast_expression *ex1,
421 ast_expression *ex2)
422 {
423 this->oper = ast_operators(oper);
424 this->subexpressions[0] = ex0;
425 this->subexpressions[1] = ex1;
426 this->subexpressions[2] = ex2;
427 make_empty_list(& expressions);
428 }
429
430
431 void
432 ast_expression_statement::print(void) const
433 {
434 if (expression)
435 expression->print();
436
437 printf("; ");
438 }
439
440
441 ast_expression_statement::ast_expression_statement(ast_expression *ex) :
442 expression(ex)
443 {
444 /* empty */
445 }
446
447
448 void
449 ast_function::print(void) const
450 {
451 struct simple_node *ptr;
452
453 return_type->print();
454 printf(" %s (", identifier);
455
456 foreach(ptr, & parameters) {
457 _mesa_ast_print(ptr);
458 }
459
460 printf(")");
461 }
462
463
464 ast_function::ast_function(void)
465 {
466 make_empty_list(& parameters);
467 }
468
469
470 void
471 ast_fully_specified_type::print(void) const
472 {
473 _mesa_ast_type_qualifier_print(& qualifier);
474 specifier->print();
475 }
476
477
478 void
479 ast_parameter_declarator::print(void) const
480 {
481 type->print();
482 if (identifier)
483 printf("%s ", identifier);
484 ast_opt_array_size_print(is_array, array_size);
485 }
486
487
488 void
489 ast_function_definition::print(void) const
490 {
491 prototype->print();
492 body->print();
493 }
494
495
496 void
497 ast_declaration::print(void) const
498 {
499 printf("%s ", identifier);
500 ast_opt_array_size_print(is_array, array_size);
501
502 if (initializer) {
503 printf("= ");
504 initializer->print();
505 }
506 }
507
508
509 ast_declaration::ast_declaration(char *identifier, int is_array,
510 ast_expression *array_size,
511 ast_expression *initializer)
512 {
513 this->identifier = identifier;
514 this->is_array = is_array;
515 this->array_size = array_size;
516 this->initializer = initializer;
517 }
518
519
520 void
521 ast_declarator_list::print(void) const
522 {
523 struct simple_node *head;
524 struct simple_node *ptr;
525
526 assert(type || invariant);
527
528 if (type)
529 type->print();
530 else
531 printf("invariant ");
532
533 head = first_elem(& declarations);
534 foreach (ptr, & declarations) {
535 if (ptr != head)
536 printf(", ");
537
538 _mesa_ast_print(ptr);
539 }
540
541 printf("; ");
542 }
543
544
545 ast_declarator_list::ast_declarator_list(ast_fully_specified_type *type)
546 {
547 this->type = type;
548 make_empty_list(& this->declarations);
549 }
550
551 void
552 ast_jump_statement::print(void) const
553 {
554 switch (mode) {
555 case ast_continue:
556 printf("continue; ");
557 break;
558 case ast_break:
559 printf("break; ");
560 break;
561 case ast_return:
562 printf("return ");
563 if (opt_return_value)
564 opt_return_value->print();
565
566 printf("; ");
567 break;
568 case ast_discard:
569 printf("discard; ");
570 break;
571 }
572 }
573
574
575 ast_jump_statement::ast_jump_statement(int mode, ast_expression *return_value)
576 {
577 this->mode = ast_jump_modes(mode);
578
579 if (mode == ast_return)
580 opt_return_value = return_value;
581 }
582
583
584 void
585 ast_selection_statement::print(void) const
586 {
587 printf("if ( ");
588 condition->print();
589 printf(") ");
590
591 then_statement->print();
592
593 if (else_statement) {
594 printf("else ");
595 else_statement->print();
596 }
597
598 }
599
600
601 ast_selection_statement::ast_selection_statement(ast_expression *condition,
602 ast_node *then_statement,
603 ast_node *else_statement)
604 {
605 this->condition = condition;
606 this->then_statement = then_statement;
607 this->else_statement = else_statement;
608 }
609
610
611 void
612 ast_iteration_statement::print(void) const
613 {
614 switch (mode) {
615 case ast_for:
616 printf("for( ");
617 if (init_statement)
618 init_statement->print();
619 printf("; ");
620
621 if (condition)
622 condition->print();
623 printf("; ");
624
625 if (rest_expression)
626 rest_expression->print();
627 printf(") ");
628
629 body->print();
630 break;
631
632 case ast_while:
633 printf("while ( ");
634 if (condition)
635 condition->print();
636 printf(") ");
637 body->print();
638 break;
639
640 case ast_do_while:
641 printf("do ");
642 body->print();
643 printf("while ( ");
644 if (condition)
645 condition->print();
646 printf("); ");
647 break;
648 }
649 }
650
651
652 ast_iteration_statement::ast_iteration_statement(int mode,
653 ast_node *init,
654 ast_node *condition,
655 ast_expression *rest_expression,
656 ast_node *body)
657 {
658 this->mode = ast_iteration_modes(mode);
659 this->init_statement = init;
660 this->condition = condition;
661 this->rest_expression = rest_expression;
662 this->body = body;
663 }
664
665
666 void
667 ast_struct_specifier::print(void) const
668 {
669 struct simple_node *ptr;
670
671 printf("struct %s { ", name);
672 foreach (ptr, & declarations) {
673 _mesa_ast_print(ptr);
674 }
675 printf("} ");
676 }
677
678
679 ast_struct_specifier::ast_struct_specifier(char *identifier,
680 ast_node *declarator_list)
681 {
682 name = identifier;
683
684 /* This seems odd, but it works. The simple_list is,
685 * basically, a circular list. insert_at_tail adds
686 * the specified node to the list before the current
687 * head.
688 */
689 insert_at_tail((struct simple_node *) declarator_list,
690 & declarations);
691 }
692
693
694 static char *
695 load_text_file(const char *file_name, size_t *size)
696 {
697 char *text = NULL;
698 struct stat st;
699 ssize_t total_read = 0;
700 int fd = open(file_name, O_RDONLY);
701
702 *size = 0;
703 if (fd < 0) {
704 return NULL;
705 }
706
707 if (fstat(fd, & st) == 0) {
708 text = (char *) malloc(st.st_size + 1);
709 if (text != NULL) {
710 do {
711 ssize_t bytes = read(fd, text + total_read,
712 st.st_size - total_read);
713 if (bytes < 0) {
714 free(text);
715 text = NULL;
716 break;
717 }
718
719 if (bytes == 0) {
720 break;
721 }
722
723 total_read += bytes;
724 } while (total_read < st.st_size);
725
726 text[total_read] = '\0';
727 *size = total_read;
728 }
729 }
730
731 close(fd);
732
733 return text;
734 }
735
736
737 int
738 main(int argc, char **argv)
739 {
740 struct _mesa_glsl_parse_state state;
741 char *shader;
742 size_t shader_len;
743 struct simple_node *ptr;
744 struct simple_node instructions;
745
746 (void) argc;
747 shader = load_text_file(argv[1], & shader_len);
748
749 state.scanner = NULL;
750 make_empty_list(& state.translation_unit);
751 state.symbols = _mesa_symbol_table_ctor();
752
753 _mesa_glsl_lexer_ctor(& state, shader, shader_len);
754 _mesa_glsl_parse(& state);
755 _mesa_glsl_lexer_dtor(& state);
756
757 foreach (ptr, & state.translation_unit) {
758 _mesa_ast_print(ptr);
759 }
760
761 #if 0
762 make_empty_list(& instructions);
763 foreach (ptr, & state.translation_unit) {
764 _mesa_ast_to_hir(ptr, &instructions, &state);
765 }
766 #endif
767
768 _mesa_symbol_table_dtor(state.symbols);
769
770 return 0;
771 }