2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 #define DEBUG_PARSING 0
29 * ARB_*_program parser core
30 * \author Michal Krol, Karl Rasche
40 #include "nvvertprog.h"
41 #include "nvfragprog.h"
45 * Fragment Program Stuff:
46 * -----------------------------------------------------
47 * - How does negating on SWZ work?? If any of the components have a -,
49 * - how does thing like 'foo[N]' work in src registers?
51 * - things from Michal's email
53 * + not-overflowing floats (don't use parse_integer..)
54 * + can remove range checking in arbparse.c
56 * - check all limits of number of various variables
61 * Vertex Program Stuff:
62 * -----------------------------------------------------
63 * - throw an error if we mess with position and have are position invar
67 * -----------------------------------------------------
68 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
69 * - fetch state listed in program_parameters list
70 * + WTF should this go???
71 * + currently in nvvertexec.c and s_nvfragprog.c
73 * - allow for multiple address registers (and fetch address regs properly)
76 * -----------------------------------------------------
77 * - remove any leftover unused grammer.c stuff (dict_ ?)
78 * - fix grammer.c error handling so its not static
79 * - #ifdef around stuff pertaining to extentions
81 * Outstanding Questions:
82 * -----------------------------------------------------
83 * - ARB_matrix_palette / ARB_vertex_blend -- not supported
84 * what gets hacked off because of this:
85 * + VERTEX_ATTRIB_MATRIXINDEX
86 * + VERTEX_ATTRIB_WEIGHT
90 * - When can we fetch env/local params from their own register files, and
91 * when to we have to fetch them into the main state register file?
95 * -----------------------------------------------------
98 typedef GLubyte
*production
;
100 /*-----------------------------------------------------------------------
101 * From here on down is the syntax checking portion
110 The task is to check the syntax of an input string. Input string is a
111 stream of ASCII characters terminated with null-character
112 ('\0'). Checking it using C language is difficult and hard to
113 implement without bugs. It is hard to maintain and change prior to
114 further syntax changes.
116 This is because of high redundancy of the C code. Large blocks of code
117 are duplicated with only small changes. Even using macros does not
118 solve the problem, because macros cannot erase the complexity of the
121 The resolution is to create a new language that will be highly
122 oriented to our task. Once we describe particular syntax, we are
123 done. We can then focus on the code that implements the language. The
124 size and complexity of it is relatively small than the code that
125 directly checks the syntax.
127 First, we must implement our new language. Here, the language is
128 implemented in C, but it could also be implemented in any other
129 language. The code is listed below. We must take a good care that it
130 is bug free. This is simple because the code is simple and clean.
132 Next, we must describe the syntax of our new language in itself. Once
133 created and checked manually that it is correct, we can use it to
134 check another scripts.
136 Note that our new language loading code does not have to check the
137 syntax. It is because we assume that the script describing itself is
138 correct, and other scripts can be syntactically checked by the former
139 script. The loading code must only do semantic checking which leads us
140 to simple resolving references.
145 Here I will describe the syntax of the new language (further called
146 "Synek"). It is mainly a sequence of declarations terminated by a
147 semicolon. The declaration consists of a symbol, which is an
148 identifier, and its definition. A definition is in turn a sequence of
149 specifiers connected with ".and" or ".or" operator. These operators
150 cannot be mixed together in a one definition. Specifier can be a
151 symbol, string, character, character range or a special keyword
154 On the very beginning of the script there is a declaration of a root
155 symbol and is in the form:
156 .syntax <root_symbol>;
158 The <root_symbol> must be on of the symbols in declaration
159 sequence. The syntax is correct if the root symbol evaluates to
160 true. A symbol evaluates to true if the definition associated with the
161 symbol evaluates to true. Definition evaluation depends on the
162 operator used to connect specifiers in the definition. If ".and"
163 operator is used, definition evaluates to true if and only if all the
164 specifiers evaluate to true. If ".or" operator is used, definition
165 evalutes to true if any of the specifiers evaluates to true. If
166 definition contains only one specifier, it is evaluated as if it was
167 connected with ".true" keyword by ".and" operator.
169 If specifier is a ".true" keyword, it always evaluates to true.
171 If specifier is a ".false" keyword, it always evaluates to
172 false. Specifier evaluates to false when it does not evaluate to true.
174 Character range specifier is in the form:
175 '<first_character>' - '<second_character>'
177 If specifier is a character range, it evaluates to true if character
178 in the stream is greater or equal to <first_character> and less or
179 equal to <second_character>. In that situation the stream pointer is
180 advanced to point to next character in the stream. All C-style escape
181 sequences are supported although trigraph sequences are not. The
182 comparisions are performed on 8-bit unsigned integers.
184 Character specifier is in the form:
187 It evaluates to true if the following character range specifier evaluates to
189 '<single_character>' - '<single_character>'
191 String specifier is in the form:
194 Let N be the number of characters in <string>. Let <string>[i]
195 designate i-th character in <string>. Then the string specifier
196 evaluates to true if and only if for i in the range [0, N) the
197 following character specifier evaluates to true:
200 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
203 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
205 where <symbol> is defined as follows:
206 <symbol> <definition>; (2)
207 Construction (1) is replaced by the following code:
209 and declaration (2) is replaced by the following:
210 <symbol$1> <symbol$2> .or .true;
211 <symbol$2> <symbol> .and <symbol$1>;
212 <symbol> <definition>;
218 Synek supports all escape sequences in character specifiers. The
219 mapping table is listed below. All occurences of the characters in
220 the first column are replaced with the corresponding character in the
223 Escape sequence Represents
224 -----------------------------------------------------------------------
232 \' Single quotation mark
233 \" Double quotation mark
235 \? Literal question mark
236 \ooo ASCII character in octal notation
237 \xhhh ASCII character in hexadecimal notation
238 -----------------------------------------------------------------------
244 Any specifier can be followed by a special construction that is
245 executed when the specifier evaluates to false. The construction is in
249 <ERROR_TEXT> is an identifier declared earlier by error text
250 declaration. The declaration is in the form:
252 .errtext <ERROR_TEXT> "<error_desc>"
254 When specifier evaluates to false and this construction is present,
255 parsing is stopped immediately and <error_desc> is returned as a
256 result of parsing. The error position is also returned and it is meant
257 as an offset from the beggining of the stream to the character that
258 was valid so far. Example:
260 (**** syntax script ****)
263 .errtext MISSING_SEMICOLON "missing ';'"
264 program declaration .and .loop space .and ';'
265 .error MISSING_SEMICOLON .and
266 .loop space .and '\0';
267 declaration "declare" .and .loop space .and identifier;
269 (**** sample code ****)
272 In the example above checking the sample code will result in error
273 message "missing ';'" and error position 12. The sample code is not
274 correct. Note the presence of '\0' specifier to assure that there is
275 no code after semicolon - only spaces. <error_desc> can optionally
276 contain identifier surrounded by dollar signs $. In such a case, the
277 identifier and dollar signs are replaced by a string retrieved by
278 invoking symbol with the identifier name. The starting position is the
279 error position. The lenght of the resulting string is the position
280 after invoking the symbol.
286 Synek not only checks the syntax but it can also produce (emit) bytes
287 associated with specifiers that evaluate to true. That is, every
288 specifier and optional error construction can be followed by a number
289 of emit constructions that are in the form:
292 <paramater> can be a HEX number, identifier, a star * or a dollar
293 $. HEX number is preceded by 0x or 0X. If <parameter> is an
294 identifier, it must be earlier declared by emit code declaration in
296 .emtcode <identifier> <hex_number>
298 When given specifier evaluates to true, all emits associated with the
299 specifier are output in order they were declared. A star means that
300 last-read character should be output instead of constant
303 (**** syntax script ****)
306 .emtcode WORD_FOO 0x01
307 .emtcode WORD_BAR 0x02
308 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
309 FOO "foo" .and SPACE;
310 BAR "bar" .and SPACE;
313 (**** sample text 1 ****)
317 (**** sample text 2 ****)
321 For both samples the result will be one-element array. For first
322 sample text it will be value 1, for second - 0. Note that every text
323 will be accepted because of presence of .true as an alternative.
327 (**** syntax script ****)
330 .emtcode VARIABLE 0x01
331 declaration "declare" .and .loop space .and
332 identifier .emit VARIABLE .and (1)
333 .true .emit 0x00 .and (2)
334 .loop space .and ';';
336 identifier .loop id_char .emit *; (3)
337 id_char 'a'-'z' .or 'A'-'Z' .or '_';
338 (**** sample code ****)
341 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
342 it evaluates to true, VARIABLE constant and then production of the
343 symbol is output. Specifier (2) is used to terminate the string with
344 null to signal when the string ends. Specifier (3) outputs all
345 characters that make declared identifier. The result of sample code
346 will be the following array:
347 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
349 If .emit is followed by dollar $, it means that current position
350 should be output. Current position is a 32-bit unsigned integer
351 distance from the very beginning of the parsed string to first
352 character consumed by the specifier associated with the .emit
353 instruction. Current position is stored in the output buffer in
354 Little-Endian convention (the lowest byte comes first). */
357 * This is the text describing the rules to parse the grammar
359 #include "arbparse_syn.h"
362 * These should match up with the values defined in arbparse.syn.h
367 - changed and merged V_* and F_* opcode values to OP_*.
369 #define REVISION 0x05
372 #define FRAGMENT_PROGRAM 0x01
373 #define VERTEX_PROGRAM 0x02
375 /* program section */
377 #define INSTRUCTION 0x02
378 #define DECLARATION 0x03
381 /* fragment program option flags */
382 #define ARB_PRECISION_HINT_FASTEST 0x01
383 #define ARB_PRECISION_HINT_NICEST 0x02
384 #define ARB_FOG_EXP 0x04
385 #define ARB_FOG_EXP2 0x08
386 #define ARB_FOG_LINEAR 0x10
388 /* vertex program option flags */
390 $4: changed from 0x01 to 0x20.
392 #define ARB_POSITION_INVARIANT 0x20
394 /* fragment program 1.0 instruction class */
395 #define OP_ALU_INST 0x00
396 #define OP_TEX_INST 0x01
398 /* vertex program 1.0 instruction class */
401 /* fragment program 1.0 instruction type */
402 #define OP_ALU_VECTOR 0x06
403 #define OP_ALU_SCALAR 0x03
404 #define OP_ALU_BINSC 0x02
405 #define OP_ALU_BIN 0x01
406 #define OP_ALU_TRI 0x05
407 #define OP_ALU_SWZ 0x04
408 #define OP_TEX_SAMPLE 0x07
409 #define OP_TEX_KIL 0x08
411 /* vertex program 1.0 instruction type */
412 #define OP_ALU_ARL 0x00
420 /* fragment program 1.0 instruction code */
422 #define OP_ABS_SAT 0x1B
424 #define OP_FLR_SAT 0x26
426 #define OP_FRC_SAT 0x27
428 #define OP_LIT_SAT 0x2A
430 #define OP_MOV_SAT 0x30
432 #define OP_COS_SAT 0x20
434 #define OP_EX2_SAT 0x25
436 #define OP_LG2_SAT 0x29
438 #define OP_RCP_SAT 0x33
440 #define OP_RSQ_SAT 0x34
442 #define OP_SIN_SAT 0x39
444 #define OP_SCS_SAT 0x36
446 #define OP_POW_SAT 0x32
448 #define OP_ADD_SAT 0x1C
450 #define OP_DP3_SAT 0x21
452 #define OP_DP4_SAT 0x22
454 #define OP_DPH_SAT 0x23
456 #define OP_DST_SAT 0x24
458 #define OP_MAX_SAT 0x2E
460 #define OP_MIN_SAT 0x2F
462 #define OP_MUL_SAT 0x31
464 #define OP_SGE_SAT 0x37
466 #define OP_SLT_SAT 0x3A
468 #define OP_SUB_SAT 0x3B
470 #define OP_XPD_SAT 0x43
472 #define OP_CMP_SAT 0x1E
474 #define OP_LRP_SAT 0x2C
476 #define OP_MAD_SAT 0x2D
478 #define OP_SWZ_SAT 0x3C
480 #define OP_TEX_SAT 0x3E
482 #define OP_TXB_SAT 0x40
484 #define OP_TXP_SAT 0x42
487 /* vertex program 1.0 instruction code */
516 /* fragment attribute binding */
517 #define FRAGMENT_ATTRIB_COLOR 0x01
518 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
519 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
520 #define FRAGMENT_ATTRIB_POSITION 0x04
522 /* vertex attribute binding */
523 #define VERTEX_ATTRIB_POSITION 0x01
524 #define VERTEX_ATTRIB_WEIGHT 0x02
525 #define VERTEX_ATTRIB_NORMAL 0x03
526 #define VERTEX_ATTRIB_COLOR 0x04
527 #define VERTEX_ATTRIB_FOGCOORD 0x05
528 #define VERTEX_ATTRIB_TEXCOORD 0x06
529 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
530 #define VERTEX_ATTRIB_GENERIC 0x08
532 /* fragment result binding */
533 #define FRAGMENT_RESULT_COLOR 0x01
534 #define FRAGMENT_RESULT_DEPTH 0x02
536 /* vertex result binding */
537 #define VERTEX_RESULT_POSITION 0x01
538 #define VERTEX_RESULT_COLOR 0x02
539 #define VERTEX_RESULT_FOGCOORD 0x03
540 #define VERTEX_RESULT_POINTSIZE 0x04
541 #define VERTEX_RESULT_TEXCOORD 0x05
544 #define TEXTARGET_1D 0x01
545 #define TEXTARGET_2D 0x02
546 #define TEXTARGET_3D 0x03
547 #define TEXTARGET_RECT 0x04
548 #define TEXTARGET_CUBE 0x05
552 $3: removed. '+' and '-' are used instead.
555 #define SIGN_PLUS 0x00
556 #define SIGN_MINUS 0x01
560 #define FACE_FRONT 0x00
561 #define FACE_BACK 0x01
564 #define COLOR_PRIMARY 0x00
565 #define COLOR_SECONDARY 0x01
569 $3: Added enumerants.
571 #define COMPONENT_X 0x00
572 #define COMPONENT_Y 0x01
573 #define COMPONENT_Z 0x02
574 #define COMPONENT_W 0x03
575 #define COMPONENT_0 0x04
576 #define COMPONENT_1 0x05
578 #define ARRAY_INDEX_ABSOLUTE 0x00
579 #define ARRAY_INDEX_RELATIVE 0x01
582 #define MATRIX_MODELVIEW 0x01
583 #define MATRIX_PROJECTION 0x02
584 #define MATRIX_MVP 0x03
585 #define MATRIX_TEXTURE 0x04
586 #define MATRIX_PALETTE 0x05
587 #define MATRIX_PROGRAM 0x06
589 /* matrix modifier */
590 #define MATRIX_MODIFIER_IDENTITY 0x00
591 #define MATRIX_MODIFIER_INVERSE 0x01
592 #define MATRIX_MODIFIER_TRANSPOSE 0x02
593 #define MATRIX_MODIFIER_INVTRANS 0x03
596 #define CONSTANT_SCALAR 0x01
597 #define CONSTANT_VECTOR 0x02
599 /* program param type */
600 #define PROGRAM_PARAM_ENV 0x01
601 #define PROGRAM_PARAM_LOCAL 0x02
604 #define REGISTER_ATTRIB 0x01
605 #define REGISTER_PARAM 0x02
606 #define REGISTER_RESULT 0x03
607 #define REGISTER_ESTABLISHED_NAME 0x04
610 #define PARAM_NULL 0x00
611 #define PARAM_ARRAY_ELEMENT 0x01
612 #define PARAM_STATE_ELEMENT 0x02
613 #define PARAM_PROGRAM_ELEMENT 0x03
614 #define PARAM_PROGRAM_ELEMENTS 0x04
615 #define PARAM_CONSTANT 0x05
617 /* param state property */
618 #define STATE_MATERIAL_PARSER 0x01
619 #define STATE_LIGHT_PARSER 0x02
620 #define STATE_LIGHT_MODEL 0x03
621 #define STATE_LIGHT_PROD 0x04
622 #define STATE_FOG 0x05
623 #define STATE_MATRIX_ROWS 0x06
624 /* fragment program only */
625 #define STATE_TEX_ENV 0x07
626 #define STATE_DEPTH 0x08
627 /* vertex program only */
629 $4: incremented all the three emit codes by two to not collide with other STATE_* emit codes.
631 #define STATE_TEX_GEN 0x09
632 #define STATE_CLIP_PLANE 0x0A
633 #define STATE_POINT 0x0B
635 /* state material property */
636 #define MATERIAL_AMBIENT 0x01
637 #define MATERIAL_DIFFUSE 0x02
638 #define MATERIAL_SPECULAR 0x03
639 #define MATERIAL_EMISSION 0x04
640 #define MATERIAL_SHININESS 0x05
642 /* state light property */
643 #define LIGHT_AMBIENT 0x01
644 #define LIGHT_DIFFUSE 0x02
645 #define LIGHT_SPECULAR 0x03
646 #define LIGHT_POSITION 0x04
647 #define LIGHT_ATTENUATION 0x05
648 #define LIGHT_HALF 0x06
649 #define LIGHT_SPOT_DIRECTION 0x07
651 /* state light model property */
652 #define LIGHT_MODEL_AMBIENT 0x01
653 #define LIGHT_MODEL_SCENECOLOR 0x02
655 /* state light product property */
656 #define LIGHT_PROD_AMBIENT 0x01
657 #define LIGHT_PROD_DIFFUSE 0x02
658 #define LIGHT_PROD_SPECULAR 0x03
660 /* state texture environment property */
661 #define TEX_ENV_COLOR 0x01
663 /* state texture generation coord property */
664 #define TEX_GEN_EYE 0x01
665 #define TEX_GEN_OBJECT 0x02
667 /* state fog property */
668 #define FOG_COLOR 0x01
669 #define FOG_PARAMS 0x02
671 /* state depth property */
672 #define DEPTH_RANGE 0x01
674 /* state point parameters property */
675 #define POINT_SIZE 0x01
676 #define POINT_ATTENUATION 0x02
684 /* vertex program 1.0 only */
688 memory management routines
690 static GLvoid
*mem_alloc (GLsizei
);
691 static GLvoid
mem_free (GLvoid
**);
692 static GLvoid
*mem_realloc (GLvoid
*, GLsizei
, GLsizei
);
693 static GLubyte
*str_duplicate (const GLubyte
*);
696 internal error messages
698 static const GLubyte
*OUT_OF_MEMORY
=
699 (GLubyte
*) "internal error 1001: out of physical memory";
700 static const GLubyte
*UNRESOLVED_REFERENCE
=
701 (GLubyte
*) "internal error 1002: unresolved reference '$'";
703 static const GLubyte *INVALID_PARAMETER =
704 (GLubyte *) "internal error 1003: invalid parameter";
707 static const GLubyte
*error_message
= NULL
;
708 static GLubyte
*error_param
= NULL
; /* this is inserted into error_message in place of $ */
709 static GLint error_position
= -1;
711 static GLubyte
*unknown
= (GLubyte
*) "???";
714 clear_last_error (GLvoid
)
716 /* reset error message */
717 error_message
= NULL
;
719 /* free error parameter - if error_param is a "???" don't free it - it's static */
720 if (error_param
!= unknown
)
721 mem_free ((GLvoid
**) & error_param
);
725 /* reset error position */
730 set_last_error (const GLubyte
* msg
, GLubyte
* param
, GLint pos
)
732 if (error_message
!= NULL
)
739 error_param
= unknown
;
741 error_position
= pos
;
745 * memory management routines
748 mem_alloc (GLsizei size
)
750 GLvoid
*ptr
= _mesa_malloc (size
);
752 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
757 mem_free (GLvoid
** ptr
)
764 mem_realloc (GLvoid
* ptr
, GLsizei old_size
, GLsizei new_size
)
766 GLvoid
*ptr2
= _mesa_realloc (ptr
, old_size
, new_size
);
768 set_last_error (OUT_OF_MEMORY
, NULL
, -1);
773 str_duplicate (const GLubyte
* str
)
775 return (GLubyte
*) _mesa_strdup ((const char *) str
);
781 typedef enum emit_type_
783 et_byte
, /* explicit number */
784 et_stream
, /* eaten character */
785 et_position
/* current position */
794 emit_type m_emit_type
;
795 GLubyte m_byte
; /* et_byte */
796 struct emit_
*m_next
;
801 emit_create (emit
** em
)
803 *em
= (emit
*) mem_alloc (sizeof (emit
));
805 (**em
).m_emit_type
= et_byte
;
807 (**em
).m_next
= NULL
;
812 emit_destroy (emit
** em
)
815 emit_destroy (&(**em
).m_next
);
816 mem_free ((GLvoid
**) em
);
821 emit_append (emit
** em
, emit
** ne
)
824 emit_append (&(**em
).m_next
, ne
);
832 typedef struct error_
835 GLubyte
*m_token_name
;
836 struct defntn_
*m_token
;
841 error_create (error
** er
)
843 *er
= (error
*) mem_alloc (sizeof (error
));
845 (**er
).m_text
= NULL
;
846 (**er
).m_token_name
= NULL
;
847 (**er
).m_token
= NULL
;
852 error_destroy (error
** er
)
855 mem_free ((GLvoid
**) & (**er
).m_text
);
856 mem_free ((GLvoid
**) & (**er
).m_token_name
);
857 mem_free ((GLvoid
**) er
);
862 static GLubyte
*error_get_token (error
*, struct dict_
*, const GLubyte
*, GLuint
);
865 * specifier type typedef
867 typedef enum spec_type_
885 spec_type m_spec_type
;
886 GLubyte m_byte
[2]; /* st_byte, st_byte_range */
887 GLubyte
*m_string
; /* st_string */
888 struct defntn_
*m_defntn
; /* st_identifier, st_identifier_loop */
891 struct spec_
*m_next
;
896 spec_create (spec
** sp
)
898 *sp
= (spec
*) mem_alloc (sizeof (spec
));
900 (**sp
).m_spec_type
= st_false
;
901 (**sp
).m_byte
[0] = '\0';
902 (**sp
).m_byte
[1] = '\0';
903 (**sp
).m_string
= NULL
;
904 (**sp
).m_defntn
= NULL
;
905 (**sp
).m_emits
= NULL
;
906 (**sp
).m_errtext
= NULL
;
907 (**sp
).m_next
= NULL
;
912 spec_destroy (spec
** sp
)
915 spec_destroy (&(**sp
).m_next
);
916 emit_destroy (&(**sp
).m_emits
);
917 error_destroy (&(**sp
).m_errtext
);
918 mem_free ((GLvoid
**) & (**sp
).m_string
);
919 mem_free ((GLvoid
**) sp
);
924 spec_append (spec
** sp
, spec
** ns
)
927 spec_append (&(**sp
).m_next
, ns
);
946 typedef struct defntn_
950 struct defntn_
*m_next
;
958 defntn_create (defntn
** de
)
960 *de
= (defntn
*) mem_alloc (sizeof (defntn
));
962 (**de
).m_oper
= op_none
;
963 (**de
).m_specs
= NULL
;
964 (**de
).m_next
= NULL
;
966 (**de
).m_referenced
= 0;
972 defntn_destroy (defntn
** de
)
975 defntn_destroy (&(**de
).m_next
);
976 spec_destroy (&(**de
).m_specs
);
977 mem_free ((GLvoid
**) de
);
982 defntn_append (defntn
** de
, defntn
** nd
)
985 defntn_append (&(**de
).m_next
, nd
);
998 struct dict_
*m_next
;
1003 dict_create (dict
** di
)
1005 *di
= (dict
*) mem_alloc (sizeof (dict
));
1007 (**di
).m_defntns
= NULL
;
1008 (**di
).m_syntax
= NULL
;
1009 (**di
).m_string
= NULL
;
1010 (**di
).m_next
= NULL
;
1015 dict_destroy (dict
** di
)
1018 dict_destroy (&(**di
).m_next
);
1019 defntn_destroy (&(**di
).m_defntns
);
1020 mem_free ((GLvoid
**) di
);
1025 * GLubyte array typedef
1027 typedef struct barray_
1035 barray_create (barray
** ba
)
1037 *ba
= (barray
*) mem_alloc (sizeof (barray
));
1045 barray_destroy (barray
** ba
)
1048 mem_free ((GLvoid
**) & (**ba
).data
);
1049 mem_free ((GLvoid
**) ba
);
1054 * reallocates GLubyte array to requested size,
1055 * returns 0 on success,
1056 * returns 1 otherwise
1059 barray_resize (barray
** ba
, GLuint nlen
)
1061 GLubyte
*new_pointer
;
1064 mem_free ((void **) &(**ba
).data
);
1071 new_pointer
= (GLubyte
*)
1072 mem_realloc ((**ba
).data
, (**ba
).len
* sizeof (GLubyte
),
1073 nlen
* sizeof (GLubyte
));
1075 (**ba
).data
= new_pointer
;
1086 * adds GLubyte array pointed by *nb to the end of array pointed by *ba,
1087 * returns 0 on success,
1088 * returns 1 otherwise
1091 barray_append (barray
** ba
, barray
** nb
)
1094 const GLuint len
= (**ba
).len
;
1096 if (barray_resize (ba
, (**ba
).len
+ (**nb
).len
))
1099 for (i
= 0; i
< (**nb
).len
; i
++)
1100 (**ba
).data
[len
+ i
] = (**nb
).data
[i
];
1107 * Adds emit chain pointed by em to the end of array pointed by *ba.
1108 * \return 0 on success, 1 otherwise.
1111 barray_push (barray
** ba
, emit
* em
, GLubyte c
, GLuint pos
)
1117 if (temp
->m_emit_type
== et_position
)
1118 count
+= 4; /* position is a 32-bit unsigned integer */
1122 temp
= temp
->m_next
;
1125 if (barray_resize (ba
, (**ba
).len
+ count
))
1129 if (em
->m_emit_type
== et_byte
)
1130 (**ba
).data
[(**ba
).len
- count
--] = em
->m_byte
;
1131 else if (em
->m_emit_type
== et_stream
)
1132 (**ba
).data
[(**ba
).len
- count
--] = c
;
1134 /* This is where the position is emitted into the stream */
1135 else { /* em->type == et_position */
1137 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
,
1138 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 8),
1139 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 16),
1140 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
>> 24);
1142 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) pos
;
1143 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x100);
1144 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x10000);
1145 (**ba
).data
[(**ba
).len
- count
--] = (GLubyte
) (pos
/ 0x1000000);
1156 * string to string map typedef
1158 typedef struct map_str_
1162 struct map_str_
*next
;
1167 map_str_create (map_str
** ma
)
1169 *ma
= (map_str
*) mem_alloc (sizeof (map_str
));
1178 map_str_destroy (map_str
** ma
)
1181 map_str_destroy (&(**ma
).next
);
1182 mem_free ((GLvoid
**) & (**ma
).key
);
1183 mem_free ((GLvoid
**) & (**ma
).data
);
1184 mem_free ((GLvoid
**) ma
);
1189 map_str_append (map_str
** ma
, map_str
** nm
)
1192 map_str_append (&(**ma
).next
, nm
);
1198 * searches the map for specified key,
1199 * if the key is matched, *data is filled with data associated with the key,
1200 * \return 0 if the key is matched, 1 otherwise
1203 map_str_find (map_str
** ma
, const GLubyte
* key
, GLubyte
** data
)
1206 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1207 *data
= str_duplicate ((**ma
).data
);
1217 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1222 * string to GLubyte map typedef
1224 typedef struct map_byte_
1228 struct map_byte_
*next
;
1232 map_byte_create (map_byte
** ma
)
1234 *ma
= (map_byte
*) mem_alloc (sizeof (map_byte
));
1243 map_byte_destroy (map_byte
** ma
)
1246 map_byte_destroy (&(**ma
).next
);
1247 mem_free ((GLvoid
**) & (**ma
).key
);
1248 mem_free ((GLvoid
**) ma
);
1253 map_byte_append (map_byte
** ma
, map_byte
** nm
)
1256 map_byte_append (&(**ma
).next
, nm
);
1262 * Searches the map for specified key,
1263 * If the key is matched, *data is filled with data associated with the key,
1264 * \return 0 if the is matched, 1 otherwise
1267 map_byte_find (map_byte
** ma
, const GLubyte
* key
, GLubyte
* data
)
1270 if (strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1271 *data
= (**ma
).data
;
1278 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1283 * string to defntn map typedef
1285 typedef struct map_def_
1289 struct map_def_
*next
;
1293 map_def_create (map_def
** ma
)
1295 *ma
= (map_def
*) mem_alloc (sizeof (map_def
));
1304 map_def_destroy (map_def
** ma
)
1307 map_def_destroy (&(**ma
).next
);
1308 mem_free ((GLvoid
**) & (**ma
).key
);
1309 mem_free ((GLvoid
**) ma
);
1314 map_def_append (map_def
** ma
, map_def
** nm
)
1317 map_def_append (&(**ma
).next
, nm
);
1323 * searches the map for specified key,
1324 * if the key is matched, *data is filled with data associated with the key,
1325 * \return 0 if the is matched, 1 otherwise
1328 map_def_find (map_def
** ma
, const GLubyte
* key
, defntn
** data
)
1331 if (_mesa_strcmp ((const char *) (**ma
).key
, (const char *) key
) == 0) {
1332 *data
= (**ma
).data
;
1340 set_last_error (UNRESOLVED_REFERENCE
, str_duplicate (key
), -1);
1345 * returns 1 if given character is a space,
1346 * returns 0 otherwise
1349 is_space (GLubyte c
)
1351 return c
== ' ' || c
== '\t' || c
== '\n' || c
== '\r';
1355 * advances text pointer by 1 if character pointed by *text is a space,
1356 * returns 1 if a space has been eaten,
1357 * returns 0 otherwise
1360 eat_space (const GLubyte
** text
)
1362 if (is_space (**text
)) {
1372 * returns 1 if text points to C-style comment start string "/ *",
1373 * returns 0 otherwise
1376 is_comment_start (const GLubyte
* text
)
1378 return text
[0] == '/' && text
[1] == '*';
1382 * advances text pointer to first character after C-style comment block - if any,
1383 * returns 1 if C-style comment block has been encountered and eaten,
1384 * returns 0 otherwise
1387 eat_comment (const GLubyte
** text
)
1389 if (is_comment_start (*text
)) {
1390 /* *text points to comment block - skip two characters to enter comment body */
1392 /* skip any character except consecutive '*' and '/' */
1393 while (!((*text
)[0] == '*' && (*text
)[1] == '/'))
1395 /* skip those two terminating characters */
1405 * advances text pointer to first character that is neither space nor C-style comment block
1408 eat_spaces (const GLubyte
** text
)
1410 while (eat_space (text
) || eat_comment (text
));
1414 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1415 * returns 0 on success,
1416 * returns 1 otherwise
1419 string_grow (GLubyte
** ptr
, GLuint
* len
, GLubyte c
)
1421 /* reallocate the string in 16-length increments */
1422 if ((*len
& 0x0F) == 0x0F || *ptr
== NULL
) {
1423 GLubyte
*tmp
= (GLubyte
*) mem_realloc (*ptr
, (*len
) * sizeof (GLubyte
),
1425 0x0F) & ~0x0F) * sizeof (GLubyte
));
1433 /* append given character */
1437 (*ptr
)[*len
] = '\0';
1443 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1444 * returns 0 otherwise
1447 is_identifier (GLubyte c
)
1449 return (c
>= 'a' && c
<= 'z') || (c
>= 'A' && c
<= 'Z') ||
1450 (c
>= '0' && c
<= '9') || c
== '_';
1454 * copies characters from *text to *id until non-identifier character is encountered,
1455 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1456 * text pointer is advanced to point past the copied identifier,
1457 * returns 0 if identifier was successfully copied,
1458 * returns 1 otherwise
1461 get_identifier (const GLubyte
** text
, GLubyte
** id
)
1463 const GLubyte
*t
= *text
;
1467 if (string_grow (&p
, &len
, '\0'))
1470 /* loop while next character in buffer is valid for identifiers */
1471 while (is_identifier (*t
)) {
1472 if (string_grow (&p
, &len
, *t
++)) {
1473 mem_free ((GLvoid
**) & p
);
1485 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1486 * returns 0 otherwise
1491 return (c
>= '0' && c
<= '9') || (c
>= 'A' && c
<= 'F') || (c
>= 'a'
1496 * returns value of passed character as if it was HEX digit
1501 if (c
>= '0' && c
<= '9')
1503 if (c
>= 'A' && c
<= 'F')
1504 return c
- 'A' + 10;
1505 return c
- 'a' + 10;
1509 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1510 * advances text pointer past the converted sequence,
1511 * returns the converted value
1514 hex_convert (const GLubyte
** text
)
1518 while (is_hex (**text
)) {
1519 value
= value
* 0x10 + hex2dec (**text
);
1527 * returns 1 if given character is OCT digit 0-7,
1528 * returns 0 otherwise
1533 return c
>= '0' && c
<= '7';
1537 * returns value of passed character as if it was OCT digit
1546 get_escape_sequence (const GLubyte
** text
)
1550 /* skip '\' character */
1553 switch (*(*text
)++) {
1577 return (GLubyte
) hex_convert (text
);
1581 if (is_oct (**text
)) {
1582 value
= oct2dec (*(*text
)++);
1583 if (is_oct (**text
)) {
1584 value
= value
* 010 + oct2dec (*(*text
)++);
1585 if (is_oct (**text
))
1586 value
= value
* 010 + oct2dec (*(*text
)++);
1590 return (GLubyte
) value
;
1594 * copies characters from *text to *str until " or ' character is encountered,
1595 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1596 * assumes that *text points to " or ' character that starts the string,
1597 * text pointer is advanced to point past the " or ' character,
1598 * returns 0 if string was successfully copied,
1599 * returns 1 otherwise
1602 get_string (const GLubyte
** text
, GLubyte
** str
)
1604 const GLubyte
*t
= *text
;
1609 if (string_grow (&p
, &len
, '\0'))
1612 /* read " or ' character that starts the string */
1614 /* while next character is not the terminating character */
1615 while (*t
&& *t
!= term_char
) {
1619 c
= get_escape_sequence (&t
);
1623 if (string_grow (&p
, &len
, c
)) {
1624 mem_free ((GLvoid
**) & p
);
1629 /* skip " or ' character that ends the string */
1638 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1639 * assumes that *text already points to <symbol>,
1640 * returns 0 if emit code is successfully read,
1641 * returns 1 otherwise
1644 get_emtcode (const GLubyte
** text
, map_byte
** ma
)
1646 const GLubyte
*t
= *text
;
1649 map_byte_create (&m
);
1653 if (get_identifier (&t
, &m
->key
)) {
1654 map_byte_destroy (&m
);
1662 if (get_string (&t
, &c
)) {
1663 map_byte_destroy (&m
);
1667 m
->data
= (GLubyte
) c
[0];
1668 mem_free ((GLvoid
**) & c
);
1671 /* skip HEX "0x" or "0X" prefix */
1673 m
->data
= (GLubyte
) hex_convert (&t
);
1684 * returns 0 on success,
1685 * returns 1 otherwise
1688 get_errtext (const GLubyte
** text
, map_str
** ma
)
1690 const GLubyte
*t
= *text
;
1693 map_str_create (&m
);
1697 if (get_identifier (&t
, &m
->key
)) {
1698 map_str_destroy (&m
);
1703 if (get_string (&t
, &m
->data
)) {
1704 map_str_destroy (&m
);
1715 * returns 0 on success,
1716 * returns 1 otherwise,
1719 get_error (const GLubyte
** text
, error
** er
, map_str
* maps
)
1721 const GLubyte
*t
= *text
;
1722 GLubyte
*temp
= NULL
;
1728 if (get_identifier (&t
, &temp
))
1732 if (_mesa_strcmp ("error", (char *) temp
) != 0) {
1733 mem_free ((GLvoid
**) & temp
);
1737 mem_free ((GLvoid
**) & temp
);
1744 if (get_string (&t
, &(**er
).m_text
)) {
1751 if (get_identifier (&t
, &temp
)) {
1757 if (map_str_find (&maps
, temp
, &(**er
).m_text
)) {
1758 mem_free ((GLvoid
**) & temp
);
1763 mem_free ((GLvoid
**) & temp
);
1766 /* try to extract "token" from "...$token$..." */
1768 char *processed
= NULL
;
1769 GLuint len
= 0, i
= 0;
1771 if (string_grow ((GLubyte
**) (&processed
), &len
, '\0')) {
1776 while (i
< _mesa_strlen ((char *) ((**er
).m_text
))) {
1777 /* check if the dollar sign is repeated - if so skip it */
1778 if ((**er
).m_text
[i
] == '$' && (**er
).m_text
[i
+ 1] == '$') {
1779 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1780 mem_free ((GLvoid
**) & processed
);
1787 else if ((**er
).m_text
[i
] != '$') {
1788 if (string_grow ((GLubyte
**) (&processed
), &len
, (**er
).m_text
[i
])) {
1789 mem_free ((GLvoid
**) & processed
);
1797 if (string_grow ((GLubyte
**) (&processed
), &len
, '$')) {
1798 mem_free ((GLvoid
**) & processed
);
1804 /* length of token being extracted */
1807 if (string_grow (&(**er
).m_token_name
, &tlen
, '\0')) {
1808 mem_free ((GLvoid
**) & processed
);
1813 /* skip the dollar sign */
1816 while ((**er
).m_text
[i
] != '$') {
1818 (&(**er
).m_token_name
, &tlen
, (**er
).m_text
[i
])) {
1819 mem_free ((GLvoid
**) & processed
);
1827 /* skip the dollar sign */
1833 mem_free ((GLvoid
**) & (**er
).m_text
);
1834 (**er
).m_text
= (GLubyte
*) processed
;
1842 * returns 0 on success,
1843 * returns 1 otherwise,
1846 get_emits (const GLubyte
** text
, emit
** em
, map_byte
* mapb
)
1848 const GLubyte
*t
= *text
;
1849 GLubyte
*temp
= NULL
;
1856 if (get_identifier (&t
, &temp
))
1861 if (_mesa_strcmp ("emit", (char *) temp
) != 0) {
1862 mem_free ((GLvoid
**) & temp
);
1866 mem_free ((GLvoid
**) & temp
);
1875 e
->m_byte
= (GLubyte
) hex_convert (&t
);
1877 e
->m_emit_type
= et_byte
;
1880 else if (*t
== '*') {
1883 e
->m_emit_type
= et_stream
;
1886 else if (*t
== '$') {
1889 e
->m_emit_type
= et_position
;
1892 else if (*t
== '\'') {
1893 if (get_string (&t
, &temp
)) {
1897 e
->m_byte
= (GLubyte
) temp
[0];
1899 mem_free ((GLvoid
**) & temp
);
1901 e
->m_emit_type
= et_byte
;
1904 if (get_identifier (&t
, &temp
)) {
1909 if (map_byte_find (&mapb
, temp
, &e
->m_byte
)) {
1910 mem_free ((GLvoid
**) & temp
);
1915 mem_free ((GLvoid
**) & temp
);
1917 e
->m_emit_type
= et_byte
;
1922 if (get_emits (&t
, &e
->m_next
, mapb
)) {
1933 * returns 0 on success,
1934 * returns 1 otherwise,
1937 get_spec (const GLubyte
** text
, spec
** sp
, map_str
* maps
, map_byte
* mapb
)
1939 const GLubyte
*t
= *text
;
1947 GLubyte
*temp
= NULL
;
1949 if (get_string (&t
, &temp
)) {
1956 GLubyte
*temp2
= NULL
;
1958 /* skip the '-' character */
1962 if (get_string (&t
, &temp2
)) {
1963 mem_free ((GLvoid
**) & temp
);
1969 s
->m_spec_type
= st_byte_range
;
1970 s
->m_byte
[0] = *temp
;
1971 s
->m_byte
[1] = *temp2
;
1973 mem_free ((GLvoid
**) & temp2
);
1976 s
->m_spec_type
= st_byte
;
1980 mem_free ((GLvoid
**) & temp
);
1982 else if (*t
== '"') {
1983 if (get_string (&t
, &s
->m_string
)) {
1989 s
->m_spec_type
= st_string
;
1991 else if (*t
== '.') {
1992 GLubyte
*keyword
= NULL
;
1997 if (get_identifier (&t
, &keyword
)) {
2004 if (_mesa_strcmp ("true", (char *) keyword
) == 0) {
2005 s
->m_spec_type
= st_true
;
2008 else if (_mesa_strcmp ("false", (char *) keyword
) == 0) {
2009 s
->m_spec_type
= st_false
;
2012 else if (_mesa_strcmp ("debug", (char *) keyword
) == 0) {
2013 s
->m_spec_type
= st_debug
;
2016 else if (_mesa_strcmp ("loop", (char *) keyword
) == 0) {
2017 if (get_identifier (&t
, &s
->m_string
)) {
2018 mem_free ((GLvoid
**) & keyword
);
2024 s
->m_spec_type
= st_identifier_loop
;
2027 mem_free ((GLvoid
**) & keyword
);
2030 if (get_identifier (&t
, &s
->m_string
)) {
2036 s
->m_spec_type
= st_identifier
;
2039 if (get_error (&t
, &s
->m_errtext
, maps
)) {
2044 if (get_emits (&t
, &s
->m_emits
, mapb
)) {
2055 * returns 0 on success,
2056 * returns 1 otherwise,
2059 get_definition (const GLubyte
** text
, defntn
** de
, map_str
* maps
,
2062 const GLubyte
*t
= *text
;
2069 if (get_spec (&t
, &d
->m_specs
, maps
, mapb
)) {
2070 defntn_destroy (&d
);
2078 /* skip the dot that precedes "and" or "or" */
2081 /* read "and" or "or" keyword */
2082 if (get_identifier (&t
, &op
)) {
2083 defntn_destroy (&d
);
2088 if (d
->m_oper
== op_none
) {
2090 if (_mesa_strcmp ("and", (char *) op
) == 0)
2097 mem_free ((GLvoid
**) & op
);
2099 if (get_spec (&t
, &sp
, maps
, mapb
)) {
2100 defntn_destroy (&d
);
2104 spec_append (&d
->m_specs
, &sp
);
2107 /* skip the semicolon */
2117 * returns 0 on success,
2118 * returns 1 otherwise,
2121 update_dependency (map_def
* mapd
, GLubyte
* symbol
, defntn
** def
)
2123 if (map_def_find (&mapd
, symbol
, def
))
2127 (**def
).m_referenced
= 1;
2134 * returns 0 on success,
2135 * returns 1 otherwise,
2138 update_dependencies (dict
* di
, map_def
* mapd
, GLubyte
** syntax_symbol
,
2139 GLubyte
** string_symbol
)
2141 defntn
*de
= di
->m_defntns
;
2143 if (update_dependency (mapd
, *syntax_symbol
, &di
->m_syntax
) ||
2144 (*string_symbol
!= NULL
2145 && update_dependency (mapd
, *string_symbol
, &di
->m_string
)))
2148 mem_free ((GLvoid
**) syntax_symbol
);
2149 mem_free ((GLvoid
**) string_symbol
);
2152 spec
*sp
= de
->m_specs
;
2155 if (sp
->m_spec_type
== st_identifier
2156 || sp
->m_spec_type
== st_identifier_loop
) {
2157 if (update_dependency (mapd
, sp
->m_string
, &sp
->m_defntn
))
2160 mem_free ((GLvoid
**) & sp
->m_string
);
2163 if (sp
->m_errtext
&& sp
->m_errtext
->m_token_name
) {
2164 if (update_dependency
2165 (mapd
, sp
->m_errtext
->m_token_name
, &sp
->m_errtext
->m_token
))
2168 mem_free ((GLvoid
**) & sp
->m_errtext
->m_token_name
);
2180 typedef enum match_result_
2182 mr_not_matched
, /* the examined string does not match */
2183 mr_matched
, /* the examined string matches */
2184 mr_error_raised
, /* mr_not_matched + error has been raised */
2185 mr_dont_emit
, /* used by identifier loops only */
2186 mr_internal_error
/* an internal error has occured such as out of memory */
2190 match (dict
* di
, const GLubyte
* text
, GLuint
* index
, defntn
* de
,
2191 barray
** ba
, GLint filtering_string
)
2193 GLuint ind
= *index
;
2194 match_result status
= mr_not_matched
;
2195 spec
*sp
= de
->m_specs
;
2197 /* for every specifier in the definition */
2199 GLuint i
, len
, save_ind
= ind
;
2200 barray
*array
= NULL
;
2202 switch (sp
->m_spec_type
) {
2204 barray_create (&array
);
2206 return mr_internal_error
;
2209 match (di
, text
, &ind
, sp
->m_defntn
, &array
, filtering_string
);
2210 if (status
== mr_internal_error
) {
2211 barray_destroy (&array
);
2212 return mr_internal_error
;
2216 len
= _mesa_strlen ((char *) (sp
->m_string
));
2218 /* prefilter the stream */
2219 if (!filtering_string
&& di
->m_string
) {
2221 GLuint filter_index
= 0;
2222 match_result result
;
2224 barray_create (&ba
);
2226 return mr_internal_error
;
2229 match (di
, text
+ ind
, &filter_index
, di
->m_string
, &ba
, 1);
2231 if (result
== mr_internal_error
) {
2232 barray_destroy (&ba
);
2233 return mr_internal_error
;
2236 if (result
!= mr_matched
) {
2237 barray_destroy (&ba
);
2238 status
= mr_not_matched
;
2242 barray_destroy (&ba
);
2244 if (filter_index
!= len
2245 || _mesa_strncmp ((char *)sp
->m_string
, (char *)(text
+ ind
), len
)) {
2246 status
= mr_not_matched
;
2250 status
= mr_matched
;
2254 status
= mr_matched
;
2255 for (i
= 0; status
== mr_matched
&& i
< len
; i
++)
2256 if (text
[ind
+ i
] != sp
->m_string
[i
])
2257 status
= mr_not_matched
;
2258 if (status
== mr_matched
)
2263 status
= text
[ind
] == *sp
->m_byte
? mr_matched
: mr_not_matched
;
2264 if (status
== mr_matched
)
2268 status
= (text
[ind
] >= sp
->m_byte
[0]
2270 sp
->m_byte
[1]) ? mr_matched
: mr_not_matched
;
2271 if (status
== mr_matched
)
2275 status
= mr_matched
;
2278 status
= mr_not_matched
;
2281 status
= mr_matched
;
2283 case st_identifier_loop
:
2284 barray_create (&array
);
2286 return mr_internal_error
;
2288 status
= mr_dont_emit
;
2290 match_result result
;
2294 match (di
, text
, &ind
, sp
->m_defntn
, &array
,
2297 if (result
== mr_error_raised
) {
2301 else if (result
== mr_matched
) {
2302 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)
2303 || barray_append (ba
, &array
)) {
2304 barray_destroy (&array
);
2305 return mr_internal_error
;
2307 barray_destroy (&array
);
2308 barray_create (&array
);
2310 return mr_internal_error
;
2312 else if (result
== mr_internal_error
) {
2313 barray_destroy (&array
);
2314 return mr_internal_error
;
2322 if (status
== mr_error_raised
) {
2323 barray_destroy (&array
);
2325 return mr_error_raised
;
2328 if (de
->m_oper
== op_and
&& status
!= mr_matched
2329 && status
!= mr_dont_emit
) {
2330 barray_destroy (&array
);
2332 if (sp
->m_errtext
) {
2333 set_last_error (sp
->m_errtext
->m_text
,
2334 error_get_token (sp
->m_errtext
, di
, text
, ind
),
2337 return mr_error_raised
;
2340 return mr_not_matched
;
2343 if (status
== mr_matched
) {
2345 if (barray_push (ba
, sp
->m_emits
, text
[ind
- 1], save_ind
)) {
2346 barray_destroy (&array
);
2347 return mr_internal_error
;
2351 if (barray_append (ba
, &array
)) {
2352 barray_destroy (&array
);
2353 return mr_internal_error
;
2357 barray_destroy (&array
);
2359 if (de
->m_oper
== op_or
2360 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2368 if (de
->m_oper
== op_and
2369 && (status
== mr_matched
|| status
== mr_dont_emit
)) {
2374 return mr_not_matched
;
2378 error_get_token (error
* er
, dict
* di
, const GLubyte
* text
, unsigned int ind
)
2380 GLubyte
*str
= NULL
;
2384 GLuint filter_index
= 0;
2386 barray_create (&ba
);
2388 if (match (di
, text
+ ind
, &filter_index
, er
->m_token
, &ba
, 0) ==
2389 mr_matched
&& filter_index
) {
2390 str
= (GLubyte
*) mem_alloc (filter_index
+ 1);
2392 _mesa_strncpy ((char *) str
, (char *) (text
+ ind
),
2394 str
[filter_index
] = '\0';
2397 barray_destroy (&ba
);
2404 typedef struct grammar_load_state_
2407 GLubyte
*syntax_symbol
;
2408 GLubyte
*string_symbol
;
2412 } grammar_load_state
;
2416 grammar_load_state_create (grammar_load_state
** gr
)
2418 *gr
= (grammar_load_state
*) mem_alloc (sizeof (grammar_load_state
));
2421 (**gr
).syntax_symbol
= NULL
;
2422 (**gr
).string_symbol
= NULL
;
2430 grammar_load_state_destroy (grammar_load_state
** gr
)
2433 dict_destroy (&(**gr
).di
);
2434 mem_free ((GLvoid
**) &(**gr
).syntax_symbol
);
2435 mem_free ((GLvoid
**) &(**gr
).string_symbol
);
2436 map_str_destroy (&(**gr
).maps
);
2437 map_byte_destroy (&(**gr
).mapb
);
2438 map_def_destroy (&(**gr
).mapd
);
2439 mem_free ((GLvoid
**) gr
);
2448 * loads grammar script from null-terminated ASCII text
2449 * returns the grammar object
2450 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2454 grammar_load_from_text (const GLubyte
* text
)
2457 grammar_load_state
*g
= NULL
;
2459 clear_last_error ();
2461 grammar_load_state_create (&g
);
2465 dict_create (&g
->di
);
2466 if (g
->di
== NULL
) {
2467 grammar_load_state_destroy (&g
);
2473 /* skip ".syntax" keyword */
2477 /* retrieve root symbol */
2478 if (get_identifier (&text
, &g
->syntax_symbol
)) {
2479 grammar_load_state_destroy (&g
);
2484 /* skip semicolon */
2489 GLubyte
*symbol
= NULL
;
2490 GLint is_dot
= *text
== '.';
2495 if (get_identifier (&text
, &symbol
)) {
2496 grammar_load_state_destroy (&g
);
2502 if (is_dot
&& _mesa_strcmp ((char *) symbol
, "emtcode") == 0) {
2503 map_byte
*ma
= NULL
;
2505 mem_free ((void **) &symbol
);
2507 if (get_emtcode (&text
, &ma
)) {
2508 grammar_load_state_destroy (&g
);
2512 map_byte_append (&g
->mapb
, &ma
);
2515 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "errtext") == 0) {
2518 mem_free ((GLvoid
**) &symbol
);
2520 if (get_errtext (&text
, &ma
)) {
2521 grammar_load_state_destroy (&g
);
2525 map_str_append (&g
->maps
, &ma
);
2528 else if (is_dot
&& _mesa_strcmp ((char *) symbol
, "string") == 0) {
2529 mem_free ((GLvoid
**) (&symbol
));
2531 if (g
->di
->m_string
!= NULL
) {
2532 grammar_load_state_destroy (&g
);
2536 if (get_identifier (&text
, &g
->string_symbol
)) {
2537 grammar_load_state_destroy (&g
);
2541 /* skip semicolon */
2550 if (get_definition (&text
, &de
, g
->maps
, g
->mapb
)) {
2551 grammar_load_state_destroy (&g
);
2555 defntn_append (&g
->di
->m_defntns
, &de
);
2557 /* if definition consist of only one specifier, give it an ".and" operator */
2558 if (de
->m_oper
== op_none
)
2559 de
->m_oper
= op_and
;
2561 map_def_create (&ma
);
2563 grammar_load_state_destroy (&g
);
2569 map_def_append (&g
->mapd
, &ma
);
2573 if (update_dependencies
2574 (g
->di
, g
->mapd
, &g
->syntax_symbol
, &g
->string_symbol
)) {
2575 grammar_load_state_destroy (&g
);
2582 grammar_load_state_destroy (&g
);
2588 * checks if a null-terminated text matches given grammar
2589 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2590 * returns 1 on success, the prod points to newly allocated buffer with
2591 * production and size is filled with the production size
2593 * \param id - The grammar returned from grammar_load_from_text()
2594 * \param text - The program string
2595 * \param production - The return parameter for the binary array holding the
2597 * \param size - The return parameter for the size of production
2599 * \return 1 on sucess, 0 on parser error
2602 grammar_check (dict
* di
, const GLubyte
* text
, GLubyte
** production
,
2608 clear_last_error ();
2610 barray_create (&ba
);
2617 if (match (di
, text
, &index
, di
->m_syntax
, &ba
, 0) != mr_matched
) {
2618 barray_destroy (&ba
);
2622 *production
= (GLubyte
*) mem_alloc (ba
->len
* sizeof (GLubyte
));
2623 if (*production
== NULL
) {
2624 barray_destroy (&ba
);
2628 memcpy (*production
, ba
->data
, ba
->len
* sizeof (GLubyte
));
2630 barray_destroy (&ba
);
2636 grammar_get_last_error (GLubyte
* text
, GLint size
, GLint
*pos
)
2638 GLint len
= 0, dots_made
= 0;
2639 const GLubyte
*p
= error_message
;
2642 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2643 if (len < size - 1) {\
2644 text[len++] = (x); text[len] = '\0';\
2647 for (i = 0; i < 3; i++)\
2657 const GLubyte
*r
= error_param
;
2660 APPEND_CHARACTER (*r
)
2667 APPEND_CHARACTER (*p
)
2672 *pos
= error_position
;
2675 /*-----------------------------------------------------------------------
2676 * From here on down is the semantic checking portion
2681 * Variable Table Handling functions
2696 * Setting an explicit field for each of the binding properties is a bit wasteful
2697 * of space, but it should be much more clear when reading later on..
2703 GLuint address_binding
; /* The index of the address register we should
2705 GLuint attrib_binding
; /* For type vt_attrib, see nvfragprog.h for values */
2706 GLuint attrib_binding_idx
; /* The index into the attrib register file corresponding
2707 * to the state in attrib_binding */
2708 GLuint attrib_is_generic
; /* If the attrib was specified through a generic
2710 GLuint temp_binding
; /* The index of the temp register we are to use */
2711 GLuint output_binding
; /* For type vt_output, see nvfragprog.h for values */
2712 GLuint output_binding_idx
; /* This is the index into the result register file
2713 * corresponding to the bound result state */
2714 struct var_cache
*alias_binding
; /* For type vt_alias, points to the var_cache entry
2715 * that this is aliased to */
2716 GLuint param_binding_type
; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2717 * PROGRAM_ENV_PARAM} */
2718 GLuint param_binding_begin
; /* This is the offset into the program_parameter_list where
2719 * the tokens representing our bound state (or constants)
2721 GLuint param_binding_length
; /* This is how many entries in the the program_parameter_list
2722 * we take up with our state tokens or constants. Note that
2723 * this is _not_ the same as the number of param registers
2724 * we eventually use */
2725 struct var_cache
*next
;
2729 var_cache_create (struct var_cache
**va
)
2731 *va
= (struct var_cache
*) _mesa_malloc (sizeof (struct var_cache
));
2734 (**va
).type
= vt_none
;
2735 (**va
).attrib_binding
= ~0;
2736 (**va
).attrib_is_generic
= 0;
2737 (**va
).temp_binding
= ~0;
2738 (**va
).output_binding
= ~0;
2739 (**va
).output_binding_idx
= ~0;
2740 (**va
).param_binding_type
= ~0;
2741 (**va
).param_binding_begin
= ~0;
2742 (**va
).param_binding_length
= ~0;
2743 (**va
).alias_binding
= NULL
;
2749 var_cache_destroy (struct var_cache
**va
)
2752 var_cache_destroy (&(**va
).next
);
2759 var_cache_append (struct var_cache
**va
, struct var_cache
*nv
)
2762 var_cache_append (&(**va
).next
, nv
);
2767 static struct var_cache
*
2768 var_cache_find (struct var_cache
*va
, GLubyte
* name
)
2770 struct var_cache
*first
= va
;
2773 if (!strcmp ( (const char*) name
, (const char*) va
->name
)) {
2774 if (va
->type
== vt_alias
)
2775 return var_cache_find (first
, va
->name
);
2786 * constructs an integer from 4 GLubytes in LE format
2789 parse_position (GLubyte
** inst
)
2793 value
= (GLuint
) (*(*inst
)++);
2794 value
+= (GLuint
) (*(*inst
)++) * 0x100;
2795 value
+= (GLuint
) (*(*inst
)++) * 0x10000;
2796 value
+= (GLuint
) (*(*inst
)++) * 0x1000000;
2802 * This will, given a string, lookup the string as a variable name in the
2803 * var cache. If the name is found, the var cache node corresponding to the
2804 * var name is returned. If it is not found, a new entry is allocated
2806 * \param I Points into the binary array where the string identifier begins
2807 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2808 * \return The location on the var_cache corresponding the the string starting at I
2810 static struct var_cache
*
2811 parse_string (GLubyte
** inst
, struct var_cache
**vc_head
,
2812 struct arb_program
*Program
, GLuint
* found
)
2815 struct var_cache
*va
= NULL
;
2817 *inst
+= _mesa_strlen ((char *) i
) + 1;
2819 va
= var_cache_find (*vc_head
, i
);
2827 var_cache_create (&va
);
2830 var_cache_append (vc_head
, va
);
2836 parse_string_without_adding (GLubyte
** inst
, struct arb_program
*Program
)
2840 *inst
+= _mesa_strlen ((char *) i
) + 1;
2846 * \return 0 if sign is plus, 1 if sign is minus
2849 parse_sign (GLubyte
** inst
)
2851 /*return *(*inst)++ != '+'; */
2853 if (**inst
== '-') {
2857 else if (**inst
== '+') {
2866 * parses and returns signed integer
2869 parse_integer (GLubyte
** inst
, struct arb_program
*Program
)
2874 /* check if *inst points to '+' or '-'
2875 * if yes, grab the sign and increment *inst
2877 sign
= parse_sign (inst
);
2879 /* now check if *inst points to 0
2880 * if yes, increment the *inst and return the default value
2887 /* parse the integer as you normally would do it */
2888 value
= _mesa_atoi (parse_string_without_adding (inst
, Program
));
2890 /* now, after terminating 0 there is a position
2891 * to parse it - parse_position()
2893 Program
->Position
= parse_position (inst
);
2904 parse_float (GLubyte
** inst
, struct arb_program
*Program
)
2906 GLint tmp
[5], denom
;
2907 GLuint leading_zeros
=0;
2911 tmp
[0] = parse_sign (inst
); /* This is the sign of the number + - >0, - -> 1 */
2913 tmp
[1] = parse_integer (inst
, Program
); /* This is the integer portion of the number */
2915 /* Now we grab the fractional portion of the number (the digits after
2916 * the .). We can have leading 0's here, which parse_integer will ignore,
2917 * so we'll check for those first
2919 while ((**inst
== '0') && ( *(*inst
+1) != 0))
2924 tmp
[2] = parse_integer (inst
, Program
); /* This is the fractional portion of the number */
2925 tmp
[3] = parse_sign (inst
); /* This is the sign of the exponent */
2926 tmp
[4] = parse_integer (inst
, Program
); /* This is the exponent */
2928 value
= (GLfloat
) tmp
[1];
2930 while (denom
< tmp
[2])
2932 denom
*= _mesa_pow( 10, leading_zeros
);
2933 value
+= (GLfloat
) tmp
[2] / (GLfloat
) denom
;
2938 value
*= _mesa_pow (10, (GLfloat
) tmp
[3] * (GLfloat
) tmp
[4]);
2947 parse_signed_float (GLubyte
** inst
, struct arb_program
*Program
)
2952 negate
= parse_sign (inst
);
2954 value
= parse_float (inst
, Program
);
2963 * This picks out a constant value from the parsed array. The constant vector is r
2964 * returned in the *values array, which should be of length 4.
2966 * \param values - The 4 component vector with the constant value in it
2969 parse_constant (GLubyte
** inst
, GLfloat
*values
, struct arb_program
*Program
,
2972 GLuint components
, i
;
2975 switch (*(*inst
)++) {
2976 case CONSTANT_SCALAR
:
2977 if (use
== GL_TRUE
) {
2980 values
[2] = values
[3] = parse_float (inst
, Program
);
2985 values
[2] = values
[3] = parse_signed_float (inst
, Program
);
2989 case CONSTANT_VECTOR
:
2990 values
[0] = values
[1] = values
[2] = 0;
2992 components
= *(*inst
)++;
2993 for (i
= 0; i
< components
; i
++) {
2994 values
[i
] = parse_signed_float (inst
, Program
);
3001 * \param offset The offset from the address register that we should
3004 * \return 0 on sucess, 1 on error
3007 parse_relative_offset (GLcontext
*ctx
, GLubyte
**inst
, struct arb_program
*Program
,
3010 *offset
= parse_integer(inst
, Program
);
3011 if ((*offset
> 63) || (*offset
< -64)) {
3012 _mesa_set_program_error (ctx
, Program
->Position
,
3013 "Relative offset out of range");
3014 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Relative offset %d out of range",
3023 * \param color 0 if color type is primary, 1 if color type is secondary
3024 * \return 0 on sucess, 1 on error
3027 parse_color_type (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3030 *color
= *(*inst
)++ != COLOR_PRIMARY
;
3035 * Get an integer corresponding to a generic vertex attribute.
3037 * \return 0 on sucess, 1 on error
3040 parse_generic_attrib_num(GLcontext
*ctx
, GLubyte
** inst
,
3041 struct arb_program
*Program
, GLuint
*attrib
)
3043 *attrib
= parse_integer(inst
, Program
);
3045 if ((*attrib
< 0) || (*attrib
> MAX_VERTEX_PROGRAM_ATTRIBS
))
3047 _mesa_set_program_error (ctx
, Program
->Position
,
3048 "Invalid generic vertex attribute index");
3049 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid generic vertex attribute index");
3059 * \param coord The texture unit index
3060 * \return 0 on sucess, 1 on error
3063 parse_texcoord_num (GLcontext
* ctx
, GLubyte
** inst
,
3064 struct arb_program
*Program
, GLuint
* coord
)
3066 *coord
= parse_integer (inst
, Program
);
3068 if ((*coord
< 0) || (*coord
>= ctx
->Const
.MaxTextureUnits
)) {
3069 _mesa_set_program_error (ctx
, Program
->Position
,
3070 "Invalid texture unit index");
3071 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid texture unit index");
3079 * \param coord The weight index
3080 * \return 0 on sucess, 1 on error
3083 parse_weight_num (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3086 *coord
= parse_integer (inst
, Program
);
3088 if ((*coord
< 0) || (*coord
>= 1)) {
3089 _mesa_set_program_error (ctx
, Program
->Position
,
3090 "Invalid weight index");
3091 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid weight index");
3099 * \param coord The clip plane index
3100 * \return 0 on sucess, 1 on error
3103 parse_clipplane_num (GLcontext
* ctx
, GLubyte
** inst
,
3104 struct arb_program
*Program
, GLint
* coord
)
3106 *coord
= parse_integer (inst
, Program
);
3108 if ((*coord
< 0) || (*coord
>= (GLint
) ctx
->Const
.MaxClipPlanes
)) {
3109 _mesa_set_program_error (ctx
, Program
->Position
,
3110 "Invalid clip plane index");
3111 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Invalid clip plane index");
3120 * \return 0 on front face, 1 on back face
3123 parse_face_type (GLubyte
** inst
)
3125 switch (*(*inst
)++) {
3137 * Given a matrix and a modifier token on the binary array, return tokens
3138 * that _mesa_fetch_state() [program.c] can understand.
3140 * \param matrix - the matrix we are talking about
3141 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3142 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3143 * \return 0 on sucess, 1 on failure
3146 parse_matrix (GLcontext
* ctx
, GLubyte
** inst
, struct arb_program
*Program
,
3147 GLint
* matrix
, GLint
* matrix_idx
, GLint
* matrix_modifier
)
3149 GLubyte mat
= *(*inst
)++;
3154 case MATRIX_MODELVIEW
:
3155 *matrix
= STATE_MODELVIEW
;
3156 *matrix_idx
= parse_integer (inst
, Program
);
3157 if (*matrix_idx
> 0) {
3158 _mesa_set_program_error (ctx
, Program
->Position
,
3159 "ARB_vertex_blend not supported\n");
3160 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3161 "ARB_vertex_blend not supported\n");
3166 case MATRIX_PROJECTION
:
3167 *matrix
= STATE_PROJECTION
;
3171 *matrix
= STATE_MVP
;
3174 case MATRIX_TEXTURE
:
3175 *matrix
= STATE_TEXTURE
;
3176 *matrix_idx
= parse_integer (inst
, Program
);
3177 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxTextureUnits
) {
3178 _mesa_set_program_error (ctx
, Program
->Position
,
3179 "Invalid Texture Unit");
3180 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3181 "Invalid Texture Unit: %d", *matrix_idx
);
3186 /* This is not currently supported (ARB_matrix_palette) */
3187 case MATRIX_PALETTE
:
3188 *matrix_idx
= parse_integer (inst
, Program
);
3189 _mesa_set_program_error (ctx
, Program
->Position
,
3190 "ARB_matrix_palette not supported\n");
3191 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3192 "ARB_matrix_palette not supported\n");
3196 case MATRIX_PROGRAM
:
3197 *matrix
= STATE_PROGRAM
;
3198 *matrix_idx
= parse_integer (inst
, Program
);
3199 if (*matrix_idx
>= (GLint
) ctx
->Const
.MaxProgramMatrices
) {
3200 _mesa_set_program_error (ctx
, Program
->Position
,
3201 "Invalid Program Matrix");
3202 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3203 "Invalid Program Matrix: %d", *matrix_idx
);
3209 switch (*(*inst
)++) {
3210 case MATRIX_MODIFIER_IDENTITY
:
3211 *matrix_modifier
= 0;
3213 case MATRIX_MODIFIER_INVERSE
:
3214 *matrix_modifier
= STATE_MATRIX_INVERSE
;
3216 case MATRIX_MODIFIER_TRANSPOSE
:
3217 *matrix_modifier
= STATE_MATRIX_TRANSPOSE
;
3219 case MATRIX_MODIFIER_INVTRANS
:
3220 *matrix_modifier
= STATE_MATRIX_INVTRANS
;
3229 * This parses a state string (rather, the binary version of it) into
3230 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3232 * \param inst - the start in the binary arry to start working from
3233 * \param state_tokens - the storage for the 6-token state description
3234 * \return - 0 on sucess, 1 on error
3237 parse_state_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3238 struct arb_program
*Program
, GLint
* state_tokens
)
3240 switch (*(*inst
)++) {
3241 case STATE_MATERIAL_PARSER
:
3242 state_tokens
[0] = STATE_MATERIAL
;
3243 state_tokens
[1] = parse_face_type (inst
);
3244 switch (*(*inst
)++) {
3245 case MATERIAL_AMBIENT
:
3246 state_tokens
[2] = STATE_AMBIENT
;
3248 case MATERIAL_DIFFUSE
:
3249 state_tokens
[2] = STATE_DIFFUSE
;
3251 case MATERIAL_SPECULAR
:
3252 state_tokens
[2] = STATE_SPECULAR
;
3254 case MATERIAL_EMISSION
:
3255 state_tokens
[2] = STATE_EMISSION
;
3257 case MATERIAL_SHININESS
:
3258 state_tokens
[2] = STATE_SHININESS
;
3263 case STATE_LIGHT_PARSER
:
3264 state_tokens
[0] = STATE_LIGHT
;
3265 state_tokens
[1] = parse_integer (inst
, Program
);
3267 /* Check the value of state_tokens[1] against the # of lights */
3268 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3269 _mesa_set_program_error (ctx
, Program
->Position
,
3270 "Invalid Light Number");
3271 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3272 "Invalid Light Number: %d", state_tokens
[1]);
3276 switch (*(*inst
)++) {
3278 state_tokens
[2] = STATE_AMBIENT
;
3281 state_tokens
[2] = STATE_DIFFUSE
;
3283 case LIGHT_SPECULAR
:
3284 state_tokens
[2] = STATE_SPECULAR
;
3286 case LIGHT_POSITION
:
3287 state_tokens
[2] = STATE_POSITION
;
3289 case LIGHT_ATTENUATION
:
3290 state_tokens
[2] = STATE_ATTENUATION
;
3293 state_tokens
[2] = STATE_HALF
;
3295 case LIGHT_SPOT_DIRECTION
:
3296 state_tokens
[2] = STATE_SPOT_DIRECTION
;
3301 case STATE_LIGHT_MODEL
:
3302 switch (*(*inst
)++) {
3303 case LIGHT_MODEL_AMBIENT
:
3304 state_tokens
[0] = STATE_LIGHTMODEL_AMBIENT
;
3306 case LIGHT_MODEL_SCENECOLOR
:
3307 state_tokens
[0] = STATE_LIGHTMODEL_SCENECOLOR
;
3308 state_tokens
[1] = parse_face_type (inst
);
3313 case STATE_LIGHT_PROD
:
3314 state_tokens
[0] = STATE_LIGHTPROD
;
3315 state_tokens
[1] = parse_integer (inst
, Program
);
3317 /* Check the value of state_tokens[1] against the # of lights */
3318 if (state_tokens
[1] >= (GLint
) ctx
->Const
.MaxLights
) {
3319 _mesa_set_program_error (ctx
, Program
->Position
,
3320 "Invalid Light Number");
3321 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3322 "Invalid Light Number: %d", state_tokens
[1]);
3326 state_tokens
[2] = parse_face_type (inst
);
3327 switch (*(*inst
)++) {
3328 case LIGHT_PROD_AMBIENT
:
3329 state_tokens
[3] = STATE_AMBIENT
;
3331 case LIGHT_PROD_DIFFUSE
:
3332 state_tokens
[3] = STATE_DIFFUSE
;
3334 case LIGHT_PROD_SPECULAR
:
3335 state_tokens
[3] = STATE_SPECULAR
;
3342 switch (*(*inst
)++) {
3344 state_tokens
[0] = STATE_FOG_COLOR
;
3347 state_tokens
[0] = STATE_FOG_PARAMS
;
3353 state_tokens
[1] = parse_integer (inst
, Program
);
3354 switch (*(*inst
)++) {
3356 state_tokens
[0] = STATE_TEXENV_COLOR
;
3365 state_tokens
[0] = STATE_TEXGEN
;
3366 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3368 if (parse_texcoord_num (ctx
, inst
, Program
, &coord
))
3370 state_tokens
[1] = coord
;
3375 /* 0 - s, 1 - t, 2 - r, 3 - q */
3378 if (type
== TEX_GEN_EYE
) {
3381 state_tokens
[2] = STATE_TEXGEN_EYE_S
;
3384 state_tokens
[2] = STATE_TEXGEN_EYE_T
;
3387 state_tokens
[2] = STATE_TEXGEN_EYE_R
;
3390 state_tokens
[2] = STATE_TEXGEN_EYE_Q
;
3397 state_tokens
[2] = STATE_TEXGEN_OBJECT_S
;
3400 state_tokens
[2] = STATE_TEXGEN_OBJECT_T
;
3403 state_tokens
[2] = STATE_TEXGEN_OBJECT_R
;
3406 state_tokens
[2] = STATE_TEXGEN_OBJECT_Q
;
3414 switch (*(*inst
)++) {
3416 state_tokens
[0] = STATE_DEPTH_RANGE
;
3421 case STATE_CLIP_PLANE
:
3422 state_tokens
[0] = STATE_CLIPPLANE
;
3423 state_tokens
[1] = parse_integer (inst
, Program
);
3424 if (parse_clipplane_num (ctx
, inst
, Program
, &state_tokens
[1]))
3429 switch (*(*inst
++)) {
3431 state_tokens
[0] = STATE_POINT_SIZE
;
3434 case POINT_ATTENUATION
:
3435 state_tokens
[0] = STATE_POINT_ATTENUATION
;
3440 /* XXX: I think this is the correct format for a matrix row */
3441 case STATE_MATRIX_ROWS
:
3442 state_tokens
[0] = STATE_MATRIX
;
3444 (ctx
, inst
, Program
, &state_tokens
[1], &state_tokens
[2],
3448 state_tokens
[3] = parse_integer (inst
, Program
); /* The first row to grab */
3450 if ((**inst
) != 0) { /* Either the last row, 0 */
3451 state_tokens
[4] = parse_integer (inst
, Program
);
3452 if (state_tokens
[4] < state_tokens
[3]) {
3453 _mesa_set_program_error (ctx
, Program
->Position
,
3454 "Second matrix index less than the first");
3455 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3456 "Second matrix index (%d) less than the first (%d)",
3457 state_tokens
[4], state_tokens
[3]);
3462 state_tokens
[4] = state_tokens
[3];
3472 * This parses a state string (rather, the binary version of it) into
3473 * a 6-token similar for the state fetching code in program.c
3475 * One might ask, why fetch these parameters into just like you fetch
3476 * state when they are already stored in other places?
3478 * Because of array offsets -> We can stick env/local parameters in the
3479 * middle of a parameter array and then index someplace into the array
3482 * One optimization might be to only do this for the cases where the
3483 * env/local parameters end up inside of an array, and leave the
3484 * single parameters (or arrays of pure env/local pareameters) in their
3485 * respective register files.
3487 * For ENV parameters, the format is:
3488 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3489 * state_tokens[1] = STATE_ENV
3490 * state_tokens[2] = the parameter index
3492 * for LOCAL parameters, the format is:
3493 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3494 * state_tokens[1] = STATE_LOCAL
3495 * state_tokens[2] = the parameter index
3497 * \param inst - the start in the binary arry to start working from
3498 * \param state_tokens - the storage for the 6-token state description
3499 * \return - 0 on sucess, 1 on failure
3502 parse_program_single_item (GLcontext
* ctx
, GLubyte
** inst
,
3503 struct arb_program
*Program
, GLint
* state_tokens
)
3505 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
3506 state_tokens
[0] = STATE_FRAGMENT_PROGRAM
;
3508 state_tokens
[0] = STATE_VERTEX_PROGRAM
;
3511 switch (*(*inst
)++) {
3512 case PROGRAM_PARAM_ENV
:
3513 state_tokens
[1] = STATE_ENV
;
3514 state_tokens
[2] = parse_integer (inst
, Program
);
3516 /* Check state_tokens[2] against the number of ENV parameters available */
3517 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3518 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramEnvParams
))
3520 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3521 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramEnvParams
))) {
3522 _mesa_set_program_error (ctx
, Program
->Position
,
3523 "Invalid Program Env Parameter");
3524 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3525 "Invalid Program Env Parameter: %d",
3532 case PROGRAM_PARAM_LOCAL
:
3533 state_tokens
[1] = STATE_LOCAL
;
3534 state_tokens
[2] = parse_integer (inst
, Program
);
3536 /* Check state_tokens[2] against the number of LOCAL parameters available */
3537 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
3538 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxFragmentProgramLocalParams
))
3540 ((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
3541 (state_tokens
[2] >= (GLint
) ctx
->Const
.MaxVertexProgramLocalParams
))) {
3542 _mesa_set_program_error (ctx
, Program
->Position
,
3543 "Invalid Program Local Parameter");
3544 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3545 "Invalid Program Local Parameter: %d",
3556 * For ARB_vertex_program, programs are not allowed to use both an explicit
3557 * vertex attribute and a generic vertex attribute corresponding to the same
3558 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
3560 * This will walk our var_cache and make sure that nobody does anything fishy.
3562 * \return 0 on sucess, 1 on error
3565 generic_attrib_check(struct var_cache
*vc_head
)
3568 struct var_cache
*curr
;
3569 GLboolean explicitAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
],
3570 genericAttrib
[MAX_VERTEX_PROGRAM_ATTRIBS
];
3572 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3573 explicitAttrib
[a
] = GL_FALSE
;
3574 genericAttrib
[a
] = GL_FALSE
;
3579 if (curr
->type
== vt_attrib
) {
3580 if (curr
->attrib_is_generic
)
3581 genericAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3583 explicitAttrib
[ curr
->attrib_binding_idx
] = GL_TRUE
;
3589 for (a
=0; a
<MAX_VERTEX_PROGRAM_ATTRIBS
; a
++) {
3590 if ((explicitAttrib
[a
]) && (genericAttrib
[a
]))
3598 * This will handle the binding side of an ATTRIB var declaration
3600 * \param binding - the fragment input register state, defined in nvfragprog.h
3601 * \param binding_idx - the index in the attrib register file that binding is associated with
3602 * \return returns 0 on sucess, 1 on error
3604 * See nvfragparse.c for attrib register file layout
3607 parse_attrib_binding (GLcontext
* ctx
, GLubyte
** inst
,
3608 struct arb_program
*Program
, GLuint
* binding
,
3609 GLuint
* binding_idx
, GLuint
*is_generic
)
3616 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3617 switch (*(*inst
)++) {
3618 case FRAGMENT_ATTRIB_COLOR
:
3619 err
= parse_color_type (ctx
, inst
, Program
, &coord
);
3620 *binding
= FRAG_ATTRIB_COL0
+ coord
;
3621 *binding_idx
= 1 + coord
;
3624 case FRAGMENT_ATTRIB_TEXCOORD
:
3625 err
= parse_texcoord_num (ctx
, inst
, Program
, &texcoord
);
3626 *binding
= FRAG_ATTRIB_TEX0
+ texcoord
;
3627 *binding_idx
= 4 + texcoord
;
3630 case FRAGMENT_ATTRIB_FOGCOORD
:
3631 *binding
= FRAG_ATTRIB_FOGC
;
3635 case FRAGMENT_ATTRIB_POSITION
:
3636 *binding
= FRAG_ATTRIB_WPOS
;
3646 switch (*(*inst
)++) {
3647 case VERTEX_ATTRIB_POSITION
:
3648 *binding
= VERT_ATTRIB_POS
;
3652 case VERTEX_ATTRIB_WEIGHT
:
3656 err
= parse_weight_num (ctx
, inst
, Program
, &weight
);
3657 *binding
= VERT_ATTRIB_WEIGHT
;
3660 _mesa_set_program_error (ctx
, Program
->Position
,
3661 "ARB_vertex_blend not supported\n");
3662 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3663 "ARB_vertex_blend not supported\n");
3667 case VERTEX_ATTRIB_NORMAL
:
3668 *binding
= VERT_ATTRIB_NORMAL
;
3672 case VERTEX_ATTRIB_COLOR
:
3676 err
= parse_color_type (ctx
, inst
, Program
, &color
);
3678 *binding
= VERT_ATTRIB_COLOR1
;
3682 *binding
= VERT_ATTRIB_COLOR0
;
3688 case VERTEX_ATTRIB_FOGCOORD
:
3689 *binding
= VERT_ATTRIB_FOG
;
3693 case VERTEX_ATTRIB_TEXCOORD
:
3697 err
= parse_texcoord_num (ctx
, inst
, Program
, &unit
);
3698 *binding
= VERT_ATTRIB_TEX0
+ unit
;
3699 *binding_idx
= 8 + unit
;
3703 /* It looks like we don't support this at all, atm */
3704 case VERTEX_ATTRIB_MATRIXINDEX
:
3705 parse_integer (inst
, Program
);
3706 _mesa_set_program_error (ctx
, Program
->Position
,
3707 "ARB_palette_matrix not supported");
3708 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3709 "ARB_palette_matrix not supported");
3713 case VERTEX_ATTRIB_GENERIC
:
3717 if (!parse_generic_attrib_num(ctx
, inst
, Program
, &attrib
)) {
3721 *binding
= VERT_ATTRIB_POS
;
3724 *binding
= VERT_ATTRIB_WEIGHT
;
3727 *binding
= VERT_ATTRIB_NORMAL
;
3730 *binding
= VERT_ATTRIB_COLOR0
;
3733 *binding
= VERT_ATTRIB_COLOR1
;
3736 *binding
= VERT_ATTRIB_FOG
;
3743 *binding
= VERT_ATTRIB_TEX0
+ (attrib
-8);
3746 *binding_idx
= attrib
;
3757 /* Can this even happen? */
3759 _mesa_set_program_error (ctx
, Program
->Position
,
3760 "Bad attribute binding");
3761 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Bad attribute binding");
3764 Program
->InputsRead
|= (1 << *binding_idx
);
3770 * This translates between a binary token for an output variable type
3771 * and the mesa token for the same thing.
3774 * XXX: What is the 'name' for vertex program state? -> do we need it?
3775 * I don't think we do;
3777 * See nvfragprog.h for definitions
3779 * \param inst - The parsed tokens
3780 * \param binding - The name of the state we are binding too
3781 * \param binding_idx - The index into the result register file that this is bound too
3783 * See nvfragparse.c for the register file layout for fragment programs
3784 * See nvvertparse.c for the register file layout for vertex programs
3787 parse_result_binding (GLcontext
* ctx
, GLubyte
** inst
, GLuint
* binding
,
3788 GLuint
* binding_idx
, struct arb_program
*Program
)
3792 switch (*(*inst
)++) {
3793 case FRAGMENT_RESULT_COLOR
:
3794 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3795 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3796 *binding
= FRAG_OUTPUT_COLR
;
3799 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3805 case FRAGMENT_RESULT_DEPTH
:
3806 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3807 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3808 *binding
= FRAG_OUTPUT_DEPR
;
3811 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3814 GLuint face_type
= parse_face_type(inst
);
3815 GLint color_type_ret
= parse_color_type(ctx
, inst
, Program
, &color_type
);
3819 if (color_type_ret
) return 1;
3821 /* secondary color */
3832 /* secondary color */
3844 case VERTEX_RESULT_FOGCOORD
:
3848 case VERTEX_RESULT_POINTSIZE
:
3852 case VERTEX_RESULT_TEXCOORD
:
3853 if (parse_texcoord_num (ctx
, inst
, Program
, &b
))
3855 *binding_idx
= 7 + b
;
3859 Program
->OutputsWritten
|= (1 << *binding_idx
);
3865 * This handles the declaration of ATTRIB variables
3868 * parse_vert_attrib_binding(), or something like that
3870 * \return 0 on sucess, 1 on error
3873 parse_attrib (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
3874 struct arb_program
*Program
)
3878 struct var_cache
*attrib_var
;
3880 attrib_var
= parse_string (inst
, vc_head
, Program
, &found
);
3881 Program
->Position
= parse_position (inst
);
3883 error_msg
= (char *)
3884 _mesa_malloc (_mesa_strlen ((char *) attrib_var
->name
) + 40);
3885 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
3888 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
3889 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
3891 _mesa_free (error_msg
);
3895 attrib_var
->type
= vt_attrib
;
3897 /* I think this is ok now - karl */
3899 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3901 if (parse_attrib_binding
3902 (ctx
, inst
, Program
, &attrib_var
->attrib_binding
,
3903 &attrib_var
->attrib_binding_idx
, &attrib_var
->attrib_is_generic
))
3905 if (generic_attrib_check(*vc_head
)) {
3906 _mesa_set_program_error (ctx
, Program
->Position
,
3907 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3908 _mesa_error (ctx
, GL_INVALID_OPERATION
,
3909 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3915 Program
->Base
.NumAttributes
++;
3920 * \param use -- TRUE if we're called when declaring implicit parameters,
3921 * FALSE if we're declaraing variables. This has to do with
3922 * if we get a signed or unsigned float for scalar constants
3925 parse_param_elements (GLcontext
* ctx
, GLubyte
** inst
,
3926 struct var_cache
*param_var
,
3927 struct arb_program
*Program
, GLboolean use
)
3931 GLint state_tokens
[6];
3932 GLfloat const_values
[4];
3936 switch (*(*inst
)++) {
3937 case PARAM_STATE_ELEMENT
:
3939 if (parse_state_single_item (ctx
, inst
, Program
, state_tokens
))
3942 /* If we adding STATE_MATRIX that has multiple rows, we need to
3943 * unroll it and call _mesa_add_state_reference() for each row
3945 if ((state_tokens
[0] == STATE_MATRIX
)
3946 && (state_tokens
[3] != state_tokens
[4])) {
3948 GLint first_row
= state_tokens
[3];
3949 GLint last_row
= state_tokens
[4];
3951 for (row
= first_row
; row
<= last_row
; row
++) {
3952 state_tokens
[3] = state_tokens
[4] = row
;
3955 _mesa_add_state_reference (Program
->Parameters
,
3957 if (param_var
->param_binding_begin
== ~0U)
3958 param_var
->param_binding_begin
= idx
;
3959 param_var
->param_binding_length
++;
3960 Program
->Base
.NumParameters
++;
3965 _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3966 if (param_var
->param_binding_begin
== ~0U)
3967 param_var
->param_binding_begin
= idx
;
3968 param_var
->param_binding_length
++;
3969 Program
->Base
.NumParameters
++;
3973 case PARAM_PROGRAM_ELEMENT
:
3975 if (parse_program_single_item (ctx
, inst
, Program
, state_tokens
))
3977 idx
= _mesa_add_state_reference (Program
->Parameters
, state_tokens
);
3978 if (param_var
->param_binding_begin
== ~0U)
3979 param_var
->param_binding_begin
= idx
;
3980 param_var
->param_binding_length
++;
3981 Program
->Base
.NumParameters
++;
3983 /* Check if there is more: 0 -> we're done, else its an integer */
3985 GLuint out_of_range
, new_idx
;
3986 GLuint start_idx
= state_tokens
[2] + 1;
3987 GLuint end_idx
= parse_integer (inst
, Program
);
3990 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
3991 if (((state_tokens
[1] == STATE_ENV
)
3992 && (end_idx
>= ctx
->Const
.MaxFragmentProgramEnvParams
))
3993 || ((state_tokens
[1] == STATE_LOCAL
)
3995 ctx
->Const
.MaxFragmentProgramLocalParams
)))
3999 if (((state_tokens
[1] == STATE_ENV
)
4000 && (end_idx
>= ctx
->Const
.MaxVertexProgramEnvParams
))
4001 || ((state_tokens
[1] == STATE_LOCAL
)
4003 ctx
->Const
.MaxVertexProgramLocalParams
)))
4007 _mesa_set_program_error (ctx
, Program
->Position
,
4008 "Invalid Program Parameter");
4009 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4010 "Invalid Program Parameter: %d", end_idx
);
4014 for (new_idx
= start_idx
; new_idx
<= end_idx
; new_idx
++) {
4015 state_tokens
[2] = new_idx
;
4017 _mesa_add_state_reference (Program
->Parameters
,
4019 param_var
->param_binding_length
++;
4020 Program
->Base
.NumParameters
++;
4029 case PARAM_CONSTANT
:
4030 parse_constant (inst
, const_values
, Program
, use
);
4032 _mesa_add_named_constant (Program
->Parameters
,
4033 (char *) param_var
->name
, const_values
);
4034 if (param_var
->param_binding_begin
== ~0U)
4035 param_var
->param_binding_begin
= idx
;
4036 param_var
->param_binding_length
++;
4037 Program
->Base
.NumParameters
++;
4041 _mesa_set_program_error (ctx
, Program
->Position
,
4042 "Unexpected token in parse_param_elements()");
4043 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4044 "Unexpected token in parse_param_elements()");
4048 /* Make sure we haven't blown past our parameter limits */
4049 if (((Program
->type
== GL_VERTEX_PROGRAM_ARB
) &&
4050 (Program
->Base
.NumParameters
>=
4051 ctx
->Const
.MaxVertexProgramLocalParams
))
4052 || ((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
)
4053 && (Program
->Base
.NumParameters
>=
4054 ctx
->Const
.MaxFragmentProgramLocalParams
))) {
4055 _mesa_set_program_error (ctx
, Program
->Position
,
4056 "Too many parameter variables");
4057 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Too many parameter variables");
4065 * This picks out PARAM program parameter bindings.
4067 * XXX: This needs to be stressed & tested
4069 * \return 0 on sucess, 1 on error
4072 parse_param (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4073 struct arb_program
*Program
)
4075 GLuint found
, specified_length
, err
;
4077 struct var_cache
*param_var
;
4080 param_var
= parse_string (inst
, vc_head
, Program
, &found
);
4081 Program
->Position
= parse_position (inst
);
4084 error_msg
= (char *) _mesa_malloc (_mesa_strlen ((char *) param_var
->name
) + 40);
4085 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4088 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4089 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4091 _mesa_free (error_msg
);
4095 specified_length
= parse_integer (inst
, Program
);
4097 if (specified_length
< 0) {
4098 _mesa_set_program_error (ctx
, Program
->Position
,
4099 "Negative parameter array length");
4100 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4101 "Negative parameter array length: %d", specified_length
);
4105 param_var
->type
= vt_param
;
4106 param_var
->param_binding_length
= 0;
4108 /* Right now, everything is shoved into the main state register file.
4110 * In the future, it would be nice to leave things ENV/LOCAL params
4111 * in their respective register files, if possible
4113 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4116 * * - add each guy to the parameter list
4117 * * - increment the param_var->param_binding_len
4118 * * - store the param_var->param_binding_begin for the first one
4119 * * - compare the actual len to the specified len at the end
4121 while (**inst
!= PARAM_NULL
) {
4122 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_FALSE
))
4126 /* Test array length here! */
4127 if (specified_length
) {
4128 if (specified_length
!= param_var
->param_binding_length
) {
4129 _mesa_set_program_error (ctx
, Program
->Position
,
4130 "Declared parameter array lenght does not match parameter list");
4131 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4132 "Declared parameter array lenght does not match parameter list");
4145 parse_param_use (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4146 struct arb_program
*Program
, struct var_cache
**new_var
)
4148 struct var_cache
*param_var
;
4150 /* First, insert a dummy entry into the var_cache */
4151 var_cache_create (¶m_var
);
4152 param_var
->name
= (GLubyte
*) _mesa_strdup (" ");
4153 param_var
->type
= vt_param
;
4155 param_var
->param_binding_length
= 0;
4156 /* Don't fill in binding_begin; We use the default value of -1
4157 * to tell if its already initialized, elsewhere.
4159 * param_var->param_binding_begin = 0;
4161 param_var
->param_binding_type
= PROGRAM_STATE_VAR
;
4163 var_cache_append (vc_head
, param_var
);
4165 /* Then fill it with juicy parameter goodness */
4166 if (parse_param_elements (ctx
, inst
, param_var
, Program
, GL_TRUE
))
4169 *new_var
= param_var
;
4176 * This handles the declaration of TEMP variables
4178 * \return 0 on sucess, 1 on error
4181 parse_temp (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4182 struct arb_program
*Program
)
4185 struct var_cache
*temp_var
;
4188 while (**inst
!= 0) {
4189 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4190 Program
->Position
= parse_position (inst
);
4192 error_msg
= (char *)
4193 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4194 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4197 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4198 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4200 _mesa_free (error_msg
);
4204 temp_var
->type
= vt_temp
;
4206 if (((Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) &&
4207 (Program
->Base
.NumTemporaries
>=
4208 ctx
->Const
.MaxFragmentProgramTemps
))
4209 || ((Program
->type
== GL_VERTEX_PROGRAM_ARB
)
4210 && (Program
->Base
.NumTemporaries
>=
4211 ctx
->Const
.MaxVertexProgramTemps
))) {
4212 _mesa_set_program_error (ctx
, Program
->Position
,
4213 "Too many TEMP variables declared");
4214 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4215 "Too many TEMP variables declared");
4219 temp_var
->temp_binding
= Program
->Base
.NumTemporaries
;
4220 Program
->Base
.NumTemporaries
++;
4228 * This handles variables of the OUTPUT variety
4230 * \return 0 on sucess, 1 on error
4233 parse_output (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4234 struct arb_program
*Program
)
4237 struct var_cache
*output_var
;
4239 output_var
= parse_string (inst
, vc_head
, Program
, &found
);
4240 Program
->Position
= parse_position (inst
);
4243 error_msg
= (char *)
4244 _mesa_malloc (_mesa_strlen ((char *) output_var
->name
) + 40);
4245 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4248 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4249 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4251 _mesa_free (error_msg
);
4255 output_var
->type
= vt_output
;
4256 return parse_result_binding (ctx
, inst
, &output_var
->output_binding
,
4257 &output_var
->output_binding_idx
, Program
);
4261 * This handles variables of the ALIAS kind
4263 * \return 0 on sucess, 1 on error
4266 parse_alias (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4267 struct arb_program
*Program
)
4270 struct var_cache
*temp_var
;
4274 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4275 Program
->Position
= parse_position (inst
);
4278 error_msg
= (char *)
4279 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4280 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4283 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4284 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4286 _mesa_free (error_msg
);
4290 temp_var
->type
= vt_alias
;
4291 temp_var
->alias_binding
= parse_string (inst
, vc_head
, Program
, &found
);
4292 Program
->Position
= parse_position (inst
);
4296 error_msg
= (char *)
4297 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4298 _mesa_sprintf (error_msg
, "Alias value %s is not defined",
4299 temp_var
->alias_binding
->name
);
4301 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4302 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4304 _mesa_free (error_msg
);
4312 * This handles variables of the ADDRESS kind
4314 * \return 0 on sucess, 1 on error
4317 parse_address (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4318 struct arb_program
*Program
)
4321 struct var_cache
*temp_var
;
4324 while (**inst
!= 0) {
4325 temp_var
= parse_string (inst
, vc_head
, Program
, &found
);
4326 Program
->Position
= parse_position (inst
);
4328 error_msg
= (char *)
4329 _mesa_malloc (_mesa_strlen ((char *) temp_var
->name
) + 40);
4330 _mesa_sprintf (error_msg
, "Duplicate Varible Declaration: %s",
4333 _mesa_set_program_error (ctx
, Program
->Position
, error_msg
);
4334 _mesa_error (ctx
, GL_INVALID_OPERATION
, error_msg
);
4336 _mesa_free (error_msg
);
4340 temp_var
->type
= vt_address
;
4342 if (Program
->Base
.NumAddressRegs
>=
4343 ctx
->Const
.MaxVertexProgramAddressRegs
) {
4344 _mesa_set_program_error (ctx
, Program
->Position
,
4345 "Too many ADDRESS variables declared");
4346 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4347 "Too many ADDRESS variables declared");
4351 temp_var
->address_binding
= Program
->Base
.NumAddressRegs
;
4352 Program
->Base
.NumAddressRegs
++;
4360 * Parse a program declaration
4362 * \return 0 on sucess, 1 on error
4365 parse_declaration (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4366 struct arb_program
*Program
)
4370 switch (*(*inst
)++) {
4372 err
= parse_address (ctx
, inst
, vc_head
, Program
);
4376 err
= parse_alias (ctx
, inst
, vc_head
, Program
);
4380 err
= parse_attrib (ctx
, inst
, vc_head
, Program
);
4384 err
= parse_output (ctx
, inst
, vc_head
, Program
);
4388 err
= parse_param (ctx
, inst
, vc_head
, Program
);
4392 err
= parse_temp (ctx
, inst
, vc_head
, Program
);
4400 * Handle the parsing out of a masked destination register
4402 * \param File - The register file we write to
4403 * \param Index - The register index we write to
4404 * \param WriteMask - The mask controlling which components we write (1->write)
4406 * \return 0 on sucess, 1 on error
4409 parse_masked_dst_reg (GLcontext
* ctx
, GLubyte
** inst
,
4410 struct var_cache
**vc_head
, struct arb_program
*Program
,
4411 GLint
* File
, GLint
* Index
, GLboolean
* WriteMask
)
4415 struct var_cache
*dst
;
4417 /* We either have a result register specified, or a
4418 * variable that may or may not be writable
4420 switch (*(*inst
)++) {
4421 case REGISTER_RESULT
:
4422 if (parse_result_binding
4423 (ctx
, inst
, &result
, (GLuint
*) Index
, Program
))
4425 *File
= PROGRAM_OUTPUT
;
4428 case REGISTER_ESTABLISHED_NAME
:
4429 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4430 Program
->Position
= parse_position (inst
);
4432 /* If the name has never been added to our symbol table, we're hosed */
4434 _mesa_set_program_error (ctx
, Program
->Position
,
4435 "0: Undefined variable");
4436 _mesa_error (ctx
, GL_INVALID_OPERATION
, "0: Undefined variable: %s",
4441 switch (dst
->type
) {
4443 *File
= PROGRAM_OUTPUT
;
4444 *Index
= dst
->output_binding_idx
;
4448 *File
= PROGRAM_TEMPORARY
;
4449 *Index
= dst
->temp_binding
;
4452 /* If the var type is not vt_output or vt_temp, no go */
4454 _mesa_set_program_error (ctx
, Program
->Position
,
4455 "Destination register is read only");
4456 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4457 "Destination register is read only: %s",
4464 _mesa_set_program_error (ctx
, Program
->Position
,
4465 "Unexpected opcode in parse_masked_dst_reg()");
4466 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4467 "Unexpected opcode in parse_masked_dst_reg()");
4471 /* And then the mask.
4479 WriteMask
[0] = (mask
& (1 << 3)) >> 3;
4480 WriteMask
[1] = (mask
& (1 << 2)) >> 2;
4481 WriteMask
[2] = (mask
& (1 << 1)) >> 1;
4482 WriteMask
[3] = (mask
& (1));
4489 * Handle the parsing of a address register
4491 * \param Index - The register index we write to
4493 * \return 0 on sucess, 1 on error
4496 parse_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4497 struct var_cache
**vc_head
,
4498 struct arb_program
*Program
, GLint
* Index
)
4500 struct var_cache
*dst
;
4503 dst
= parse_string (inst
, vc_head
, Program
, &result
);
4504 Program
->Position
= parse_position (inst
);
4506 /* If the name has never been added to our symbol table, we're hosed */
4508 _mesa_set_program_error (ctx
, Program
->Position
, "Undefined variable");
4509 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Undefined variable: %s",
4514 if (dst
->type
!= vt_address
) {
4515 _mesa_set_program_error (ctx
, Program
->Position
,
4516 "Variable is not of type ADDRESS");
4517 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4518 "Variable: %s is not of type ADDRESS", dst
->name
);
4526 * Handle the parsing out of a masked address register
4528 * \param Index - The register index we write to
4529 * \param WriteMask - The mask controlling which components we write (1->write)
4531 * \return 0 on sucess, 1 on error
4534 parse_masked_address_reg (GLcontext
* ctx
, GLubyte
** inst
,
4535 struct var_cache
**vc_head
,
4536 struct arb_program
*Program
, GLint
* Index
,
4537 GLboolean
* WriteMask
)
4539 if (parse_address_reg (ctx
, inst
, vc_head
, Program
, Index
))
4542 /* This should be 0x8 */
4545 /* Writemask of .x is implied */
4547 WriteMask
[1] = WriteMask
[2] = WriteMask
[3] = 0;
4554 * Parse out a swizzle mask.
4556 * The values in the input stream are:
4557 * COMPONENT_X -> x/r
4558 * COMPONENT_Y -> y/g
4562 * The values in the output mask are:
4568 * The len parameter allows us to grab 4 components for a vector
4569 * swizzle, or just 1 component for a scalar src register selection
4572 parse_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLint len
)
4576 for (a
= 0; a
< 4; a
++)
4579 for (a
= 0; a
< len
; a
++) {
4580 switch (*(*inst
)++) {
4605 parse_extended_swizzle_mask (GLubyte
** inst
, GLubyte
* mask
, GLboolean
* Negate
)
4611 for (a
= 0; a
< 4; a
++) {
4612 if (parse_sign (inst
))
4619 mask
[a
] = SWIZZLE_ZERO
;
4622 mask
[a
] = SWIZZLE_ONE
;
4640 mask
[a
] = SWIZZLE_ZERO
;
4642 mask
[a
] = SWIZZLE_ONE
;
4654 parse_src_reg (GLcontext
* ctx
, GLubyte
** inst
, struct var_cache
**vc_head
,
4655 struct arb_program
*Program
, GLint
* File
, GLint
* Index
,
4656 GLboolean
*IsRelOffset
)
4658 struct var_cache
*src
;
4659 GLuint binding_state
, binding_idx
, is_generic
, found
, offset
;
4661 /* And the binding for the src */
4662 switch (*(*inst
)++) {
4663 case REGISTER_ATTRIB
:
4664 if (parse_attrib_binding
4665 (ctx
, inst
, Program
, &binding_state
, &binding_idx
, &is_generic
))
4667 *File
= PROGRAM_INPUT
;
4668 *Index
= binding_idx
;
4670 /* We need to insert a dummy variable into the var_cache so we can
4671 * catch generic vertex attrib aliasing errors
4673 var_cache_create(&src
);
4674 src
->type
= vt_attrib
;
4675 src
->name
= (GLubyte
*)_mesa_strdup("Dummy Attrib Variable");
4676 src
->attrib_binding
= binding_state
;
4677 src
->attrib_binding_idx
= binding_idx
;
4678 src
->attrib_is_generic
= is_generic
;
4679 var_cache_append(vc_head
, src
);
4680 if (generic_attrib_check(*vc_head
)) {
4681 _mesa_set_program_error (ctx
, Program
->Position
,
4682 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4683 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4684 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4689 case REGISTER_PARAM
:
4691 case PARAM_ARRAY_ELEMENT
:
4693 src
= parse_string (inst
, vc_head
, Program
, &found
);
4694 Program
->Position
= parse_position (inst
);
4697 _mesa_set_program_error (ctx
, Program
->Position
,
4698 "2: Undefined variable");
4699 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4700 "2: Undefined variable: %s", src
->name
);
4704 *File
= src
->param_binding_type
;
4706 switch (*(*inst
)++) {
4707 case ARRAY_INDEX_ABSOLUTE
:
4708 offset
= parse_integer (inst
, Program
);
4711 || (offset
>= src
->param_binding_length
)) {
4712 _mesa_set_program_error (ctx
, Program
->Position
,
4713 "Index out of range");
4714 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4715 "Index %d out of range for %s", offset
,
4720 *Index
= src
->param_binding_begin
+ offset
;
4723 case ARRAY_INDEX_RELATIVE
:
4725 GLint addr_reg_idx
, rel_off
;
4727 /* First, grab the address regiseter */
4728 if (parse_address_reg (ctx
, inst
, vc_head
, Program
, &addr_reg_idx
))
4737 /* Then the relative offset */
4738 if (parse_relative_offset(ctx
, inst
, Program
, &rel_off
)) return 1;
4740 /* And store it properly */
4741 *Index
= src
->param_binding_begin
+ rel_off
;
4750 if (parse_param_use (ctx
, inst
, vc_head
, Program
, &src
))
4753 *File
= src
->param_binding_type
;
4754 *Index
= src
->param_binding_begin
;
4759 case REGISTER_ESTABLISHED_NAME
:
4761 src
= parse_string (inst
, vc_head
, Program
, &found
);
4762 Program
->Position
= parse_position (inst
);
4764 /* If the name has never been added to our symbol table, we're hosed */
4766 _mesa_set_program_error (ctx
, Program
->Position
,
4767 "3: Undefined variable");
4768 _mesa_error (ctx
, GL_INVALID_OPERATION
, "3: Undefined variable: %s",
4773 switch (src
->type
) {
4775 *File
= PROGRAM_INPUT
;
4776 *Index
= src
->attrib_binding_idx
;
4779 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4781 *File
= src
->param_binding_type
;
4782 *Index
= src
->param_binding_begin
;
4786 *File
= PROGRAM_TEMPORARY
;
4787 *Index
= src
->temp_binding
;
4790 /* If the var type is vt_output no go */
4792 _mesa_set_program_error (ctx
, Program
->Position
,
4793 "destination register is read only");
4794 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4795 "destination register is read only: %s",
4802 _mesa_set_program_error (ctx
, Program
->Position
,
4803 "Unknown token in parse_src_reg");
4804 _mesa_error (ctx
, GL_INVALID_OPERATION
,
4805 "Unknown token in parse_src_reg");
4815 parse_vector_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4816 struct var_cache
**vc_head
, struct arb_program
*Program
,
4817 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4818 GLubyte
* Swizzle
, GLboolean
*IsRelOffset
)
4821 *Negate
= parse_sign (inst
);
4823 /* And the src reg */
4824 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
, IsRelOffset
))
4827 /* finally, the swizzle */
4828 parse_swizzle_mask (inst
, Swizzle
, 4);
4836 parse_scalar_src_reg (GLcontext
* ctx
, GLubyte
** inst
,
4837 struct var_cache
**vc_head
, struct arb_program
*Program
,
4838 GLint
* File
, GLint
* Index
, GLboolean
* Negate
,
4839 GLubyte
* Swizzle
, GLboolean
*IsRelOffset
)
4842 *Negate
= parse_sign (inst
);
4844 /* And the src reg */
4845 if (parse_src_reg (ctx
, inst
, vc_head
, Program
, File
, Index
, IsRelOffset
))
4848 /* Now, get the component and shove it into all the swizzle slots */
4849 parse_swizzle_mask (inst
, Swizzle
, 1);
4855 * This is a big mother that handles getting opcodes into the instruction
4856 * and handling the src & dst registers for fragment program instructions
4859 parse_fp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
4860 struct var_cache
**vc_head
, struct arb_program
*Program
,
4861 struct fp_instruction
*fp
)
4864 GLubyte swz
[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4866 GLubyte instClass
, type
, code
;
4869 /* No condition codes in ARB_fp */
4870 fp
->UpdateCondRegister
= 0;
4872 /* Record the position in the program string for debugging */
4873 fp
->StringPos
= Program
->Position
;
4875 /* OP_ALU_INST or OP_TEX_INST */
4876 instClass
= *(*inst
)++;
4878 /* OP_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4879 * OP_TEX_{SAMPLE, KIL}
4883 /* The actual opcode name */
4886 /* Increment the correct count */
4887 switch (instClass
) {
4889 Program
->NumAluInstructions
++;
4892 Program
->NumTexInstructions
++;
4897 fp
->Precision
= FLOAT32
;
4899 fp
->DstReg
.CondMask
= COND_TR
;
4907 fp
->Opcode
= FP_OPCODE_ABS
;
4913 fp
->Opcode
= FP_OPCODE_FLR
;
4919 fp
->Opcode
= FP_OPCODE_FRC
;
4925 fp
->Opcode
= FP_OPCODE_LIT
;
4931 fp
->Opcode
= FP_OPCODE_MOV
;
4935 if (parse_masked_dst_reg
4936 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4937 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
4940 fp
->SrcReg
[0].Abs
= GL_FALSE
;
4941 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
4942 if (parse_vector_src_reg
4943 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
4944 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
4948 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
4956 fp
->Opcode
= FP_OPCODE_COS
;
4962 fp
->Opcode
= FP_OPCODE_EX2
;
4968 fp
->Opcode
= FP_OPCODE_LG2
;
4974 fp
->Opcode
= FP_OPCODE_RCP
;
4980 fp
->Opcode
= FP_OPCODE_RSQ
;
4986 fp
->Opcode
= FP_OPCODE_SIN
;
4993 fp
->Opcode
= FP_OPCODE_SCS
;
4997 if (parse_masked_dst_reg
4998 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
4999 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5001 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5002 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5003 if (parse_scalar_src_reg
5004 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5005 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5009 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5017 fp
->Opcode
= FP_OPCODE_POW
;
5021 if (parse_masked_dst_reg
5022 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5023 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5025 for (a
= 0; a
< 2; a
++) {
5026 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5027 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5028 if (parse_scalar_src_reg
5029 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5030 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5034 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5044 fp
->Opcode
= FP_OPCODE_ADD
;
5050 fp
->Opcode
= FP_OPCODE_DP3
;
5056 fp
->Opcode
= FP_OPCODE_DP4
;
5062 fp
->Opcode
= FP_OPCODE_DPH
;
5068 fp
->Opcode
= FP_OPCODE_DST
;
5074 fp
->Opcode
= FP_OPCODE_MAX
;
5080 fp
->Opcode
= FP_OPCODE_MIN
;
5086 fp
->Opcode
= FP_OPCODE_MUL
;
5092 fp
->Opcode
= FP_OPCODE_SGE
;
5098 fp
->Opcode
= FP_OPCODE_SLT
;
5104 fp
->Opcode
= FP_OPCODE_SUB
;
5110 fp
->Opcode
= FP_OPCODE_X2D
;
5114 if (parse_masked_dst_reg
5115 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5116 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5118 for (a
= 0; a
< 2; a
++) {
5119 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5120 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5121 if (parse_vector_src_reg
5122 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5123 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5127 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5136 fp
->Opcode
= FP_OPCODE_CMP
;
5142 fp
->Opcode
= FP_OPCODE_LRP
;
5148 fp
->Opcode
= FP_OPCODE_MAD
;
5152 if (parse_masked_dst_reg
5153 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5154 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5156 for (a
= 0; a
< 3; a
++) {
5157 fp
->SrcReg
[a
].Abs
= GL_FALSE
;
5158 fp
->SrcReg
[a
].NegateAbs
= GL_FALSE
;
5159 if (parse_vector_src_reg
5160 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[a
].File
,
5161 &fp
->SrcReg
[a
].Index
, &fp
->SrcReg
[a
].NegateBase
,
5165 fp
->SrcReg
[a
].Swizzle
[b
] = swz
[b
];
5174 fp
->Opcode
= FP_OPCODE_SWZ
;
5177 if (parse_masked_dst_reg
5178 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5179 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5183 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5184 &fp
->SrcReg
[0].Index
, &rel
))
5186 parse_extended_swizzle_mask (inst
, swz
,
5187 &fp
->SrcReg
[0].NegateBase
);
5189 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5197 fp
->Opcode
= FP_OPCODE_TEX
;
5203 fp
->Opcode
= FP_OPCODE_TXP
;
5210 fp
->Opcode
= FP_OPCODE_TXB
;
5214 if (parse_masked_dst_reg
5215 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->DstReg
.File
,
5216 &fp
->DstReg
.Index
, fp
->DstReg
.WriteMask
))
5218 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5219 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5220 if (parse_vector_src_reg
5221 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5222 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5226 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5229 if (parse_texcoord_num (ctx
, inst
, Program
, &texcoord
))
5231 fp
->TexSrcUnit
= texcoord
;
5234 switch (*(*inst
)++) {
5236 fp
->TexSrcBit
= TEXTURE_1D_BIT
;
5239 fp
->TexSrcBit
= TEXTURE_2D_BIT
;
5242 fp
->TexSrcBit
= TEXTURE_3D_BIT
;
5244 case TEXTARGET_RECT
:
5245 fp
->TexSrcBit
= TEXTURE_RECT_BIT
;
5247 case TEXTARGET_CUBE
:
5248 fp
->TexSrcBit
= TEXTURE_CUBE_BIT
;
5251 Program
->TexturesUsed
[texcoord
] |= fp
->TexSrcBit
;
5255 fp
->Opcode
= FP_OPCODE_KIL
;
5256 fp
->SrcReg
[0].Abs
= GL_FALSE
;
5257 fp
->SrcReg
[0].NegateAbs
= GL_FALSE
;
5258 if (parse_vector_src_reg
5259 (ctx
, inst
, vc_head
, Program
, (GLint
*) & fp
->SrcReg
[0].File
,
5260 &fp
->SrcReg
[0].Index
, &fp
->SrcReg
[0].NegateBase
,
5264 fp
->SrcReg
[0].Swizzle
[b
] = swz
[b
];
5272 * This is a big mother that handles getting opcodes into the instruction
5273 * and handling the src & dst registers for vertex program instructions
5276 parse_vp_instruction (GLcontext
* ctx
, GLubyte
** inst
,
5277 struct var_cache
**vc_head
, struct arb_program
*Program
,
5278 struct vp_instruction
*vp
)
5283 /* OP_ALU_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5286 /* The actual opcode name */
5289 vp
->SrcReg
[0].RelAddr
= vp
->SrcReg
[1].RelAddr
= vp
->SrcReg
[2].RelAddr
= 0;
5291 for (a
= 0; a
< 4; a
++) {
5292 vp
->SrcReg
[0].Swizzle
[a
] = a
;
5293 vp
->SrcReg
[1].Swizzle
[a
] = a
;
5294 vp
->SrcReg
[2].Swizzle
[a
] = a
;
5295 vp
->DstReg
.WriteMask
[a
] = 1;
5301 vp
->Opcode
= VP_OPCODE_ARL
;
5303 /* Remember to set SrcReg.RelAddr; */
5305 /* Get the masked address register [dst] */
5306 if (parse_masked_address_reg
5307 (ctx
, inst
, vc_head
, Program
, &vp
->DstReg
.Index
,
5308 vp
->DstReg
.WriteMask
))
5310 vp
->DstReg
.File
= PROGRAM_ADDRESS
;
5312 /* Get a scalar src register */
5313 if (parse_scalar_src_reg
5314 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5315 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5316 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5324 vp
->Opcode
= VP_OPCODE_ABS
;
5327 vp
->Opcode
= VP_OPCODE_FLR
;
5330 vp
->Opcode
= VP_OPCODE_FRC
;
5333 vp
->Opcode
= VP_OPCODE_LIT
;
5336 vp
->Opcode
= VP_OPCODE_MOV
;
5339 if (parse_masked_dst_reg
5340 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5341 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5343 if (parse_vector_src_reg
5344 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5345 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5346 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5353 vp
->Opcode
= VP_OPCODE_EX2
;
5356 vp
->Opcode
= VP_OPCODE_EXP
;
5359 vp
->Opcode
= VP_OPCODE_LG2
;
5362 vp
->Opcode
= VP_OPCODE_LOG
;
5365 vp
->Opcode
= VP_OPCODE_RCP
;
5368 vp
->Opcode
= VP_OPCODE_RSQ
;
5371 if (parse_masked_dst_reg
5372 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5373 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5375 if (parse_scalar_src_reg
5376 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5377 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].Negate
,
5378 vp
->SrcReg
[0].Swizzle
, &vp
->SrcReg
[0].RelAddr
))
5385 vp
->Opcode
= VP_OPCODE_POW
;
5388 if (parse_masked_dst_reg
5389 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5390 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5392 for (a
= 0; a
< 2; a
++) {
5393 if (parse_scalar_src_reg
5394 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5395 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5396 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5404 vp
->Opcode
= VP_OPCODE_ADD
;
5407 vp
->Opcode
= VP_OPCODE_DP3
;
5410 vp
->Opcode
= VP_OPCODE_DP4
;
5413 vp
->Opcode
= VP_OPCODE_DPH
;
5416 vp
->Opcode
= VP_OPCODE_DST
;
5419 vp
->Opcode
= VP_OPCODE_MAX
;
5422 vp
->Opcode
= VP_OPCODE_MIN
;
5425 vp
->Opcode
= VP_OPCODE_MUL
;
5428 vp
->Opcode
= VP_OPCODE_SGE
;
5431 vp
->Opcode
= VP_OPCODE_SLT
;
5434 vp
->Opcode
= VP_OPCODE_SUB
;
5437 vp
->Opcode
= VP_OPCODE_XPD
;
5440 if (parse_masked_dst_reg
5441 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5442 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5444 for (a
= 0; a
< 2; a
++) {
5445 if (parse_vector_src_reg
5446 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5447 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5448 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5456 vp
->Opcode
= VP_OPCODE_MAD
;
5460 if (parse_masked_dst_reg
5461 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5462 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5464 for (a
= 0; a
< 3; a
++) {
5465 if (parse_vector_src_reg
5466 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[a
].File
,
5467 &vp
->SrcReg
[a
].Index
, &vp
->SrcReg
[a
].Negate
,
5468 vp
->SrcReg
[a
].Swizzle
, &vp
->SrcReg
[a
].RelAddr
))
5476 vp
->Opcode
= VP_OPCODE_SWZ
;
5479 if (parse_masked_dst_reg
5480 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->DstReg
.File
,
5481 &vp
->DstReg
.Index
, vp
->DstReg
.WriteMask
))
5485 (ctx
, inst
, vc_head
, Program
, (GLint
*) & vp
->SrcReg
[0].File
,
5486 &vp
->SrcReg
[0].Index
, &vp
->SrcReg
[0].RelAddr
))
5488 parse_extended_swizzle_mask (inst
, vp
->SrcReg
[0].Swizzle
,
5489 &vp
->SrcReg
[0].Negate
);
5498 print_state_token (GLint token
)
5501 case STATE_MATERIAL
:
5502 fprintf (stderr
, "STATE_MATERIAL ");
5505 fprintf (stderr
, "STATE_LIGHT ");
5508 case STATE_LIGHTMODEL_AMBIENT
:
5509 fprintf (stderr
, "STATE_AMBIENT ");
5512 case STATE_LIGHTMODEL_SCENECOLOR
:
5513 fprintf (stderr
, "STATE_SCENECOLOR ");
5516 case STATE_LIGHTPROD
:
5517 fprintf (stderr
, "STATE_LIGHTPROD ");
5521 fprintf (stderr
, "STATE_TEXGEN ");
5524 case STATE_FOG_COLOR
:
5525 fprintf (stderr
, "STATE_FOG_COLOR ");
5528 case STATE_FOG_PARAMS
:
5529 fprintf (stderr
, "STATE_FOG_PARAMS ");
5532 case STATE_CLIPPLANE
:
5533 fprintf (stderr
, "STATE_CLIPPLANE ");
5536 case STATE_POINT_SIZE
:
5537 fprintf (stderr
, "STATE_POINT_SIZE ");
5540 case STATE_POINT_ATTENUATION
:
5541 fprintf (stderr
, "STATE_ATTENUATION ");
5545 fprintf (stderr
, "STATE_MATRIX ");
5548 case STATE_MODELVIEW
:
5549 fprintf (stderr
, "STATE_MODELVIEW ");
5552 case STATE_PROJECTION
:
5553 fprintf (stderr
, "STATE_PROJECTION ");
5557 fprintf (stderr
, "STATE_MVP ");
5561 fprintf (stderr
, "STATE_TEXTURE ");
5565 fprintf (stderr
, "STATE_PROGRAM ");
5568 case STATE_MATRIX_INVERSE
:
5569 fprintf (stderr
, "STATE_INVERSE ");
5572 case STATE_MATRIX_TRANSPOSE
:
5573 fprintf (stderr
, "STATE_TRANSPOSE ");
5576 case STATE_MATRIX_INVTRANS
:
5577 fprintf (stderr
, "STATE_INVTRANS ");
5581 fprintf (stderr
, "STATE_AMBIENT ");
5585 fprintf (stderr
, "STATE_DIFFUSE ");
5588 case STATE_SPECULAR
:
5589 fprintf (stderr
, "STATE_SPECULAR ");
5592 case STATE_EMISSION
:
5593 fprintf (stderr
, "STATE_EMISSION ");
5596 case STATE_SHININESS
:
5597 fprintf (stderr
, "STATE_SHININESS ");
5601 fprintf (stderr
, "STATE_HALF ");
5604 case STATE_POSITION
:
5605 fprintf (stderr
, "STATE_POSITION ");
5608 case STATE_ATTENUATION
:
5609 fprintf (stderr
, "STATE_ATTENUATION ");
5612 case STATE_SPOT_DIRECTION
:
5613 fprintf (stderr
, "STATE_DIRECTION ");
5616 case STATE_TEXGEN_EYE_S
:
5617 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5620 case STATE_TEXGEN_EYE_T
:
5621 fprintf (stderr
, "STATE_TEXGEN_EYE_T ");
5624 case STATE_TEXGEN_EYE_R
:
5625 fprintf (stderr
, "STATE_TEXGEN_EYE_R ");
5628 case STATE_TEXGEN_EYE_Q
:
5629 fprintf (stderr
, "STATE_TEXGEN_EYE_Q ");
5632 case STATE_TEXGEN_OBJECT_S
:
5633 fprintf (stderr
, "STATE_TEXGEN_EYE_S ");
5636 case STATE_TEXGEN_OBJECT_T
:
5637 fprintf (stderr
, "STATE_TEXGEN_OBJECT_T ");
5640 case STATE_TEXGEN_OBJECT_R
:
5641 fprintf (stderr
, "STATE_TEXGEN_OBJECT_R ");
5644 case STATE_TEXGEN_OBJECT_Q
:
5645 fprintf (stderr
, "STATE_TEXGEN_OBJECT_Q ");
5648 case STATE_TEXENV_COLOR
:
5649 fprintf (stderr
, "STATE_TEXENV_COLOR ");
5652 case STATE_DEPTH_RANGE
:
5653 fprintf (stderr
, "STATE_DEPTH_RANGE ");
5656 case STATE_VERTEX_PROGRAM
:
5657 fprintf (stderr
, "STATE_VERTEX_PROGRAM ");
5660 case STATE_FRAGMENT_PROGRAM
:
5661 fprintf (stderr
, "STATE_FRAGMENT_PROGRAM ");
5665 fprintf (stderr
, "STATE_ENV ");
5669 fprintf (stderr
, "STATE_LOCAL ");
5673 fprintf (stderr
, "[%d] ", token
);
5678 debug_variables (GLcontext
* ctx
, struct var_cache
*vc_head
,
5679 struct arb_program
*Program
)
5681 struct var_cache
*vc
;
5684 fprintf (stderr
, "debug_variables, vc_head: %x\n", vc_head
);
5686 /* First of all, print out the contents of the var_cache */
5689 fprintf (stderr
, "[%x]\n", vc
);
5692 fprintf (stderr
, "UNDEFINED %s\n", vc
->name
);
5695 fprintf (stderr
, "ATTRIB %s\n", vc
->name
);
5696 fprintf (stderr
, " binding: 0x%x\n", vc
->attrib_binding
);
5699 fprintf (stderr
, "PARAM %s begin: %d len: %d\n", vc
->name
,
5700 vc
->param_binding_begin
, vc
->param_binding_length
);
5701 b
= vc
->param_binding_begin
;
5702 for (a
= 0; a
< vc
->param_binding_length
; a
++) {
5703 fprintf (stderr
, "%s\n",
5704 Program
->Parameters
->Parameters
[a
+ b
].Name
);
5705 if (Program
->Parameters
->Parameters
[a
+ b
].Type
== STATE
) {
5706 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5708 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5710 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5712 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5714 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5716 print_state_token (Program
->Parameters
->Parameters
[a
+ b
].
5720 fprintf (stderr
, "%f %f %f %f\n",
5721 Program
->Parameters
->Parameters
[a
+ b
].Values
[0],
5722 Program
->Parameters
->Parameters
[a
+ b
].Values
[1],
5723 Program
->Parameters
->Parameters
[a
+ b
].Values
[2],
5724 Program
->Parameters
->Parameters
[a
+ b
].Values
[3]);
5728 fprintf (stderr
, "TEMP %s\n", vc
->name
);
5729 fprintf (stderr
, " binding: 0x%x\n", vc
->temp_binding
);
5732 fprintf (stderr
, "OUTPUT %s\n", vc
->name
);
5733 fprintf (stderr
, " binding: 0x%x\n", vc
->output_binding
);
5736 fprintf (stderr
, "ALIAS %s\n", vc
->name
);
5737 fprintf (stderr
, " binding: 0x%x (%s)\n",
5738 vc
->alias_binding
, vc
->alias_binding
->name
);
5749 * The main loop for parsing a fragment or vertex program
5751 * \return 0 on sucess, 1 on error
5754 parse_arb_program (GLcontext
* ctx
, GLubyte
* inst
, struct var_cache
**vc_head
,
5755 struct arb_program
*Program
)
5759 Program
->MajorVersion
= (GLuint
) * inst
++;
5760 Program
->MinorVersion
= (GLuint
) * inst
++;
5762 while (*inst
!= END
) {
5767 case ARB_PRECISION_HINT_FASTEST
:
5768 Program
->HintPrecisionFastest
= 1;
5771 case ARB_PRECISION_HINT_NICEST
:
5772 Program
->HintPrecisionNicest
= 1;
5776 Program
->HintFogExp
= 1;
5780 Program
->HintFogExp2
= 1;
5783 case ARB_FOG_LINEAR
:
5784 Program
->HintFogLinear
= 1;
5787 case ARB_POSITION_INVARIANT
:
5788 Program
->HintPositionInvariant
= 1;
5794 Program
->Position
= parse_position (&inst
);
5796 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5797 /* Realloc Program->FPInstructions */
5798 Program
->FPInstructions
=
5799 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5800 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5801 (Program
->Base
.NumInstructions
+1)*sizeof (struct fp_instruction
));
5803 /* parse the current instruction */
5804 err
= parse_fp_instruction (ctx
, &inst
, vc_head
, Program
,
5805 &Program
->FPInstructions
[Program
->Base
.NumInstructions
]);
5809 /* Realloc Program->VPInstructions */
5810 Program
->VPInstructions
=
5811 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5812 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5813 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5815 /* parse the current instruction */
5816 err
= parse_vp_instruction (ctx
, &inst
, vc_head
, Program
,
5817 &Program
->VPInstructions
[Program
->Base
.NumInstructions
]);
5820 /* increment Program->Base.NumInstructions */
5821 Program
->Base
.NumInstructions
++;
5825 err
= parse_declaration (ctx
, &inst
, vc_head
, Program
);
5836 /* Finally, tag on an OPCODE_END instruction */
5837 if (Program
->type
== GL_FRAGMENT_PROGRAM_ARB
) {
5838 Program
->FPInstructions
=
5839 (struct fp_instruction
*) _mesa_realloc (Program
->FPInstructions
,
5840 Program
->Base
.NumInstructions
*sizeof(struct fp_instruction
),
5841 (Program
->Base
.NumInstructions
+1)*sizeof(struct fp_instruction
));
5843 Program
->FPInstructions
[Program
->Base
.NumInstructions
].Opcode
= FP_OPCODE_END
;
5846 Program
->VPInstructions
=
5847 (struct vp_instruction
*) _mesa_realloc (Program
->VPInstructions
,
5848 Program
->Base
.NumInstructions
*sizeof(struct vp_instruction
),
5849 (Program
->Base
.NumInstructions
+1)*sizeof(struct vp_instruction
));
5851 Program
->VPInstructions
[Program
->Base
.NumInstructions
].Opcode
= VP_OPCODE_END
;
5854 /* increment Program->Base.NumInstructions */
5855 Program
->Base
.NumInstructions
++;
5862 * This kicks everything off.
5864 * \param ctx - The GL Context
5865 * \param str - The program string
5866 * \param len - The program string length
5867 * \param Program - The arb_program struct to return all the parsed info in
5868 * \return 0 on sucess, 1 on error
5871 _mesa_parse_arb_program (GLcontext
* ctx
, const GLubyte
* str
, GLsizei len
,
5872 struct arb_program
* program
)
5874 GLint a
, err
, error_pos
;
5875 char error_msg
[300];
5877 struct var_cache
*vc_head
;
5879 GLubyte
*parsed
, *inst
;
5882 fprintf (stderr
, "Loading grammar text!\n");
5884 dt
= grammar_load_from_text ((GLubyte
*) arb_grammar_text
);
5886 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5887 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5888 _mesa_error (ctx
, GL_INVALID_OPERATION
,
5889 "Error loading grammer rule set");
5894 printf ("Checking Grammar!\n");
5896 err
= grammar_check (dt
, str
, &parsed
, &parsed_len
);
5899 /* Syntax parse error */
5901 grammar_get_last_error ((GLubyte
*) error_msg
, 300, &error_pos
);
5902 _mesa_set_program_error (ctx
, error_pos
, error_msg
);
5903 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Parse Error");
5910 printf ("Destroying grammer dict [parse retval: %d]\n", err
);
5914 /* Initialize the arb_program struct */
5915 program
->Base
.NumInstructions
=
5916 program
->Base
.NumTemporaries
=
5917 program
->Base
.NumParameters
=
5918 program
->Base
.NumAttributes
= program
->Base
.NumAddressRegs
= 0;
5919 program
->Parameters
= _mesa_new_parameter_list ();
5920 program
->InputsRead
= 0;
5921 program
->OutputsWritten
= 0;
5922 program
->Position
= 0;
5923 program
->MajorVersion
= program
->MinorVersion
= 0;
5924 program
->HintPrecisionFastest
=
5925 program
->HintPrecisionNicest
=
5926 program
->HintFogExp2
=
5927 program
->HintFogExp
=
5928 program
->HintFogLinear
= program
->HintPositionInvariant
= 0;
5929 for (a
= 0; a
< MAX_TEXTURE_IMAGE_UNITS
; a
++)
5930 program
->TexturesUsed
[a
] = 0;
5931 program
->NumAluInstructions
=
5932 program
->NumTexInstructions
=
5933 program
->NumTexIndirections
= 0;
5935 program
->FPInstructions
= NULL
;
5936 program
->VPInstructions
= NULL
;
5941 /* Start examining the tokens in the array */
5944 /* Check the grammer rev */
5945 if (*inst
++ != REVISION
) {
5946 _mesa_set_program_error (ctx
, 0, "Grammar version mismatch");
5947 _mesa_error (ctx
, GL_INVALID_OPERATION
, "Grammar verison mismatch");
5952 case FRAGMENT_PROGRAM
:
5953 program
->type
= GL_FRAGMENT_PROGRAM_ARB
;
5956 case VERTEX_PROGRAM
:
5957 program
->type
= GL_VERTEX_PROGRAM_ARB
;
5961 err
= parse_arb_program (ctx
, inst
, &vc_head
, program
);
5963 fprintf (stderr
, "Symantic analysis returns %d [1 is bad!]\n", err
);
5967 /*debug_variables(ctx, vc_head, program); */
5969 /* We're done with the parsed binary array */
5970 var_cache_destroy (&vc_head
);
5972 _mesa_free (parsed
);
5974 printf ("_mesa_parse_arb_program() done\n");