added support for generic vertex attributes (ARB_vp) and their error checking
[mesa.git] / src / mesa / main / arbparse.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 5.1
4 *
5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
23 */
24
25 #define DEBUG_PARSING 0
26
27 /**
28 * \file arbparse.c
29 * ARB_*_program parser core
30 * \author Michal Krol, Karl Rasche
31 */
32
33
34 #include "mtypes.h"
35 #include "glheader.h"
36 #include "context.h"
37 #include "hash.h"
38 #include "imports.h"
39 #include "macros.h"
40 #include "program.h"
41 #include "nvvertprog.h"
42 #include "nvfragprog.h"
43 #include "arbparse.h"
44
45 /* TODO:
46 * Fragment Program Stuff:
47 * -----------------------------------------------------
48 * - How does negating on SWZ work?? If any of the components have a -,
49 * negate?
50 * - how does thing like 'foo[N]' work in src registers?
51 *
52 * - things from Michal's email
53 * + overflow on atoi
54 * + not-overflowing floats (don't use parse_integer..)
55 * + test for 0 on matrix rows, or give a default value to parse_integer()
56 *
57 * + fix multiple cases in switches, that might change
58 * (these are things that are #defined to the same value, but occur
59 * only on fp or vp's, which funkifies the switch statements)
60 * - STATE_TEX_* STATE_CLIP_PLANE, etc and PRECISION_HINT_FASTEST/
61 * PositionInvariant
62 *
63 * - check all limits of number of various variables
64 * + parameters
65 * + modelview matrix number
66 *
67 * - test! test! test!
68 *
69 * Vertex Program Stuff:
70 * -----------------------------------------------------
71 * - Add in cases for vp attribs
72 * + VERTEX_ATTRIB_MATRIXINDEX -- ??
73 *
74 * - ARRAY_INDEX_RELATIVE
75 * - grep for XXX
76 *
77 * Mesa Stuff
78 * -----------------------------------------------------
79 * - vp_src swizzle is GLubyte, fp_src swizzle is GLuint
80 * - fetch state listed in program_parameters list
81 * + WTF should this go???
82 * + currently in nvvertexec.c and s_nvfragprog.c
83 *
84 * - allow for multiple address registers (and fetch address regs properly)
85 *
86 * Cosmetic Stuff
87 * -----------------------------------------------------
88 * - fix compiler warnings
89 * - remove any leftover unused grammer.c stuff (dict_ ?)
90 * - fix grammer.c error handling so its not static
91 * - #ifdef around stuff pertaining to extentions
92 *
93 * Outstanding Questions:
94 * -----------------------------------------------------
95 * - palette matrix? do we support this extension? what is the extention?
96 * - When can we fetch env/local params from their own register files, and
97 * when to we have to fetch them into the main state register file?
98 * (think arrays)
99 *
100 * Grammar Changes:
101 * -----------------------------------------------------
102 * - changed optional_exponent rule from:
103 * " exponent .or .true .emit '1' .emit 0x00;\n"
104 * to
105 * " exponent .or .true .emit '1' .emit 0x00 .emit $;\n"
106 *
107 * - XXX: need to recognize "1" as a valid float ?
108 * - XXX: this fails:
109 * "MUL result.color.xyz, R0, program.local[35] ;"
110 * but this works:
111 * "MUL result.color.primary.xyz, R0, program.local[35] ;"
112 * -> see progs/tests/arbvptorus.c
113 *
114 * - changed "progLocalParam\n" changed from:
115 * " \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum
116 * .and rbracket;\n"
117 * to:
118 * " \"local\" .emit PROGRAM_PARAM_LOCAL .and lbracket .and progLocalParamNum
119 * .and rbracket .emit 0x00;\n"
120 * so we can distinguish between the progLocalParam and progLocalParams rules
121 *
122 * - made the same change as above to the progEnvParam rule
123 */
124
125 typedef GLubyte *production;
126
127 /*-----------------------------------------------------------------------
128 * From here on down is the syntax checking portion
129 */
130
131 /* VERSION: 0.3 */
132
133 /*
134 INTRODUCTION
135 ------------
136
137 The task is to check the syntax of an input string. Input string is a
138 stream of ASCII characters terminated with null-character
139 ('\0'). Checking it using C language is difficult and hard to
140 implement without bugs. It is hard to maintain and change prior to
141 further syntax changes.
142
143 This is because of high redundancy of the C code. Large blocks of code
144 are duplicated with only small changes. Even using macros does not
145 solve the problem, because macros cannot erase the complexity of the
146 code.
147
148 The resolution is to create a new language that will be highly
149 oriented to our task. Once we describe particular syntax, we are
150 done. We can then focus on the code that implements the language. The
151 size and complexity of it is relatively small than the code that
152 directly checks the syntax.
153
154 First, we must implement our new language. Here, the language is
155 implemented in C, but it could also be implemented in any other
156 language. The code is listed below. We must take a good care that it
157 is bug free. This is simple because the code is simple and clean.
158
159 Next, we must describe the syntax of our new language in itself. Once
160 created and checked manually that it is correct, we can use it to
161 check another scripts.
162
163 Note that our new language loading code does not have to check the
164 syntax. It is because we assume that the script describing itself is
165 correct, and other scripts can be syntactically checked by the former
166 script. The loading code must only do semantic checking which leads us
167 to simple resolving references.
168
169 THE LANGUAGE
170 ------------
171
172 Here I will describe the syntax of the new language (further called
173 "Synek"). It is mainly a sequence of declarations terminated by a
174 semicolon. The declaration consists of a symbol, which is an
175 identifier, and its definition. A definition is in turn a sequence of
176 specifiers connected with ".and" or ".or" operator. These operators
177 cannot be mixed together in a one definition. Specifier can be a
178 symbol, string, character, character range or a special keyword
179 ".true" or ".false".
180
181 On the very beginning of the script there is a declaration of a root
182 symbol and is in the form:
183 .syntax <root_symbol>;
184
185 The <root_symbol> must be on of the symbols in declaration
186 sequence. The syntax is correct if the root symbol evaluates to
187 true. A symbol evaluates to true if the definition associated with the
188 symbol evaluates to true. Definition evaluation depends on the
189 operator used to connect specifiers in the definition. If ".and"
190 operator is used, definition evaluates to true if and only if all the
191 specifiers evaluate to true. If ".or" operator is used, definition
192 evalutes to true if any of the specifiers evaluates to true. If
193 definition contains only one specifier, it is evaluated as if it was
194 connected with ".true" keyword by ".and" operator.
195
196 If specifier is a ".true" keyword, it always evaluates to true.
197
198 If specifier is a ".false" keyword, it always evaluates to
199 false. Specifier evaluates to false when it does not evaluate to true.
200
201 Character range specifier is in the form:
202 '<first_character>' - '<second_character>'
203
204 If specifier is a character range, it evaluates to true if character
205 in the stream is greater or equal to <first_character> and less or
206 equal to <second_character>. In that situation the stream pointer is
207 advanced to point to next character in the stream. All C-style escape
208 sequences are supported although trigraph sequences are not. The
209 comparisions are performed on 8-bit unsigned integers.
210
211 Character specifier is in the form:
212 '<single_character>'
213
214 It evaluates to true if the following character range specifier evaluates to
215 true:
216 '<single_character>' - '<single_character>'
217
218 String specifier is in the form:
219 "<string>"
220
221 Let N be the number of characters in <string>. Let <string>[i]
222 designate i-th character in <string>. Then the string specifier
223 evaluates to true if and only if for i in the range [0, N) the
224 following character specifier evaluates to true:
225 '<string>[i]'
226
227 If <string>[i] is a quotation mark, '<string>[i]' is replaced with
228 '\<string>[i]'.
229
230 Symbol specifier can be optionally preceded by a ".loop" keyword in the form:
231 .loop <symbol> (1)
232 where <symbol> is defined as follows:
233 <symbol> <definition>; (2)
234 Construction (1) is replaced by the following code:
235 <symbol$1>
236 and declaration (2) is replaced by the following:
237 <symbol$1> <symbol$2> .or .true;
238 <symbol$2> <symbol> .and <symbol$1>;
239 <symbol> <definition>;
240
241
242 ESCAPE SEQUENCES
243 ----------------
244
245 Synek supports all escape sequences in character specifiers. The
246 mapping table is listed below. All occurences of the characters in
247 the first column are replaced with the corresponding character in the
248 second column.
249
250 Escape sequence Represents
251 -----------------------------------------------------------------------
252 \a Bell (alert)
253 \b Backspace
254 \f Formfeed
255 \n New line
256 \r Carriage return
257 \t Horizontal tab
258 \v Vertical tab
259 \' Single quotation mark
260 \" Double quotation mark
261 \\ Backslash
262 \? Literal question mark
263 \ooo ASCII character in octal notation
264 \xhhh ASCII character in hexadecimal notation
265 -----------------------------------------------------------------------
266
267
268 RAISING ERRORS
269 --------------
270
271 Any specifier can be followed by a special construction that is
272 executed when the specifier evaluates to false. The construction is in
273 the form:
274 .error <ERROR_TEXT>
275
276 <ERROR_TEXT> is an identifier declared earlier by error text
277 declaration. The declaration is in the form:
278
279 .errtext <ERROR_TEXT> "<error_desc>"
280
281 When specifier evaluates to false and this construction is present,
282 parsing is stopped immediately and <error_desc> is returned as a
283 result of parsing. The error position is also returned and it is meant
284 as an offset from the beggining of the stream to the character that
285 was valid so far. Example:
286
287 (**** syntax script ****)
288
289 .syntax program;
290 .errtext MISSING_SEMICOLON "missing ';'"
291 program declaration .and .loop space .and ';'
292 .error MISSING_SEMICOLON .and
293 .loop space .and '\0';
294 declaration "declare" .and .loop space .and identifier;
295 space ' ';
296 (**** sample code ****)
297 declare foo ,
298
299 In the example above checking the sample code will result in error
300 message "missing ';'" and error position 12. The sample code is not
301 correct. Note the presence of '\0' specifier to assure that there is
302 no code after semicolon - only spaces. <error_desc> can optionally
303 contain identifier surrounded by dollar signs $. In such a case, the
304 identifier and dollar signs are replaced by a string retrieved by
305 invoking symbol with the identifier name. The starting position is the
306 error position. The lenght of the resulting string is the position
307 after invoking the symbol.
308
309
310 PRODUCTION
311 ----------
312
313 Synek not only checks the syntax but it can also produce (emit) bytes
314 associated with specifiers that evaluate to true. That is, every
315 specifier and optional error construction can be followed by a number
316 of emit constructions that are in the form:
317 .emit <parameter>
318
319 <paramater> can be a HEX number, identifier, a star * or a dollar
320 $. HEX number is preceded by 0x or 0X. If <parameter> is an
321 identifier, it must be earlier declared by emit code declaration in
322 the form:
323 .emtcode <identifier> <hex_number>
324
325 When given specifier evaluates to true, all emits associated with the
326 specifier are output in order they were declared. A star means that
327 last-read character should be output instead of constant
328 value. Example:
329
330 (**** syntax script ****)
331
332 .syntax foobar;
333 .emtcode WORD_FOO 0x01
334 .emtcode WORD_BAR 0x02
335 foobar FOO .emit WORD_FOO .or BAR .emit WORD_BAR .or .true .emit 0x00;
336 FOO "foo" .and SPACE;
337 BAR "bar" .and SPACE;
338 SPACE ' ' .or '\0';
339
340 (**** sample text 1 ****)
341
342 foo
343
344 (**** sample text 2 ****)
345
346 foobar
347
348 For both samples the result will be one-element array. For first
349 sample text it will be value 1, for second - 0. Note that every text
350 will be accepted because of presence of .true as an alternative.
351
352 Another example:
353
354 (**** syntax script ****)
355
356 .syntax declaration;
357 .emtcode VARIABLE 0x01
358 declaration "declare" .and .loop space .and
359 identifier .emit VARIABLE .and (1)
360 .true .emit 0x00 .and (2)
361 .loop space .and ';';
362 space ' ' .or '\t';
363 identifier .loop id_char .emit *; (3)
364 id_char 'a'-'z' .or 'A'-'Z' .or '_';
365 (**** sample code ****)
366 declare fubar;
367
368 In specifier (1) symbol <identifier> is followed by .emit VARIABLE. If
369 it evaluates to true, VARIABLE constant and then production of the
370 symbol is output. Specifier (2) is used to terminate the string with
371 null to signal when the string ends. Specifier (3) outputs all
372 characters that make declared identifier. The result of sample code
373 will be the following array:
374 { 1, 'f', 'u', 'b', 'a', 'r', 0 }
375
376 If .emit is followed by dollar $, it means that current position
377 should be output. Current position is a 32-bit unsigned integer
378 distance from the very beginning of the parsed string to first
379 character consumed by the specifier associated with the .emit
380 instruction. Current position is stored in the output buffer in
381 Little-Endian convention (the lowest byte comes first). */
382
383
384 /**
385 * This is the text describing the rules to parse the grammar
386 */
387 #include "arbparse_syn.h"
388
389 /**
390 * These should match up with the values defined in arbparse.syn.h
391 */
392
393 #define REVISION 0x03
394
395 /* program type */
396 #define FRAGMENT_PROGRAM 0x01
397 #define VERTEX_PROGRAM 0x02
398
399 /* program section */
400 #define OPTION 0x01
401 #define INSTRUCTION 0x02
402 #define DECLARATION 0x03
403 #define END 0x04
404
405 /* fragment program option flags */
406 #define ARB_PRECISION_HINT_FASTEST 0x01
407 #define ARB_PRECISION_HINT_NICEST 0x02
408 #define ARB_FOG_EXP 0x04
409 #define ARB_FOG_EXP2 0x08
410 #define ARB_FOG_LINEAR 0x10
411
412 /* vertex program option flags */
413 #define ARB_POSITION_INVARIANT 0x01
414
415 /* fragment program instruction class */
416 #define F_ALU_INST 0x01
417 #define F_TEX_INST 0x02
418
419 /* fragment program instruction type */
420 #define F_ALU_VECTOR 0x01
421 #define F_ALU_SCALAR 0x02
422 #define F_ALU_BINSC 0x03
423 #define F_ALU_BIN 0x04
424 #define F_ALU_TRI 0x05
425 #define F_ALU_SWZ 0x06
426 #define F_TEX_SAMPLE 0x07
427 #define F_TEX_KIL 0x08
428
429 /* vertex program instruction type */
430 #define V_GEN_ARL 0x01
431 #define V_GEN_VECTOR 0x02
432 #define V_GEN_SCALAR 0x03
433 #define V_GEN_BINSC 0x04
434 #define V_GEN_BIN 0x05
435 #define V_GEN_TRI 0x06
436 #define V_GEN_SWZ 0x07
437
438 /* fragment program instruction code */
439 #define F_ABS 0x00
440 #define F_ABS_SAT 0x01
441 #define F_FLR 0x02
442 #define F_FLR_SAT 0x03
443 #define F_FRC 0x04
444 #define F_FRC_SAT 0x05
445 #define F_LIT 0x06
446 #define F_LIT_SAT 0x07
447 #define F_MOV 0x08
448 #define F_MOV_SAT 0x09
449 #define F_COS 0x0A
450 #define F_COS_SAT 0x0B
451 #define F_EX2 0x0C
452 #define F_EX2_SAT 0x0D
453 #define F_LG2 0x0E
454 #define F_LG2_SAT 0x0F
455 #define F_RCP 0x10
456 #define F_RCP_SAT 0x11
457 #define F_RSQ 0x12
458 #define F_RSQ_SAT 0x13
459 #define F_SIN 0x14
460 #define F_SIN_SAT 0x15
461 #define F_SCS 0x16
462 #define F_SCS_SAT 0x17
463 #define F_POW 0x18
464 #define F_POW_SAT 0x19
465 #define F_ADD 0x1A
466 #define F_ADD_SAT 0x1B
467 #define F_DP3 0x1C
468 #define F_DP3_SAT 0x1D
469 #define F_DP4 0x1E
470 #define F_DP4_SAT 0x1F
471 #define F_DPH 0x20
472 #define F_DPH_SAT 0x21
473 #define F_DST 0x22
474 #define F_DST_SAT 0x23
475 #define F_MAX 0x24
476 #define F_MAX_SAT 0x25
477 #define F_MIN 0x26
478 #define F_MIN_SAT 0x27
479 #define F_MUL 0x28
480 #define F_MUL_SAT 0x29
481 #define F_SGE 0x2A
482 #define F_SGE_SAT 0x2B
483 #define F_SLT 0x2C
484 #define F_SLT_SAT 0x2D
485 #define F_SUB 0x2E
486 #define F_SUB_SAT 0x2F
487 #define F_XPD 0x30
488 #define F_XPD_SAT 0x31
489 #define F_CMP 0x32
490 #define F_CMP_SAT 0x33
491 #define F_LRP 0x34
492 #define F_LRP_SAT 0x35
493 #define F_MAD 0x36
494 #define F_MAD_SAT 0x37
495 #define F_SWZ 0x38
496 #define F_SWZ_SAT 0x39
497 #define F_TEX 0x3A
498 #define F_TEX_SAT 0x3B
499 #define F_TXB 0x3C
500 #define F_TXB_SAT 0x3D
501 #define F_TXP 0x3E
502 #define F_TXP_SAT 0x3F
503 #define F_KIL 0x40
504
505 /* vertex program instruction code */
506 #define V_ARL 0x01
507 #define V_ABS 0x02
508 #define V_FLR 0x03
509 #define V_FRC 0x04
510 #define V_LIT 0x05
511 #define V_MOV 0x06
512 #define V_EX2 0x07
513 #define V_EXP 0x08
514 #define V_LG2 0x09
515 #define V_LOG 0x0A
516 #define V_RCP 0x0B
517 #define V_RSQ 0x0C
518 #define V_POW 0x0D
519 #define V_ADD 0x0E
520 #define V_DP3 0x0F
521 #define V_DP4 0x10
522 #define V_DPH 0x11
523 #define V_DST 0x12
524 #define V_MAX 0x13
525 #define V_MIN 0x14
526 #define V_MUL 0x15
527 #define V_SGE 0x16
528 #define V_SLT 0x17
529 #define V_SUB 0x18
530 #define V_XPD 0x19
531 #define V_MAD 0x1A
532 #define V_SWZ 0x1B
533
534 /* fragment attribute binding */
535 #define FRAGMENT_ATTRIB_COLOR 0x01
536 #define FRAGMENT_ATTRIB_TEXCOORD 0x02
537 #define FRAGMENT_ATTRIB_FOGCOORD 0x03
538 #define FRAGMENT_ATTRIB_POSITION 0x04
539
540 /* vertex attribute binding */
541 #define VERTEX_ATTRIB_POSITION 0x01
542 #define VERTEX_ATTRIB_WEIGHT 0x02
543 #define VERTEX_ATTRIB_NORMAL 0x03
544 #define VERTEX_ATTRIB_COLOR 0x04
545 #define VERTEX_ATTRIB_FOGCOORD 0x05
546 #define VERTEX_ATTRIB_TEXCOORD 0x06
547 #define VERTEX_ATTRIB_MATRIXINDEX 0x07
548 #define VERTEX_ATTRIB_GENERIC 0x08
549
550 /* fragment result binding */
551 #define FRAGMENT_RESULT_COLOR 0x01
552 #define FRAGMENT_RESULT_DEPTH 0x02
553
554 /* vertex result binding */
555 #define VERTEX_RESULT_POSITION 0x01
556 #define VERTEX_RESULT_COLOR 0x02
557 #define VERTEX_RESULT_FOGCOORD 0x03
558 #define VERTEX_RESULT_POINTSIZE 0x04
559 #define VERTEX_RESULT_TEXCOORD 0x05
560
561 /* texture target */
562 #define TEXTARGET_1D 0x01
563 #define TEXTARGET_2D 0x02
564 #define TEXTARGET_3D 0x03
565 #define TEXTARGET_RECT 0x04
566 #define TEXTARGET_CUBE 0x05
567
568 /* sign */
569 /*
570 $3: removed. '+' and '-' are used instead.
571 */
572 /*
573 #define SIGN_PLUS 0x00
574 #define SIGN_MINUS 0x01
575 */
576
577 /* face type */
578 #define FACE_FRONT 0x00
579 #define FACE_BACK 0x01
580
581 /* color type */
582 #define COLOR_PRIMARY 0x00
583 #define COLOR_SECONDARY 0x01
584
585 /* component */
586 /*
587 $3: Added enumerants.
588 */
589 #define COMPONENT_X 0x00
590 #define COMPONENT_Y 0x01
591 #define COMPONENT_Z 0x02
592 #define COMPONENT_W 0x03
593 #define COMPONENT_0 0x04
594 #define COMPONENT_1 0x05
595
596 #define ARRAY_INDEX_ABSOLUTE 0x00
597 #define ARRAY_INDEX_RELATIVE 0x01
598
599 /* matrix name */
600 #define MATRIX_MODELVIEW 0x01
601 #define MATRIX_PROJECTION 0x02
602 #define MATRIX_MVP 0x03
603 #define MATRIX_TEXTURE 0x04
604 #define MATRIX_PALETTE 0x05
605 #define MATRIX_PROGRAM 0x06
606
607 /* matrix modifier */
608 #define MATRIX_MODIFIER_IDENTITY 0x00
609 #define MATRIX_MODIFIER_INVERSE 0x01
610 #define MATRIX_MODIFIER_TRANSPOSE 0x02
611 #define MATRIX_MODIFIER_INVTRANS 0x03
612
613 /* constant type */
614 #define CONSTANT_SCALAR 0x01
615 #define CONSTANT_VECTOR 0x02
616
617 /* program param type */
618 #define PROGRAM_PARAM_ENV 0x01
619 #define PROGRAM_PARAM_LOCAL 0x02
620
621 /* register type */
622 #define REGISTER_ATTRIB 0x01
623 #define REGISTER_PARAM 0x02
624 #define REGISTER_RESULT 0x03
625 #define REGISTER_ESTABLISHED_NAME 0x04
626
627 /* param binding */
628 #define PARAM_NULL 0x00
629 #define PARAM_ARRAY_ELEMENT 0x01
630 #define PARAM_STATE_ELEMENT 0x02
631 #define PARAM_PROGRAM_ELEMENT 0x03
632 #define PARAM_PROGRAM_ELEMENTS 0x04
633 #define PARAM_CONSTANT 0x05
634
635 /* param state property */
636 #define STATE_MATERIAL_PARSER 0x01
637 #define STATE_LIGHT_PARSER 0x02
638 #define STATE_LIGHT_MODEL 0x03
639 #define STATE_LIGHT_PROD 0x04
640 #define STATE_FOG 0x05
641 #define STATE_MATRIX_ROWS 0x06
642 /* fragment program only */
643 #define STATE_TEX_ENV 0x07
644 #define STATE_DEPTH 0x08
645 /* vertex program only */
646 #define STATE_TEX_GEN 0x07
647 #define STATE_CLIP_PLANE 0x08
648 #define STATE_POINT 0x09
649
650 /* state material property */
651 #define MATERIAL_AMBIENT 0x01
652 #define MATERIAL_DIFFUSE 0x02
653 #define MATERIAL_SPECULAR 0x03
654 #define MATERIAL_EMISSION 0x04
655 #define MATERIAL_SHININESS 0x05
656
657 /* state light property */
658 #define LIGHT_AMBIENT 0x01
659 #define LIGHT_DIFFUSE 0x02
660 #define LIGHT_SPECULAR 0x03
661 #define LIGHT_POSITION 0x04
662 #define LIGHT_ATTENUATION 0x05
663 #define LIGHT_HALF 0x06
664 #define LIGHT_SPOT_DIRECTION 0x07
665
666 /* state light model property */
667 #define LIGHT_MODEL_AMBIENT 0x01
668 #define LIGHT_MODEL_SCENECOLOR 0x02
669
670 /* state light product property */
671 #define LIGHT_PROD_AMBIENT 0x01
672 #define LIGHT_PROD_DIFFUSE 0x02
673 #define LIGHT_PROD_SPECULAR 0x03
674
675 /* state texture environment property */
676 #define TEX_ENV_COLOR 0x01
677
678 /* state texture generation coord property */
679 #define TEX_GEN_EYE 0x01
680 #define TEX_GEN_OBJECT 0x02
681
682 /* state fog property */
683 #define FOG_COLOR 0x01
684 #define FOG_PARAMS 0x02
685
686 /* state depth property */
687 #define DEPTH_RANGE 0x01
688
689 /* state point parameters property */
690 #define POINT_SIZE 0x01
691 #define POINT_ATTENUATION 0x02
692
693 /* declaration */
694 #define ATTRIB 0x01
695 #define PARAM 0x02
696 #define TEMP 0x03
697 #define OUTPUT 0x04
698 #define ALIAS 0x05
699 /* vertex program 1.0 only */
700 #define ADDRESS 0x06
701
702 /*
703 memory management routines
704 */
705 static GLvoid *mem_alloc (GLsizei);
706 static GLvoid mem_free (GLvoid **);
707 static GLvoid *mem_realloc (GLvoid *, GLsizei, GLsizei);
708 static GLubyte *str_duplicate (const GLubyte *);
709
710 /*
711 internal error messages
712 */
713 static const GLubyte *OUT_OF_MEMORY =
714 (GLubyte *) "internal error 1001: out of physical memory";
715 static const GLubyte *UNRESOLVED_REFERENCE =
716 (GLubyte *) "internal error 1002: unresolved reference '$'";
717 /*
718 static const GLubyte *INVALID_PARAMETER =
719 (GLubyte *) "internal error 1003: invalid parameter";
720 */
721
722 static const GLubyte *error_message = NULL;
723 static GLubyte *error_param = NULL; /* this is inserted into error_message in place of $ */
724 static GLint error_position = -1;
725
726 static GLubyte *unknown = (GLubyte *) "???";
727
728 static GLvoid
729 clear_last_error ()
730 {
731 /* reset error message */
732 error_message = NULL;
733
734 /* free error parameter - if error_param is a "???" don't free it - it's static */
735 if (error_param != unknown)
736 mem_free ((GLvoid **) & error_param);
737 else
738 error_param = NULL;
739
740 /* reset error position */
741 error_position = -1;
742 }
743
744 static GLvoid
745 set_last_error (const GLubyte * msg, GLubyte * param, GLint pos)
746 {
747 if (error_message != NULL)
748 return;
749
750 error_message = msg;
751 if (param != NULL)
752 error_param = param;
753 else
754 error_param = unknown;
755
756 error_position = pos;
757 }
758
759 /*
760 * memory management routines
761 */
762 static GLvoid *
763 mem_alloc (GLsizei size)
764 {
765 GLvoid *ptr = _mesa_malloc (size);
766 if (ptr == NULL)
767 set_last_error (OUT_OF_MEMORY, NULL, -1);
768 return ptr;
769 }
770
771 static GLvoid
772 mem_free (GLvoid ** ptr)
773 {
774 _mesa_free (*ptr);
775 *ptr = NULL;
776 }
777
778 static GLvoid *
779 mem_realloc (GLvoid * ptr, GLsizei old_size, GLsizei new_size)
780 {
781 GLvoid *ptr2 = _mesa_realloc (ptr, old_size, new_size);
782 if (ptr2 == NULL)
783 set_last_error (OUT_OF_MEMORY, NULL, -1);
784 return ptr2;
785 }
786
787 static GLubyte *
788 str_duplicate (const GLubyte * str)
789 {
790 return (GLubyte *) _mesa_strdup ((const char *) str);
791 }
792
793 /*
794 * emit type typedef
795 */
796 typedef enum emit_type_
797 {
798 et_byte, /* explicit number */
799 et_stream, /* eaten character */
800 et_position /* current position */
801 }
802 emit_type;
803
804 /*
805 * emit typedef
806 */
807 typedef struct emit_
808 {
809 emit_type m_emit_type;
810 GLubyte m_byte; /* et_byte */
811 struct emit_ *m_next;
812 }
813 emit;
814
815 static GLvoid
816 emit_create (emit ** em)
817 {
818 *em = mem_alloc (sizeof (emit));
819 if (*em) {
820 (**em).m_emit_type = et_byte;
821 (**em).m_byte = 0;
822 (**em).m_next = NULL;
823 }
824 }
825
826 static GLvoid
827 emit_destroy (emit ** em)
828 {
829 if (*em) {
830 emit_destroy (&(**em).m_next);
831 mem_free ((GLvoid **) em);
832 }
833 }
834
835 static GLvoid
836 emit_append (emit ** em, emit ** ne)
837 {
838 if (*em)
839 emit_append (&(**em).m_next, ne);
840 else
841 *em = *ne;
842 }
843
844 /*
845 * error typedef
846 */
847 typedef struct error_
848 {
849 GLubyte *m_text;
850 GLubyte *m_token_name;
851 struct defntn_ *m_token;
852 }
853 error;
854
855 static GLvoid
856 error_create (error ** er)
857 {
858 *er = mem_alloc (sizeof (error));
859 if (*er) {
860 (**er).m_text = NULL;
861 (**er).m_token_name = NULL;
862 (**er).m_token = NULL;
863 }
864 }
865
866 static GLvoid
867 error_destroy (error ** er)
868 {
869 if (*er) {
870 mem_free ((GLvoid **) & (**er).m_text);
871 mem_free ((GLvoid **) & (**er).m_token_name);
872 mem_free ((GLvoid **) er);
873 }
874 }
875
876 struct dict_;
877 static GLubyte *error_get_token (error *, struct dict_ *, const GLubyte *, GLuint);
878
879 /*
880 * specifier type typedef
881 */
882 typedef enum spec_type_
883 {
884 st_false,
885 st_true,
886 st_byte,
887 st_byte_range,
888 st_string,
889 st_identifier,
890 st_identifier_loop,
891 st_debug
892 } spec_type;
893
894
895 /*
896 * specifier typedef
897 */
898 typedef struct spec_
899 {
900 spec_type m_spec_type;
901 GLubyte m_byte[2]; /* st_byte, st_byte_range */
902 GLubyte *m_string; /* st_string */
903 struct defntn_ *m_defntn; /* st_identifier, st_identifier_loop */
904 emit *m_emits;
905 error *m_errtext;
906 struct spec_ *m_next;
907 } spec;
908
909
910 static GLvoid
911 spec_create (spec ** sp)
912 {
913 *sp = mem_alloc (sizeof (spec));
914 if (*sp) {
915 (**sp).m_spec_type = st_false;
916 (**sp).m_byte[0] = '\0';
917 (**sp).m_byte[1] = '\0';
918 (**sp).m_string = NULL;
919 (**sp).m_defntn = NULL;
920 (**sp).m_emits = NULL;
921 (**sp).m_errtext = NULL;
922 (**sp).m_next = NULL;
923 }
924 }
925
926 static GLvoid
927 spec_destroy (spec ** sp)
928 {
929 if (*sp) {
930 spec_destroy (&(**sp).m_next);
931 emit_destroy (&(**sp).m_emits);
932 error_destroy (&(**sp).m_errtext);
933 mem_free ((GLvoid **) & (**sp).m_string);
934 mem_free ((GLvoid **) sp);
935 }
936 }
937
938 static GLvoid
939 spec_append (spec ** sp, spec ** ns)
940 {
941 if (*sp)
942 spec_append (&(**sp).m_next, ns);
943 else
944 *sp = *ns;
945 }
946
947 /*
948 * operator typedef
949 */
950 typedef enum oper_
951 {
952 op_none,
953 op_and,
954 op_or
955 } oper;
956
957
958 /*
959 * definition typedef
960 */
961 typedef struct defntn_
962 {
963 oper m_oper;
964 spec *m_specs;
965 struct defntn_ *m_next;
966 #ifndef NDEBUG
967 GLint m_referenced;
968 #endif
969 } defntn;
970
971
972 static GLvoid
973 defntn_create (defntn ** de)
974 {
975 *de = mem_alloc (sizeof (defntn));
976 if (*de) {
977 (**de).m_oper = op_none;
978 (**de).m_specs = NULL;
979 (**de).m_next = NULL;
980 #ifndef NDEBUG
981 (**de).m_referenced = 0;
982 #endif
983 }
984 }
985
986 static GLvoid
987 defntn_destroy (defntn ** de)
988 {
989 if (*de) {
990 defntn_destroy (&(**de).m_next);
991 spec_destroy (&(**de).m_specs);
992 mem_free ((GLvoid **) de);
993 }
994 }
995
996 static GLvoid
997 defntn_append (defntn ** de, defntn ** nd)
998 {
999 if (*de)
1000 defntn_append (&(**de).m_next, nd);
1001 else
1002 *de = *nd;
1003 }
1004
1005 /*
1006 * dictionary typedef
1007 */
1008 typedef struct dict_
1009 {
1010 defntn *m_defntns;
1011 defntn *m_syntax;
1012 defntn *m_string;
1013 struct dict_ *m_next;
1014 } dict;
1015
1016
1017 static GLvoid
1018 dict_create (dict ** di)
1019 {
1020 *di = mem_alloc (sizeof (dict));
1021 if (*di) {
1022 (**di).m_defntns = NULL;
1023 (**di).m_syntax = NULL;
1024 (**di).m_string = NULL;
1025 (**di).m_next = NULL;
1026 }
1027 }
1028
1029 static GLvoid
1030 dict_destroy (dict ** di)
1031 {
1032 if (*di) {
1033 dict_destroy (&(**di).m_next);
1034 defntn_destroy (&(**di).m_defntns);
1035 mem_free ((GLvoid **) di);
1036 }
1037 }
1038
1039 /*
1040 * GLubyte array typedef
1041 */
1042 typedef struct barray_
1043 {
1044 GLubyte *data;
1045 GLuint len;
1046 } barray;
1047
1048
1049 static GLvoid
1050 barray_create (barray ** ba)
1051 {
1052 *ba = mem_alloc (sizeof (barray));
1053 if (*ba) {
1054 (**ba).data = NULL;
1055 (**ba).len = 0;
1056 }
1057 }
1058
1059 static GLvoid
1060 barray_destroy (barray ** ba)
1061 {
1062 if (*ba) {
1063 mem_free ((GLvoid **) & (**ba).data);
1064 mem_free ((GLvoid **) ba);
1065 }
1066 }
1067
1068 /*
1069 * reallocates GLubyte array to requested size,
1070 * returns 0 on success,
1071 * returns 1 otherwise
1072 */
1073 static GLint
1074 barray_resize (barray ** ba, GLuint nlen)
1075 {
1076 GLubyte *new_pointer;
1077
1078 if (nlen == 0) {
1079 mem_free ((void **) &(**ba).data);
1080 (**ba).data = NULL;
1081 (**ba).len = 0;
1082
1083 return 0;
1084 }
1085 else {
1086 new_pointer =
1087 mem_realloc ((**ba).data, (**ba).len * sizeof (GLubyte),
1088 nlen * sizeof (GLubyte));
1089 if (new_pointer) {
1090 (**ba).data = new_pointer;
1091 (**ba).len = nlen;
1092
1093 return 0;
1094 }
1095 }
1096
1097 return 1;
1098 }
1099
1100 /*
1101 * adds GLubyte array pointed by *nb to the end of array pointed by *ba,
1102 * returns 0 on success,
1103 * returns 1 otherwise
1104 */
1105 static GLint
1106 barray_append (barray ** ba, barray ** nb)
1107 {
1108 GLuint i;
1109 const GLuint len = (**ba).len;
1110
1111 if (barray_resize (ba, (**ba).len + (**nb).len))
1112 return 1;
1113
1114 for (i = 0; i < (**nb).len; i++)
1115 (**ba).data[len + i] = (**nb).data[i];
1116
1117 return 0;
1118 }
1119
1120
1121 /**
1122 * Adds emit chain pointed by em to the end of array pointed by *ba.
1123 * \return 0 on success, 1 otherwise.
1124 */
1125 static GLint
1126 barray_push (barray ** ba, emit * em, GLubyte c, GLuint pos)
1127 {
1128 emit *temp = em;
1129 GLuint count = 0;
1130
1131 while (temp) {
1132 if (temp->m_emit_type == et_position)
1133 count += 4; /* position is a 32-bit unsigned integer */
1134 else
1135 count++;
1136
1137 temp = temp->m_next;
1138 }
1139
1140 if (barray_resize (ba, (**ba).len + count))
1141 return 1;
1142
1143 while (em) {
1144 if (em->m_emit_type == et_byte)
1145 (**ba).data[(**ba).len - count--] = em->m_byte;
1146 else if (em->m_emit_type == et_stream)
1147 (**ba).data[(**ba).len - count--] = c;
1148
1149 /* This is where the position is emitted into the stream */
1150 else { /* em->type == et_position */
1151 #if 0
1152 (**ba).data[(**ba).len - count--] = (GLubyte) pos,
1153 (**ba).data[(**ba).len - count--] = (GLubyte) (pos >> 8),
1154 (**ba).data[(**ba).len - count--] = (GLubyte) (pos >> 16),
1155 (**ba).data[(**ba).len - count--] = (GLubyte) (pos >> 24);
1156 #else
1157 (**ba).data[(**ba).len - count--] = (GLubyte) pos;
1158 (**ba).data[(**ba).len - count--] = (GLubyte) (pos / 0x100);
1159 (**ba).data[(**ba).len - count--] = (GLubyte) (pos / 0x10000);
1160 (**ba).data[(**ba).len - count--] = (GLubyte) (pos / 0x1000000);
1161 #endif
1162 }
1163
1164 em = em->m_next;
1165 }
1166
1167 return 0;
1168 }
1169
1170 /**
1171 * string to string map typedef
1172 */
1173 typedef struct map_str_
1174 {
1175 GLubyte *key;
1176 GLubyte *data;
1177 struct map_str_ *next;
1178 } map_str;
1179
1180
1181 static GLvoid
1182 map_str_create (map_str ** ma)
1183 {
1184 *ma = mem_alloc (sizeof (map_str));
1185 if (*ma) {
1186 (**ma).key = NULL;
1187 (**ma).data = NULL;
1188 (**ma).next = NULL;
1189 }
1190 }
1191
1192 static GLvoid
1193 map_str_destroy (map_str ** ma)
1194 {
1195 if (*ma) {
1196 map_str_destroy (&(**ma).next);
1197 mem_free ((GLvoid **) & (**ma).key);
1198 mem_free ((GLvoid **) & (**ma).data);
1199 mem_free ((GLvoid **) ma);
1200 }
1201 }
1202
1203 static GLvoid
1204 map_str_append (map_str ** ma, map_str ** nm)
1205 {
1206 if (*ma)
1207 map_str_append (&(**ma).next, nm);
1208 else
1209 *ma = *nm;
1210 }
1211
1212 /**
1213 * searches the map for specified key,
1214 * if the key is matched, *data is filled with data associated with the key,
1215 * \return 0 if the key is matched, 1 otherwise
1216 */
1217 static GLint
1218 map_str_find (map_str ** ma, const GLubyte * key, GLubyte ** data)
1219 {
1220 while (*ma) {
1221 if (strcmp ((const char *) (**ma).key, (const char *) key) == 0) {
1222 *data = str_duplicate ((**ma).data);
1223 if (*data == NULL)
1224 return 1;
1225
1226 return 0;
1227 }
1228
1229 ma = &(**ma).next;
1230 }
1231
1232 set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
1233 return 1;
1234 }
1235
1236 /**
1237 * string to GLubyte map typedef
1238 */
1239 typedef struct map_byte_
1240 {
1241 GLubyte *key;
1242 GLubyte data;
1243 struct map_byte_ *next;
1244 } map_byte;
1245
1246 static GLvoid
1247 map_byte_create (map_byte ** ma)
1248 {
1249 *ma = mem_alloc (sizeof (map_byte));
1250 if (*ma) {
1251 (**ma).key = NULL;
1252 (**ma).data = 0;
1253 (**ma).next = NULL;
1254 }
1255 }
1256
1257 static GLvoid
1258 map_byte_destroy (map_byte ** ma)
1259 {
1260 if (*ma) {
1261 map_byte_destroy (&(**ma).next);
1262 mem_free ((GLvoid **) & (**ma).key);
1263 mem_free ((GLvoid **) ma);
1264 }
1265 }
1266
1267 static GLvoid
1268 map_byte_append (map_byte ** ma, map_byte ** nm)
1269 {
1270 if (*ma)
1271 map_byte_append (&(**ma).next, nm);
1272 else
1273 *ma = *nm;
1274 }
1275
1276 /**
1277 * Searches the map for specified key,
1278 * If the key is matched, *data is filled with data associated with the key,
1279 * \return 0 if the is matched, 1 otherwise
1280 */
1281 static GLint
1282 map_byte_find (map_byte ** ma, const GLubyte * key, GLubyte * data)
1283 {
1284 while (*ma) {
1285 if (strcmp ((const char *) (**ma).key, (const char *) key) == 0) {
1286 *data = (**ma).data;
1287 return 0;
1288 }
1289
1290 ma = &(**ma).next;
1291 }
1292
1293 set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
1294 return 1;
1295 }
1296
1297 /*
1298 * string to defntn map typedef
1299 */
1300 typedef struct map_def_
1301 {
1302 GLubyte *key;
1303 defntn *data;
1304 struct map_def_ *next;
1305 } map_def;
1306
1307 static GLvoid
1308 map_def_create (map_def ** ma)
1309 {
1310 *ma = mem_alloc (sizeof (map_def));
1311 if (*ma) {
1312 (**ma).key = NULL;
1313 (**ma).data = NULL;
1314 (**ma).next = NULL;
1315 }
1316 }
1317
1318 static GLvoid
1319 map_def_destroy (map_def ** ma)
1320 {
1321 if (*ma) {
1322 map_def_destroy (&(**ma).next);
1323 mem_free ((GLvoid **) & (**ma).key);
1324 mem_free ((GLvoid **) ma);
1325 }
1326 }
1327
1328 static GLvoid
1329 map_def_append (map_def ** ma, map_def ** nm)
1330 {
1331 if (*ma)
1332 map_def_append (&(**ma).next, nm);
1333 else
1334 *ma = *nm;
1335 }
1336
1337 /**
1338 * searches the map for specified key,
1339 * if the key is matched, *data is filled with data associated with the key,
1340 * \return 0 if the is matched, 1 otherwise
1341 */
1342 static GLint
1343 map_def_find (map_def ** ma, const GLubyte * key, defntn ** data)
1344 {
1345 while (*ma) {
1346 if (_mesa_strcmp ((const char *) (**ma).key, (const char *) key) == 0) {
1347 *data = (**ma).data;
1348
1349 return 0;
1350 }
1351
1352 ma = &(**ma).next;
1353 }
1354
1355 set_last_error (UNRESOLVED_REFERENCE, str_duplicate (key), -1);
1356 return 1;
1357 }
1358
1359 /*
1360 * returns 1 if given character is a space,
1361 * returns 0 otherwise
1362 */
1363 static GLint
1364 is_space (GLubyte c)
1365 {
1366 return c == ' ' || c == '\t' || c == '\n' || c == '\r';
1367 }
1368
1369 /*
1370 * advances text pointer by 1 if character pointed by *text is a space,
1371 * returns 1 if a space has been eaten,
1372 * returns 0 otherwise
1373 */
1374 static GLint
1375 eat_space (const GLubyte ** text)
1376 {
1377 if (is_space (**text)) {
1378 (*text)++;
1379
1380 return 1;
1381 }
1382
1383 return 0;
1384 }
1385
1386 /*
1387 * returns 1 if text points to C-style comment start string "/ *",
1388 * returns 0 otherwise
1389 */
1390 static GLint
1391 is_comment_start (const GLubyte * text)
1392 {
1393 return text[0] == '/' && text[1] == '*';
1394 }
1395
1396 /*
1397 * advances text pointer to first character after C-style comment block - if any,
1398 * returns 1 if C-style comment block has been encountered and eaten,
1399 * returns 0 otherwise
1400 */
1401 static GLint
1402 eat_comment (const GLubyte ** text)
1403 {
1404 if (is_comment_start (*text)) {
1405 /* *text points to comment block - skip two characters to enter comment body */
1406 *text += 2;
1407 /* skip any character except consecutive '*' and '/' */
1408 while (!((*text)[0] == '*' && (*text)[1] == '/'))
1409 (*text)++;
1410 /* skip those two terminating characters */
1411 *text += 2;
1412
1413 return 1;
1414 }
1415
1416 return 0;
1417 }
1418
1419 /*
1420 * advances text pointer to first character that is neither space nor C-style comment block
1421 */
1422 static GLvoid
1423 eat_spaces (const GLubyte ** text)
1424 {
1425 while (eat_space (text) || eat_comment (text));
1426 }
1427
1428 /*
1429 * resizes string pointed by *ptr to successfully add character c to the end of the string,
1430 * returns 0 on success,
1431 * returns 1 otherwise
1432 */
1433 static GLint
1434 string_grow (GLubyte ** ptr, GLuint * len, GLubyte c)
1435 {
1436 /* reallocate the string in 16-length increments */
1437 if ((*len & 0x0F) == 0x0F || *ptr == NULL) {
1438 GLubyte *tmp = mem_realloc (*ptr, (*len) * sizeof (GLubyte),
1439 ((*len + 1 + 1 +
1440 0x0F) & ~0x0F) * sizeof (GLubyte));
1441 if (tmp == NULL)
1442 return 1;
1443
1444 *ptr = tmp;
1445 }
1446
1447 if (c) {
1448 /* append given character */
1449 (*ptr)[*len] = c;
1450 (*len)++;
1451 }
1452 (*ptr)[*len] = '\0';
1453
1454 return 0;
1455 }
1456
1457 /*
1458 * returns 1 if given character is valid identifier character a-z, A-Z, 0-9 or _
1459 * returns 0 otherwise
1460 */
1461 static GLint
1462 is_identifier (GLubyte c)
1463 {
1464 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
1465 (c >= '0' && c <= '9') || c == '_';
1466 }
1467
1468 /*
1469 * copies characters from *text to *id until non-identifier character is encountered,
1470 * assumes that *id points to NULL object - caller is responsible for later freeing the string,
1471 * text pointer is advanced to point past the copied identifier,
1472 * returns 0 if identifier was successfully copied,
1473 * returns 1 otherwise
1474 */
1475 static GLint
1476 get_identifier (const GLubyte ** text, GLubyte ** id)
1477 {
1478 const GLubyte *t = *text;
1479 GLubyte *p = NULL;
1480 GLuint len = 0;
1481
1482 if (string_grow (&p, &len, '\0'))
1483 return 1;
1484
1485 /* loop while next character in buffer is valid for identifiers */
1486 while (is_identifier (*t)) {
1487 if (string_grow (&p, &len, *t++)) {
1488 mem_free ((GLvoid **) & p);
1489 return 1;
1490 }
1491 }
1492
1493 *text = t;
1494 *id = p;
1495
1496 return 0;
1497 }
1498
1499 /*
1500 * returns 1 if given character is HEX digit 0-9, A-F or a-f,
1501 * returns 0 otherwise
1502 */
1503 static GLint
1504 is_hex (GLubyte c)
1505 {
1506 return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a'
1507 && c <= 'f');
1508 }
1509
1510 /*
1511 * returns value of passed character as if it was HEX digit
1512 */
1513 static GLuint
1514 hex2dec (GLubyte c)
1515 {
1516 if (c >= '0' && c <= '9')
1517 return c - '0';
1518 if (c >= 'A' && c <= 'F')
1519 return c - 'A' + 10;
1520 return c - 'a' + 10;
1521 }
1522
1523 /*
1524 * converts sequence of HEX digits pointed by *text until non-HEX digit is encountered,
1525 * advances text pointer past the converted sequence,
1526 * returns the converted value
1527 */
1528 static GLuint
1529 hex_convert (const GLubyte ** text)
1530 {
1531 GLuint value = 0;
1532
1533 while (is_hex (**text)) {
1534 value = value * 0x10 + hex2dec (**text);
1535 (*text)++;
1536 }
1537
1538 return value;
1539 }
1540
1541 /*
1542 * returns 1 if given character is OCT digit 0-7,
1543 * returns 0 otherwise
1544 */
1545 static GLint
1546 is_oct (GLubyte c)
1547 {
1548 return c >= '0' && c <= '7';
1549 }
1550
1551 /*
1552 * returns value of passed character as if it was OCT digit
1553 */
1554 static GLint
1555 oct2dec (GLubyte c)
1556 {
1557 return c - '0';
1558 }
1559
1560 static GLubyte
1561 get_escape_sequence (const GLubyte ** text)
1562 {
1563 GLint value = 0;
1564
1565 /* skip '\' character */
1566 (*text)++;
1567
1568 switch (*(*text)++) {
1569 case '\'':
1570 return '\'';
1571 case '"':
1572 return '\"';
1573 case '?':
1574 return '\?';
1575 case '\\':
1576 return '\\';
1577 case 'a':
1578 return '\a';
1579 case 'b':
1580 return '\b';
1581 case 'f':
1582 return '\f';
1583 case 'n':
1584 return '\n';
1585 case 'r':
1586 return '\r';
1587 case 't':
1588 return '\t';
1589 case 'v':
1590 return '\v';
1591 case 'x':
1592 return (GLubyte) hex_convert (text);
1593 }
1594
1595 (*text)--;
1596 if (is_oct (**text)) {
1597 value = oct2dec (*(*text)++);
1598 if (is_oct (**text)) {
1599 value = value * 010 + oct2dec (*(*text)++);
1600 if (is_oct (**text))
1601 value = value * 010 + oct2dec (*(*text)++);
1602 }
1603 }
1604
1605 return (GLubyte) value;
1606 }
1607
1608 /*
1609 * copies characters from *text to *str until " or ' character is encountered,
1610 * assumes that *str points to NULL object - caller is responsible for later freeing the string,
1611 * assumes that *text points to " or ' character that starts the string,
1612 * text pointer is advanced to point past the " or ' character,
1613 * returns 0 if string was successfully copied,
1614 * returns 1 otherwise
1615 */
1616 static GLint
1617 get_string (const GLubyte ** text, GLubyte ** str)
1618 {
1619 const GLubyte *t = *text;
1620 GLubyte *p = NULL;
1621 GLuint len = 0;
1622 GLubyte term_char;
1623
1624 if (string_grow (&p, &len, '\0'))
1625 return 1;
1626
1627 /* read " or ' character that starts the string */
1628 term_char = *t++;
1629 /* while next character is not the terminating character */
1630 while (*t && *t != term_char) {
1631 GLubyte c;
1632
1633 if (*t == '\\')
1634 c = get_escape_sequence (&t);
1635 else
1636 c = *t++;
1637
1638 if (string_grow (&p, &len, c)) {
1639 mem_free ((GLvoid **) & p);
1640 return 1;
1641 }
1642 }
1643
1644 /* skip " or ' character that ends the string */
1645 t++;
1646
1647 *text = t;
1648 *str = p;
1649 return 0;
1650 }
1651
1652 /*
1653 * gets emit code, the syntax is: ".emtcode" " " <symbol> " " ("0x" | "0X") <hex_value>
1654 * assumes that *text already points to <symbol>,
1655 * returns 0 if emit code is successfully read,
1656 * returns 1 otherwise
1657 */
1658 static GLint
1659 get_emtcode (const GLubyte ** text, map_byte ** ma)
1660 {
1661 const GLubyte *t = *text;
1662 map_byte *m = NULL;
1663
1664 map_byte_create (&m);
1665 if (m == NULL)
1666 return 1;
1667
1668 if (get_identifier (&t, &m->key)) {
1669 map_byte_destroy (&m);
1670 return 1;
1671 }
1672 eat_spaces (&t);
1673
1674 if (*t == '\'') {
1675 GLubyte *c;
1676
1677 if (get_string (&t, &c)) {
1678 map_byte_destroy (&m);
1679 return 1;
1680 }
1681
1682 m->data = (GLubyte) c[0];
1683 mem_free ((GLvoid **) & c);
1684 }
1685 else {
1686 /* skip HEX "0x" or "0X" prefix */
1687 t += 2;
1688 m->data = (GLubyte) hex_convert (&t);
1689 }
1690
1691 eat_spaces (&t);
1692
1693 *text = t;
1694 *ma = m;
1695 return 0;
1696 }
1697
1698 /*
1699 * returns 0 on success,
1700 * returns 1 otherwise
1701 */
1702 static GLint
1703 get_errtext (const GLubyte ** text, map_str ** ma)
1704 {
1705 const GLubyte *t = *text;
1706 map_str *m = NULL;
1707
1708 map_str_create (&m);
1709 if (m == NULL)
1710 return 1;
1711
1712 if (get_identifier (&t, &m->key)) {
1713 map_str_destroy (&m);
1714 return 1;
1715 }
1716 eat_spaces (&t);
1717
1718 if (get_string (&t, &m->data)) {
1719 map_str_destroy (&m);
1720 return 1;
1721 }
1722 eat_spaces (&t);
1723
1724 *text = t;
1725 *ma = m;
1726 return 0;
1727 }
1728
1729 /*
1730 * returns 0 on success,
1731 * returns 1 otherwise,
1732 */
1733 static GLint
1734 get_error (const GLubyte ** text, error ** er, map_str * maps)
1735 {
1736 const GLubyte *t = *text;
1737 GLubyte *temp = NULL;
1738
1739 if (*t != '.')
1740 return 0;
1741
1742 t++;
1743 if (get_identifier (&t, &temp))
1744 return 1;
1745 eat_spaces (&t);
1746
1747 if (_mesa_strcmp ("error", (char *) temp) != 0) {
1748 mem_free ((GLvoid **) & temp);
1749 return 0;
1750 }
1751
1752 mem_free ((GLvoid **) & temp);
1753
1754 error_create (er);
1755 if (*er == NULL)
1756 return 1;
1757
1758 if (*t == '\"') {
1759 if (get_string (&t, &(**er).m_text)) {
1760 error_destroy (er);
1761 return 1;
1762 }
1763 eat_spaces (&t);
1764 }
1765 else {
1766 if (get_identifier (&t, &temp)) {
1767 error_destroy (er);
1768 return 1;
1769 }
1770 eat_spaces (&t);
1771
1772 if (map_str_find (&maps, temp, &(**er).m_text)) {
1773 mem_free ((GLvoid **) & temp);
1774 error_destroy (er);
1775 return 1;
1776 }
1777
1778 mem_free ((GLvoid **) & temp);
1779 }
1780
1781 /* try to extract "token" from "...$token$..." */
1782 {
1783 char *processed = NULL;
1784 GLuint len = 0, i = 0;
1785
1786 if (string_grow ((GLubyte **) (&processed), &len, '\0')) {
1787 error_destroy (er);
1788 return 1;
1789 }
1790
1791 while (i < _mesa_strlen ((char *) ((**er).m_text))) {
1792 /* check if the dollar sign is repeated - if so skip it */
1793 if ((**er).m_text[i] == '$' && (**er).m_text[i + 1] == '$') {
1794 if (string_grow ((GLubyte **) (&processed), &len, '$')) {
1795 mem_free ((GLvoid **) & processed);
1796 error_destroy (er);
1797 return 1;
1798 }
1799
1800 i += 2;
1801 }
1802 else if ((**er).m_text[i] != '$') {
1803 if (string_grow ((GLubyte **) (&processed), &len, (**er).m_text[i])) {
1804 mem_free ((GLvoid **) & processed);
1805 error_destroy (er);
1806 return 1;
1807 }
1808
1809 i++;
1810 }
1811 else {
1812 if (string_grow ((GLubyte **) (&processed), &len, '$')) {
1813 mem_free ((GLvoid **) & processed);
1814 error_destroy (er);
1815 return 1;
1816 }
1817
1818 {
1819 /* length of token being extracted */
1820 GLuint tlen = 0;
1821
1822 if (string_grow (&(**er).m_token_name, &tlen, '\0')) {
1823 mem_free ((GLvoid **) & processed);
1824 error_destroy (er);
1825 return 1;
1826 }
1827
1828 /* skip the dollar sign */
1829 i++;
1830
1831 while ((**er).m_text[i] != '$') {
1832 if (string_grow
1833 (&(**er).m_token_name, &tlen, (**er).m_text[i])) {
1834 mem_free ((GLvoid **) & processed);
1835 error_destroy (er);
1836 return 1;
1837 }
1838
1839 i++;
1840 }
1841
1842 /* skip the dollar sign */
1843 i++;
1844 }
1845 }
1846 }
1847
1848 mem_free ((GLvoid **) & (**er).m_text);
1849 (**er).m_text = (GLubyte *) processed;
1850 }
1851
1852 *text = t;
1853 return 0;
1854 }
1855
1856 /*
1857 * returns 0 on success,
1858 * returns 1 otherwise,
1859 */
1860 static GLint
1861 get_emits (const GLubyte ** text, emit ** em, map_byte * mapb)
1862 {
1863 const GLubyte *t = *text;
1864 GLubyte *temp = NULL;
1865 emit *e = NULL;
1866
1867 if (*t != '.')
1868 return 0;
1869
1870 t++;
1871 if (get_identifier (&t, &temp))
1872 return 1;
1873 eat_spaces (&t);
1874
1875 /* .emit */
1876 if (_mesa_strcmp ("emit", (char *) temp) != 0) {
1877 mem_free ((GLvoid **) & temp);
1878 return 0;
1879 }
1880
1881 mem_free ((GLvoid **) & temp);
1882
1883 emit_create (&e);
1884 if (e == NULL)
1885 return 1;
1886
1887 /* 0xNN */
1888 if (*t == '0') {
1889 t += 2;
1890 e->m_byte = (GLubyte) hex_convert (&t);
1891
1892 e->m_emit_type = et_byte;
1893 }
1894 /* * */
1895 else if (*t == '*') {
1896 t++;
1897
1898 e->m_emit_type = et_stream;
1899 }
1900 /* $ */
1901 else if (*t == '$') {
1902 t++;
1903
1904 e->m_emit_type = et_position;
1905 }
1906 /* 'c' */
1907 else if (*t == '\'') {
1908 if (get_string (&t, &temp)) {
1909 emit_destroy (&e);
1910 return 1;
1911 }
1912 e->m_byte = (GLubyte) temp[0];
1913
1914 mem_free ((GLvoid **) & temp);
1915
1916 e->m_emit_type = et_byte;
1917 }
1918 else {
1919 if (get_identifier (&t, &temp)) {
1920 emit_destroy (&e);
1921 return 1;
1922 }
1923
1924 if (map_byte_find (&mapb, temp, &e->m_byte)) {
1925 mem_free ((GLvoid **) & temp);
1926 emit_destroy (&e);
1927 return 1;
1928 }
1929
1930 mem_free ((GLvoid **) & temp);
1931
1932 e->m_emit_type = et_byte;
1933 }
1934
1935 eat_spaces (&t);
1936
1937 if (get_emits (&t, &e->m_next, mapb)) {
1938 emit_destroy (&e);
1939 return 1;
1940 }
1941
1942 *text = t;
1943 *em = e;
1944 return 0;
1945 }
1946
1947 /*
1948 * returns 0 on success,
1949 * returns 1 otherwise,
1950 */
1951 static GLint
1952 get_spec (const GLubyte ** text, spec ** sp, map_str * maps, map_byte * mapb)
1953 {
1954 const GLubyte *t = *text;
1955 spec *s = NULL;
1956
1957 spec_create (&s);
1958 if (s == NULL)
1959 return 1;
1960
1961 if (*t == '\'') {
1962 GLubyte *temp = NULL;
1963
1964 if (get_string (&t, &temp)) {
1965 spec_destroy (&s);
1966 return 1;
1967 }
1968 eat_spaces (&t);
1969
1970 if (*t == '-') {
1971 GLubyte *temp2 = NULL;
1972
1973 /* skip the '-' character */
1974 t++;
1975 eat_spaces (&t);
1976
1977 if (get_string (&t, &temp2)) {
1978 mem_free ((GLvoid **) & temp);
1979 spec_destroy (&s);
1980 return 1;
1981 }
1982 eat_spaces (&t);
1983
1984 s->m_spec_type = st_byte_range;
1985 s->m_byte[0] = *temp;
1986 s->m_byte[1] = *temp2;
1987
1988 mem_free ((GLvoid **) & temp2);
1989 }
1990 else {
1991 s->m_spec_type = st_byte;
1992 *s->m_byte = *temp;
1993 }
1994
1995 mem_free ((GLvoid **) & temp);
1996 }
1997 else if (*t == '"') {
1998 if (get_string (&t, &s->m_string)) {
1999 spec_destroy (&s);
2000 return 1;
2001 }
2002 eat_spaces (&t);
2003
2004 s->m_spec_type = st_string;
2005 }
2006 else if (*t == '.') {
2007 GLubyte *keyword = NULL;
2008
2009 /* skip the dot */
2010 t++;
2011
2012 if (get_identifier (&t, &keyword)) {
2013 spec_destroy (&s);
2014 return 1;
2015 }
2016 eat_spaces (&t);
2017
2018 /* .true */
2019 if (_mesa_strcmp ("true", (char *) keyword) == 0) {
2020 s->m_spec_type = st_true;
2021 }
2022 /* .false */
2023 else if (_mesa_strcmp ("false", (char *) keyword) == 0) {
2024 s->m_spec_type = st_false;
2025 }
2026 /* .debug */
2027 else if (_mesa_strcmp ("debug", (char *) keyword) == 0) {
2028 s->m_spec_type = st_debug;
2029 }
2030 /* .loop */
2031 else if (_mesa_strcmp ("loop", (char *) keyword) == 0) {
2032 if (get_identifier (&t, &s->m_string)) {
2033 mem_free ((GLvoid **) & keyword);
2034 spec_destroy (&s);
2035 return 1;
2036 }
2037 eat_spaces (&t);
2038
2039 s->m_spec_type = st_identifier_loop;
2040 }
2041
2042 mem_free ((GLvoid **) & keyword);
2043 }
2044 else {
2045 if (get_identifier (&t, &s->m_string)) {
2046 spec_destroy (&s);
2047 return 1;
2048 }
2049 eat_spaces (&t);
2050
2051 s->m_spec_type = st_identifier;
2052 }
2053
2054 if (get_error (&t, &s->m_errtext, maps)) {
2055 spec_destroy (&s);
2056 return 1;
2057 }
2058
2059 if (get_emits (&t, &s->m_emits, mapb)) {
2060 spec_destroy (&s);
2061 return 1;
2062 }
2063
2064 *text = t;
2065 *sp = s;
2066 return 0;
2067 }
2068
2069 /*
2070 * returns 0 on success,
2071 * returns 1 otherwise,
2072 */
2073 static GLint
2074 get_definition (const GLubyte ** text, defntn ** de, map_str * maps,
2075 map_byte * mapb)
2076 {
2077 const GLubyte *t = *text;
2078 defntn *d = NULL;
2079
2080 defntn_create (&d);
2081 if (d == NULL)
2082 return 1;
2083
2084 if (get_spec (&t, &d->m_specs, maps, mapb)) {
2085 defntn_destroy (&d);
2086 return 1;
2087 }
2088
2089 while (*t != ';') {
2090 GLubyte *op = NULL;
2091 spec *sp = NULL;
2092
2093 /* skip the dot that precedes "and" or "or" */
2094 t++;
2095
2096 /* read "and" or "or" keyword */
2097 if (get_identifier (&t, &op)) {
2098 defntn_destroy (&d);
2099 return 1;
2100 }
2101 eat_spaces (&t);
2102
2103 if (d->m_oper == op_none) {
2104 /* .and */
2105 if (_mesa_strcmp ("and", (char *) op) == 0)
2106 d->m_oper = op_and;
2107 /* .or */
2108 else
2109 d->m_oper = op_or;
2110 }
2111
2112 mem_free ((GLvoid **) & op);
2113
2114 if (get_spec (&t, &sp, maps, mapb)) {
2115 defntn_destroy (&d);
2116 return 1;
2117 }
2118
2119 spec_append (&d->m_specs, &sp);
2120 }
2121
2122 /* skip the semicolon */
2123 t++;
2124 eat_spaces (&t);
2125
2126 *text = t;
2127 *de = d;
2128 return 0;
2129 }
2130
2131 /*
2132 * returns 0 on success,
2133 * returns 1 otherwise,
2134 */
2135 static GLint
2136 update_dependency (map_def * mapd, GLubyte * symbol, defntn ** def)
2137 {
2138 if (map_def_find (&mapd, symbol, def))
2139 return 1;
2140
2141 #ifndef NDEBUG
2142 (**def).m_referenced = 1;
2143 #endif
2144
2145 return 0;
2146 }
2147
2148 /*
2149 * returns 0 on success,
2150 * returns 1 otherwise,
2151 */
2152 static GLint
2153 update_dependencies (dict * di, map_def * mapd, GLubyte ** syntax_symbol,
2154 GLubyte ** string_symbol)
2155 {
2156 defntn *de = di->m_defntns;
2157
2158 if (update_dependency (mapd, *syntax_symbol, &di->m_syntax) ||
2159 (*string_symbol != NULL
2160 && update_dependency (mapd, *string_symbol, &di->m_string)))
2161 return 1;
2162
2163 mem_free ((GLvoid **) syntax_symbol);
2164 mem_free ((GLvoid **) string_symbol);
2165
2166 while (de) {
2167 spec *sp = de->m_specs;
2168
2169 while (sp) {
2170 if (sp->m_spec_type == st_identifier
2171 || sp->m_spec_type == st_identifier_loop) {
2172 if (update_dependency (mapd, sp->m_string, &sp->m_defntn))
2173 return 1;
2174
2175 mem_free ((GLvoid **) & sp->m_string);
2176 }
2177
2178 if (sp->m_errtext && sp->m_errtext->m_token_name) {
2179 if (update_dependency
2180 (mapd, sp->m_errtext->m_token_name, &sp->m_errtext->m_token))
2181 return 1;
2182
2183 mem_free ((GLvoid **) & sp->m_errtext->m_token_name);
2184 }
2185
2186 sp = sp->m_next;
2187 }
2188
2189 de = de->m_next;
2190 }
2191
2192 return 0;
2193 }
2194
2195 typedef enum match_result_
2196 {
2197 mr_not_matched, /* the examined string does not match */
2198 mr_matched, /* the examined string matches */
2199 mr_error_raised, /* mr_not_matched + error has been raised */
2200 mr_dont_emit, /* used by identifier loops only */
2201 mr_internal_error /* an internal error has occured such as out of memory */
2202 } match_result;
2203
2204 static match_result
2205 match (dict * di, const GLubyte * text, GLuint * index, defntn * de,
2206 barray ** ba, GLint filtering_string)
2207 {
2208 GLuint ind = *index;
2209 match_result status = mr_not_matched;
2210 spec *sp = de->m_specs;
2211
2212 /* for every specifier in the definition */
2213 while (sp) {
2214 GLuint i, len, save_ind = ind;
2215 barray *array = NULL;
2216
2217 switch (sp->m_spec_type) {
2218 case st_identifier:
2219 barray_create (&array);
2220 if (array == NULL)
2221 return mr_internal_error;
2222
2223 status =
2224 match (di, text, &ind, sp->m_defntn, &array, filtering_string);
2225 if (status == mr_internal_error) {
2226 barray_destroy (&array);
2227 return mr_internal_error;
2228 }
2229 break;
2230 case st_string:
2231 len = _mesa_strlen ((char *) (sp->m_string));
2232
2233 /* prefilter the stream */
2234 if (!filtering_string && di->m_string) {
2235 barray *ba;
2236 GLuint filter_index = 0;
2237 match_result result;
2238
2239 barray_create (&ba);
2240 if (ba == NULL)
2241 return mr_internal_error;
2242
2243 result =
2244 match (di, text + ind, &filter_index, di->m_string, &ba, 1);
2245
2246 if (result == mr_internal_error) {
2247 barray_destroy (&ba);
2248 return mr_internal_error;
2249 }
2250
2251 if (result != mr_matched) {
2252 barray_destroy (&ba);
2253 status = mr_not_matched;
2254 break;
2255 }
2256
2257 barray_destroy (&ba);
2258
2259 if (filter_index != len
2260 || _mesa_strncmp ((char *)sp->m_string, (char *)(text + ind), len)) {
2261 status = mr_not_matched;
2262 break;
2263 }
2264
2265 status = mr_matched;
2266 ind += len;
2267 }
2268 else {
2269 status = mr_matched;
2270 for (i = 0; status == mr_matched && i < len; i++)
2271 if (text[ind + i] != sp->m_string[i])
2272 status = mr_not_matched;
2273 if (status == mr_matched)
2274 ind += len;
2275 }
2276 break;
2277 case st_byte:
2278 status = text[ind] == *sp->m_byte ? mr_matched : mr_not_matched;
2279 if (status == mr_matched)
2280 ind++;
2281 break;
2282 case st_byte_range:
2283 status = (text[ind] >= sp->m_byte[0]
2284 && text[ind] <=
2285 sp->m_byte[1]) ? mr_matched : mr_not_matched;
2286 if (status == mr_matched)
2287 ind++;
2288 break;
2289 case st_true:
2290 status = mr_matched;
2291 break;
2292 case st_false:
2293 status = mr_not_matched;
2294 break;
2295 case st_debug:
2296 status = mr_matched;
2297 break;
2298 case st_identifier_loop:
2299 barray_create (&array);
2300 if (array == NULL)
2301 return mr_internal_error;
2302
2303 status = mr_dont_emit;
2304 for (;;) {
2305 match_result result;
2306
2307 save_ind = ind;
2308 result =
2309 match (di, text, &ind, sp->m_defntn, &array,
2310 filtering_string);
2311
2312 if (result == mr_error_raised) {
2313 status = result;
2314 break;
2315 }
2316 else if (result == mr_matched) {
2317 if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind)
2318 || barray_append (ba, &array)) {
2319 barray_destroy (&array);
2320 return mr_internal_error;
2321 }
2322 barray_destroy (&array);
2323 barray_create (&array);
2324 if (array == NULL)
2325 return mr_internal_error;
2326 }
2327 else if (result == mr_internal_error) {
2328 barray_destroy (&array);
2329 return mr_internal_error;
2330 }
2331 else
2332 break;
2333 }
2334 break;
2335 };
2336
2337 if (status == mr_error_raised) {
2338 barray_destroy (&array);
2339
2340 return mr_error_raised;
2341 }
2342
2343 if (de->m_oper == op_and && status != mr_matched
2344 && status != mr_dont_emit) {
2345 barray_destroy (&array);
2346
2347 if (sp->m_errtext) {
2348 set_last_error (sp->m_errtext->m_text,
2349 error_get_token (sp->m_errtext, di, text, ind),
2350 ind);
2351
2352 return mr_error_raised;
2353 }
2354
2355 return mr_not_matched;
2356 }
2357
2358 if (status == mr_matched) {
2359 if (sp->m_emits)
2360 if (barray_push (ba, sp->m_emits, text[ind - 1], save_ind)) {
2361 barray_destroy (&array);
2362 return mr_internal_error;
2363 }
2364
2365 if (array)
2366 if (barray_append (ba, &array)) {
2367 barray_destroy (&array);
2368 return mr_internal_error;
2369 }
2370 }
2371
2372 barray_destroy (&array);
2373
2374 if (de->m_oper == op_or
2375 && (status == mr_matched || status == mr_dont_emit)) {
2376 *index = ind;
2377 return mr_matched;
2378 }
2379
2380 sp = sp->m_next;
2381 }
2382
2383 if (de->m_oper == op_and
2384 && (status == mr_matched || status == mr_dont_emit)) {
2385 *index = ind;
2386 return mr_matched;
2387 }
2388
2389 return mr_not_matched;
2390 }
2391
2392 static GLubyte *
2393 error_get_token (error * er, dict * di, const GLubyte * text, unsigned int ind)
2394 {
2395 GLubyte *str = NULL;
2396
2397 if (er->m_token) {
2398 barray *ba;
2399 GLuint filter_index = 0;
2400
2401 barray_create (&ba);
2402 if (ba != NULL) {
2403 if (match (di, text + ind, &filter_index, er->m_token, &ba, 0) ==
2404 mr_matched && filter_index) {
2405 str = mem_alloc (filter_index + 1);
2406 if (str != NULL) {
2407 _mesa_strncpy ((char *) str, (char *) (text + ind),
2408 filter_index);
2409 str[filter_index] = '\0';
2410 }
2411 }
2412 barray_destroy (&ba);
2413 }
2414 }
2415
2416 return str;
2417 }
2418
2419 typedef struct grammar_load_state_
2420 {
2421 dict *di;
2422 GLubyte *syntax_symbol;
2423 GLubyte *string_symbol;
2424 map_str *maps;
2425 map_byte *mapb;
2426 map_def *mapd;
2427 } grammar_load_state;
2428
2429
2430 static GLvoid
2431 grammar_load_state_create (grammar_load_state ** gr)
2432 {
2433 *gr = mem_alloc (sizeof (grammar_load_state));
2434 if (*gr) {
2435 (**gr).di = NULL;
2436 (**gr).syntax_symbol = NULL;
2437 (**gr).string_symbol = NULL;
2438 (**gr).maps = NULL;
2439 (**gr).mapb = NULL;
2440 (**gr).mapd = NULL;
2441 }
2442 }
2443
2444 static GLvoid
2445 grammar_load_state_destroy (grammar_load_state ** gr)
2446 {
2447 if (*gr) {
2448 dict_destroy (&(**gr).di);
2449 mem_free ((GLvoid **) &(**gr).syntax_symbol);
2450 mem_free ((GLvoid **) &(**gr).string_symbol);
2451 map_str_destroy (&(**gr).maps);
2452 map_byte_destroy (&(**gr).mapb);
2453 map_def_destroy (&(**gr).mapd);
2454 mem_free ((GLvoid **) gr);
2455 }
2456 }
2457
2458 /*
2459 * the API
2460 */
2461
2462 /*
2463 * loads grammar script from null-terminated ASCII text
2464 * returns the grammar object
2465 * returns NULL if an error occurs (call grammar_get_last_error to retrieve the error text)
2466 */
2467
2468 static dict *
2469 grammar_load_from_text (const GLubyte * text)
2470 {
2471 dict *d = NULL;
2472 grammar_load_state *g = NULL;
2473
2474 clear_last_error ();
2475
2476 grammar_load_state_create (&g);
2477 if (g == NULL)
2478 return NULL;
2479
2480 dict_create (&g->di);
2481 if (g->di == NULL) {
2482 grammar_load_state_destroy (&g);
2483 return NULL;
2484 }
2485
2486 eat_spaces (&text);
2487
2488 /* skip ".syntax" keyword */
2489 text += 7;
2490 eat_spaces (&text);
2491
2492 /* retrieve root symbol */
2493 if (get_identifier (&text, &g->syntax_symbol)) {
2494 grammar_load_state_destroy (&g);
2495 return NULL;
2496 }
2497 eat_spaces (&text);
2498
2499 /* skip semicolon */
2500 text++;
2501 eat_spaces (&text);
2502
2503 while (*text) {
2504 GLubyte *symbol = NULL;
2505 GLint is_dot = *text == '.';
2506
2507 if (is_dot)
2508 text++;
2509
2510 if (get_identifier (&text, &symbol)) {
2511 grammar_load_state_destroy (&g);
2512 return NULL;
2513 }
2514 eat_spaces (&text);
2515
2516 /* .emtcode */
2517 if (is_dot && _mesa_strcmp ((char *) symbol, "emtcode") == 0) {
2518 map_byte *ma = NULL;
2519
2520 mem_free ((void **) &symbol);
2521
2522 if (get_emtcode (&text, &ma)) {
2523 grammar_load_state_destroy (&g);
2524 return NULL;
2525 }
2526
2527 map_byte_append (&g->mapb, &ma);
2528 }
2529 /* .errtext */
2530 else if (is_dot && _mesa_strcmp ((char *) symbol, "errtext") == 0) {
2531 map_str *ma = NULL;
2532
2533 mem_free ((GLvoid **) &symbol);
2534
2535 if (get_errtext (&text, &ma)) {
2536 grammar_load_state_destroy (&g);
2537 return NULL;
2538 }
2539
2540 map_str_append (&g->maps, &ma);
2541 }
2542 /* .string */
2543 else if (is_dot && _mesa_strcmp ((char *) symbol, "string") == 0) {
2544 mem_free ((GLvoid **) (&symbol));
2545
2546 if (g->di->m_string != NULL) {
2547 grammar_load_state_destroy (&g);
2548 return NULL;
2549 }
2550
2551 if (get_identifier (&text, &g->string_symbol)) {
2552 grammar_load_state_destroy (&g);
2553 return NULL;
2554 }
2555
2556 /* skip semicolon */
2557 eat_spaces (&text);
2558 text++;
2559 eat_spaces (&text);
2560 }
2561 else {
2562 defntn *de = NULL;
2563 map_def *ma = NULL;
2564
2565 if (get_definition (&text, &de, g->maps, g->mapb)) {
2566 grammar_load_state_destroy (&g);
2567 return NULL;
2568 }
2569
2570 defntn_append (&g->di->m_defntns, &de);
2571
2572 /* if definition consist of only one specifier, give it an ".and" operator */
2573 if (de->m_oper == op_none)
2574 de->m_oper = op_and;
2575
2576 map_def_create (&ma);
2577 if (ma == NULL) {
2578 grammar_load_state_destroy (&g);
2579 return NULL;
2580 }
2581
2582 ma->key = symbol;
2583 ma->data = de;
2584 map_def_append (&g->mapd, &ma);
2585 }
2586 }
2587
2588 if (update_dependencies
2589 (g->di, g->mapd, &g->syntax_symbol, &g->string_symbol)) {
2590 grammar_load_state_destroy (&g);
2591 return NULL;
2592 }
2593
2594 d = g->di;
2595 g->di = NULL;
2596
2597 grammar_load_state_destroy (&g);
2598
2599 return d;
2600 }
2601
2602 /**
2603 * checks if a null-terminated text matches given grammar
2604 * returns 0 on error (call grammar_get_last_error to retrieve the error text)
2605 * returns 1 on success, the prod points to newly allocated buffer with
2606 * production and size is filled with the production size
2607 *
2608 * \param id - The grammar returned from grammar_load_from_text()
2609 * \param text - The program string
2610 * \param production - The return parameter for the binary array holding the
2611 * parsed results
2612 * \param size - The return parameter for the size of production
2613 *
2614 * \return 1 on sucess, 0 on parser error
2615 */
2616 static GLint
2617 grammar_check (dict * di, const GLubyte * text, GLubyte ** production,
2618 GLuint *size)
2619 {
2620 barray *ba = NULL;
2621 GLuint index = 0;
2622
2623 clear_last_error ();
2624
2625 barray_create (&ba);
2626 if (ba == NULL)
2627 return 0;
2628
2629 *production = NULL;
2630 *size = 0;
2631
2632 if (match (di, text, &index, di->m_syntax, &ba, 0) != mr_matched) {
2633 barray_destroy (&ba);
2634 return 0;
2635 }
2636
2637 *production = mem_alloc (ba->len * sizeof (GLubyte));
2638 if (*production == NULL) {
2639 barray_destroy (&ba);
2640 return 0;
2641 }
2642
2643 memcpy (*production, ba->data, ba->len * sizeof (GLubyte));
2644 *size = ba->len;
2645 barray_destroy (&ba);
2646
2647 return 1;
2648 }
2649
2650 static GLvoid
2651 grammar_get_last_error (GLubyte * text, GLint size, GLint *pos)
2652 {
2653 GLint len = 0, dots_made = 0;
2654 const GLubyte *p = error_message;
2655
2656 *text = '\0';
2657 #define APPEND_CHARACTER(x) if (dots_made == 0) {\
2658 if (len < size - 1) {\
2659 text[len++] = (x); text[len] = '\0';\
2660 } else {\
2661 GLint i;\
2662 for (i = 0; i < 3; i++)\
2663 if (--len >= 0)\
2664 text[len] = '.';\
2665 dots_made = 1;\
2666 }\
2667 }
2668
2669 if (p) {
2670 while (*p) {
2671 if (*p == '$') {
2672 const GLubyte *r = error_param;
2673
2674 while (*r) {
2675 APPEND_CHARACTER (*r)
2676 r++;
2677 }
2678
2679 p++;
2680 }
2681 else {
2682 APPEND_CHARACTER (*p)
2683 p++;
2684 }
2685 }
2686 }
2687 *pos = error_position;
2688 }
2689
2690 /*-----------------------------------------------------------------------
2691 * From here on down is the semantic checking portion
2692 *
2693 */
2694
2695 /**
2696 * Variable Table Handling functions
2697 */
2698 typedef enum
2699 {
2700 vt_none,
2701 vt_address,
2702 vt_attrib,
2703 vt_param,
2704 vt_temp,
2705 vt_output,
2706 vt_alias
2707 } var_type;
2708
2709
2710 /*
2711 * Setting an explicit field for each of the binding properties is a bit wasteful
2712 * of space, but it should be much more clear when reading later on..
2713 */
2714 struct var_cache
2715 {
2716 GLubyte *name;
2717 var_type type;
2718 GLuint address_binding; /* The index of the address register we should
2719 * be using */
2720 GLuint attrib_binding; /* For type vt_attrib, see nvfragprog.h for values */
2721 GLuint attrib_binding_idx; /* The index into the attrib register file corresponding
2722 * to the state in attrib_binding */
2723 GLuint attrib_is_generic; /* If the attrib was specified through a generic
2724 * vertex attrib */
2725 GLuint temp_binding; /* The index of the temp register we are to use */
2726 GLuint output_binding; /* For type vt_output, see nvfragprog.h for values */
2727 GLuint output_binding_idx; /* This is the index into the result register file
2728 * corresponding to the bound result state */
2729 struct var_cache *alias_binding; /* For type vt_alias, points to the var_cache entry
2730 * that this is aliased to */
2731 GLuint param_binding_type; /* {PROGRAM_STATE_VAR, PROGRAM_LOCAL_PARAM,
2732 * PROGRAM_ENV_PARAM} */
2733 GLuint param_binding_begin; /* This is the offset into the program_parameter_list where
2734 * the tokens representing our bound state (or constants)
2735 * start */
2736 GLuint param_binding_length; /* This is how many entries in the the program_parameter_list
2737 * we take up with our state tokens or constants. Note that
2738 * this is _not_ the same as the number of param registers
2739 * we eventually use */
2740 struct var_cache *next;
2741 };
2742
2743 static GLvoid
2744 var_cache_create (struct var_cache **va)
2745 {
2746 *va = _mesa_malloc (sizeof (struct var_cache));
2747 if (*va) {
2748 (**va).name = NULL;
2749 (**va).type = vt_none;
2750 (**va).attrib_binding = -1;
2751 (**va).attrib_is_generic = 0;
2752 (**va).temp_binding = -1;
2753 (**va).output_binding = -1;
2754 (**va).output_binding_idx = -1;
2755 (**va).param_binding_type = -1;
2756 (**va).param_binding_begin = -1;
2757 (**va).param_binding_length = -1;
2758 (**va).alias_binding = NULL;
2759 (**va).next = NULL;
2760 }
2761 }
2762
2763 static GLvoid
2764 var_cache_destroy (struct var_cache **va)
2765 {
2766 if (*va) {
2767 var_cache_destroy (&(**va).next);
2768 _mesa_free (*va);
2769 *va = NULL;
2770 }
2771 }
2772
2773 static GLvoid
2774 var_cache_append (struct var_cache **va, struct var_cache *nv)
2775 {
2776 if (*va)
2777 var_cache_append (&(**va).next, nv);
2778 else
2779 *va = nv;
2780 }
2781
2782 static struct var_cache *
2783 var_cache_find (struct var_cache *va, GLubyte * name)
2784 {
2785 struct var_cache *first = va;
2786
2787 while (va) {
2788 if (!strcmp ( (const char*) name, (const char*) va->name)) {
2789 if (va->type == vt_alias)
2790 return var_cache_find (first, va->name);
2791 return va;
2792 }
2793
2794 va = va->next;
2795 }
2796
2797 return NULL;
2798 }
2799
2800 /**
2801 * constructs an integer from 4 GLubytes in LE format
2802 */
2803 static GLuint
2804 parse_position (GLubyte ** inst)
2805 {
2806 GLuint value;
2807
2808 value = (GLuint) (*(*inst)++);
2809 value += (GLuint) (*(*inst)++) * 0x100;
2810 value += (GLuint) (*(*inst)++) * 0x10000;
2811 value += (GLuint) (*(*inst)++) * 0x1000000;
2812
2813 return value;
2814 }
2815
2816 /**
2817 * This will, given a string, lookup the string as a variable name in the
2818 * var cache. If the name is found, the var cache node corresponding to the
2819 * var name is returned. If it is not found, a new entry is allocated
2820 *
2821 * \param I Points into the binary array where the string identifier begins
2822 * \param found 1 if the string was found in the var_cache, 0 if it was allocated
2823 * \return The location on the var_cache corresponding the the string starting at I
2824 */
2825 static struct var_cache *
2826 parse_string (GLubyte ** inst, struct var_cache **vc_head,
2827 struct arb_program *Program, GLuint * found)
2828 {
2829 GLubyte *i = *inst;
2830 struct var_cache *va = NULL;
2831
2832 *inst += _mesa_strlen ((char *) i) + 1;
2833
2834 va = var_cache_find (*vc_head, i);
2835
2836 if (va) {
2837 *found = 1;
2838 return va;
2839 }
2840
2841 *found = 0;
2842 var_cache_create (&va);
2843 va->name = i;
2844
2845 var_cache_append (vc_head, va);
2846
2847 return va;
2848 }
2849
2850 static char *
2851 parse_string_without_adding (GLubyte ** inst, struct arb_program *Program)
2852 {
2853 GLubyte *i = *inst;
2854
2855 *inst += _mesa_strlen ((char *) i) + 1;
2856
2857 return (char *) i;
2858 }
2859
2860 /**
2861 * \return 0 if sign is plus, 1 if sign is minus
2862 */
2863 static GLuint
2864 parse_sign (GLubyte ** inst)
2865 {
2866 /*return *(*inst)++ != '+'; */
2867
2868 if (**inst == '-') {
2869 *(*inst)++;
2870 return 1;
2871 }
2872 else if (**inst == '+') {
2873 *(*inst)++;
2874 return 0;
2875 }
2876
2877 return 0;
2878 }
2879
2880 /**
2881 * parses and returns signed integer
2882 */
2883 static GLint
2884 parse_integer (GLubyte ** inst, struct arb_program *Program)
2885 {
2886 GLint sign;
2887 GLint value;
2888
2889 /* check if *inst points to '+' or '-'
2890 * if yes, grab the sign and increment *inst
2891 */
2892 sign = parse_sign (inst);
2893
2894 /* now check if *inst points to 0
2895 * if yes, increment the *inst and return the default value
2896 */
2897 if (**inst == 0) {
2898 *(*inst)++;
2899 return 0;
2900 }
2901
2902 /* parse the integer as you normally would do it */
2903 value = _mesa_atoi (parse_string_without_adding (inst, Program));
2904
2905 /* now, after terminating 0 there is a position
2906 * to parse it - parse_position()
2907 */
2908 Program->Position = parse_position (inst);
2909
2910 if (sign)
2911 value *= -1;
2912
2913 return value;
2914 }
2915
2916 /**
2917 */
2918 static GLfloat
2919 parse_float (GLubyte ** inst, struct arb_program *Program)
2920 {
2921 GLint tmp[5], denom;
2922 GLfloat value = 0;
2923
2924 #if 0
2925 tmp[0] = parse_sign (inst); /* This is the sign of the number + - >0, - -> 1 */
2926 #endif
2927 tmp[1] = parse_integer (inst, Program); /* This is the integer portion of the number */
2928 tmp[2] = parse_integer (inst, Program); /* This is the fractional portion of the number */
2929 tmp[3] = parse_sign (inst); /* This is the sign of the exponent */
2930 tmp[4] = parse_integer (inst, Program); /* This is the exponent */
2931
2932 value = (GLfloat) tmp[1];
2933 denom = 1;
2934 while (denom < tmp[2])
2935 denom *= 10;
2936 value += (GLfloat) tmp[2] / (GLfloat) denom;
2937 #if 0
2938 if (tmp[0])
2939 value *= -1;
2940 #endif
2941 value *= _mesa_pow (10, (GLfloat) tmp[3] * (GLfloat) tmp[4]);
2942
2943 return value;
2944 }
2945
2946 /**
2947 */
2948 static GLfloat
2949 parse_signed_float (GLubyte ** inst, struct arb_program *Program)
2950 {
2951 GLint negate;
2952 GLfloat value;
2953
2954 negate = parse_sign (inst);
2955
2956 value = parse_float (inst, Program);
2957
2958 if (negate)
2959 value *= -1;
2960
2961 return value;
2962 }
2963
2964 /**
2965 * This picks out a constant value from the parsed array. The constant vector is r
2966 * returned in the *values array, which should be of length 4.
2967 *
2968 * \param values - The 4 component vector with the constant value in it
2969 */
2970 static GLvoid
2971 parse_constant (GLubyte ** inst, GLfloat *values, struct arb_program *Program,
2972 GLboolean use)
2973 {
2974 GLuint components, i;
2975
2976
2977 switch (*(*inst)++) {
2978 case CONSTANT_SCALAR:
2979 if (use == GL_TRUE) {
2980 values[0] =
2981 values[1] =
2982 values[2] = values[3] = parse_float (inst, Program);
2983 }
2984 else {
2985 values[0] =
2986 values[1] =
2987 values[2] = values[3] = parse_signed_float (inst, Program);
2988 }
2989
2990 break;
2991 case CONSTANT_VECTOR:
2992 values[0] = values[1] = values[2] = 0;
2993 values[3] = 1;
2994 components = *(*inst)++;
2995 for (i = 0; i < components; i++) {
2996 values[i] = parse_signed_float (inst, Program);
2997 }
2998 break;
2999 }
3000 }
3001
3002
3003 /**
3004 * \param color 0 if color type is primary, 1 if color type is secondary
3005 * \return 0 on sucess, 1 on error
3006 */
3007 static GLuint
3008 parse_color_type (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
3009 GLint * color)
3010 {
3011 *color = *(*inst)++ != COLOR_PRIMARY;
3012 return 0;
3013 }
3014
3015 /**
3016 * Get an integer corresponding to a generic vertex attribute.
3017 *
3018 * \return 0 on sucess, 1 on error
3019 */
3020 static GLuint
3021 parse_generic_attrib_num(GLcontext *ctx, GLubyte ** inst,
3022 struct arb_program *Program, GLuint *attrib)
3023 {
3024 *attrib = parse_integer(inst, Program);
3025
3026 if ((*attrib < 0) || (*attrib > MAX_VERTEX_PROGRAM_ATTRIBS))
3027 {
3028 _mesa_set_program_error (ctx, Program->Position,
3029 "Invalid generic vertex attribute index");
3030 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid generic vertex attribute index");
3031
3032 return 1;
3033 }
3034
3035 return 0;
3036 }
3037
3038
3039 /**
3040 * \param coord The texture unit index
3041 * \return 0 on sucess, 1 on error
3042 */
3043 static GLuint
3044 parse_texcoord_num (GLcontext * ctx, GLubyte ** inst,
3045 struct arb_program *Program, GLuint * coord)
3046 {
3047 *coord = parse_integer (inst, Program);
3048
3049 if ((*coord < 0) || (*coord >= ctx->Const.MaxTextureUnits)) {
3050 _mesa_set_program_error (ctx, Program->Position,
3051 "Invalid texture unit index");
3052 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid texture unit index");
3053 return 1;
3054 }
3055
3056 Program->TexturesUsed[*coord] = 1;
3057 return 0;
3058 }
3059
3060 /**
3061 * \param coord The weight index
3062 * \return 0 on sucess, 1 on error
3063 */
3064 static GLuint
3065 parse_weight_num (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
3066 GLint * coord)
3067 {
3068 *coord = parse_integer (inst, Program);
3069
3070 if ((*coord < 0) || (*coord >= 1)) {
3071 _mesa_set_program_error (ctx, Program->Position,
3072 "Invalid weight index");
3073 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid weight index");
3074 return 1;
3075 }
3076
3077 return 0;
3078 }
3079
3080 /**
3081 * \param coord The clip plane index
3082 * \return 0 on sucess, 1 on error
3083 */
3084 static GLuint
3085 parse_clipplane_num (GLcontext * ctx, GLubyte ** inst,
3086 struct arb_program *Program, GLint * coord)
3087 {
3088 *coord = parse_integer (inst, Program);
3089
3090 if ((*coord < 0) || (*coord >= ctx->Const.MaxClipPlanes)) {
3091 _mesa_set_program_error (ctx, Program->Position,
3092 "Invalid clip plane index");
3093 _mesa_error (ctx, GL_INVALID_OPERATION, "Invalid clip plane index");
3094 return 1;
3095 }
3096
3097 return 0;
3098 }
3099
3100
3101 /**
3102 * \return 0 on front face, 1 on back face
3103 */
3104 static GLuint
3105 parse_face_type (GLubyte ** inst)
3106 {
3107 switch (*(*inst)++) {
3108 case FACE_FRONT:
3109 return 0;
3110
3111 case FACE_BACK:
3112 return 1;
3113 }
3114 return 0;
3115 }
3116
3117
3118 /**
3119 * Given a matrix and a modifier token on the binary array, return tokens
3120 * that _mesa_fetch_state() [program.c] can understand.
3121 *
3122 * \param matrix - the matrix we are talking about
3123 * \param matrix_idx - the index of the matrix we have (for texture & program matricies)
3124 * \param matrix_modifier - the matrix modifier (trans, inv, etc)
3125 * \return 0 on sucess, 1 on failure
3126 */
3127 static GLuint
3128 parse_matrix (GLcontext * ctx, GLubyte ** inst, struct arb_program *Program,
3129 GLint * matrix, GLint * matrix_idx, GLint * matrix_modifier)
3130 {
3131 GLubyte mat = *(*inst)++;
3132
3133 *matrix_idx = 0;
3134
3135 switch (mat) {
3136 case MATRIX_MODELVIEW:
3137 *matrix = STATE_MODELVIEW;
3138 *matrix_idx = parse_integer (inst, Program);
3139 /* XXX: if (*matrix_idx >= ctx->Const. */
3140 break;
3141
3142 case MATRIX_PROJECTION:
3143 *matrix = STATE_PROJECTION;
3144 break;
3145
3146 case MATRIX_MVP:
3147 *matrix = STATE_MVP;
3148 break;
3149
3150 case MATRIX_TEXTURE:
3151 *matrix = STATE_TEXTURE;
3152 *matrix_idx = parse_integer (inst, Program);
3153 if (*matrix_idx >= ctx->Const.MaxTextureUnits) {
3154 _mesa_set_program_error (ctx, Program->Position,
3155 "Invalid Texture Unit");
3156 _mesa_error (ctx, GL_INVALID_OPERATION,
3157 "Invalid Texture Unit: %d", *matrix_idx);
3158 return 1;
3159 }
3160 break;
3161
3162 /* XXX: How should we handle the palette matrix? */
3163 case MATRIX_PALETTE:
3164 *matrix_idx = parse_integer (inst, Program);
3165 break;
3166
3167 case MATRIX_PROGRAM:
3168 *matrix = STATE_PROGRAM;
3169 *matrix_idx = parse_integer (inst, Program);
3170 if (*matrix_idx >= ctx->Const.MaxProgramMatrices) {
3171 _mesa_set_program_error (ctx, Program->Position,
3172 "Invalid Program Matrix");
3173 _mesa_error (ctx, GL_INVALID_OPERATION,
3174 "Invalid Program Matrix: %d", *matrix_idx);
3175 return 1;
3176 }
3177 break;
3178 }
3179
3180 switch (*(*inst)++) {
3181 case MATRIX_MODIFIER_IDENTITY:
3182 *matrix_modifier = 0;
3183 break;
3184 case MATRIX_MODIFIER_INVERSE:
3185 *matrix_modifier = STATE_MATRIX_INVERSE;
3186 break;
3187 case MATRIX_MODIFIER_TRANSPOSE:
3188 *matrix_modifier = STATE_MATRIX_TRANSPOSE;
3189 break;
3190 case MATRIX_MODIFIER_INVTRANS:
3191 *matrix_modifier = STATE_MATRIX_INVTRANS;
3192 break;
3193 }
3194
3195 return 0;
3196 }
3197
3198
3199 /**
3200 * This parses a state string (rather, the binary version of it) into
3201 * a 6-token sequence as described in _mesa_fetch_state() [program.c]
3202 *
3203 * \param inst - the start in the binary arry to start working from
3204 * \param state_tokens - the storage for the 6-token state description
3205 * \return - 0 on sucess, 1 on error
3206 */
3207 static GLuint
3208 parse_state_single_item (GLcontext * ctx, GLubyte ** inst,
3209 struct arb_program *Program, GLint * state_tokens)
3210 {
3211 switch (*(*inst)++) {
3212 case STATE_MATERIAL_PARSER:
3213 state_tokens[0] = STATE_MATERIAL;
3214 state_tokens[1] = parse_face_type (inst);
3215 switch (*(*inst)++) {
3216 case MATERIAL_AMBIENT:
3217 state_tokens[2] = STATE_AMBIENT;
3218 break;
3219 case MATERIAL_DIFFUSE:
3220 state_tokens[2] = STATE_DIFFUSE;
3221 break;
3222 case MATERIAL_SPECULAR:
3223 state_tokens[2] = STATE_SPECULAR;
3224 break;
3225 case MATERIAL_EMISSION:
3226 state_tokens[2] = STATE_EMISSION;
3227 break;
3228 case MATERIAL_SHININESS:
3229 state_tokens[2] = STATE_SHININESS;
3230 break;
3231 }
3232 break;
3233
3234 case STATE_LIGHT_PARSER:
3235 state_tokens[0] = STATE_LIGHT;
3236 state_tokens[1] = parse_integer (inst, Program);
3237
3238 /* Check the value of state_tokens[1] against the # of lights */
3239 if (state_tokens[1] >= ctx->Const.MaxLights) {
3240 _mesa_set_program_error (ctx, Program->Position,
3241 "Invalid Light Number");
3242 _mesa_error (ctx, GL_INVALID_OPERATION,
3243 "Invalid Light Number: %d", state_tokens[1]);
3244 return 1;
3245 }
3246
3247 switch (*(*inst)++) {
3248 case LIGHT_AMBIENT:
3249 state_tokens[2] = STATE_AMBIENT;
3250 break;
3251 case LIGHT_DIFFUSE:
3252 state_tokens[2] = STATE_DIFFUSE;
3253 break;
3254 case LIGHT_SPECULAR:
3255 state_tokens[2] = STATE_SPECULAR;
3256 break;
3257 case LIGHT_POSITION:
3258 state_tokens[2] = STATE_POSITION;
3259 break;
3260 case LIGHT_ATTENUATION:
3261 state_tokens[2] = STATE_ATTENUATION;
3262 break;
3263 case LIGHT_HALF:
3264 state_tokens[2] = STATE_HALF;
3265 break;
3266 case LIGHT_SPOT_DIRECTION:
3267 state_tokens[2] = STATE_SPOT_DIRECTION;
3268 break;
3269 }
3270 break;
3271
3272 case STATE_LIGHT_MODEL:
3273 switch (*(*inst)++) {
3274 case LIGHT_MODEL_AMBIENT:
3275 state_tokens[0] = STATE_LIGHTMODEL_AMBIENT;
3276 break;
3277 case LIGHT_MODEL_SCENECOLOR:
3278 state_tokens[0] = STATE_LIGHTMODEL_SCENECOLOR;
3279 state_tokens[1] = parse_face_type (inst);
3280 break;
3281 }
3282 break;
3283
3284 case STATE_LIGHT_PROD:
3285 state_tokens[0] = STATE_LIGHTPROD;
3286 state_tokens[1] = parse_integer (inst, Program);
3287
3288 /* Check the value of state_tokens[1] against the # of lights */
3289 if (state_tokens[1] >= ctx->Const.MaxLights) {
3290 _mesa_set_program_error (ctx, Program->Position,
3291 "Invalid Light Number");
3292 _mesa_error (ctx, GL_INVALID_OPERATION,
3293 "Invalid Light Number: %d", state_tokens[1]);
3294 return 1;
3295 }
3296
3297 state_tokens[2] = parse_face_type (inst);
3298 switch (*(*inst)++) {
3299 case LIGHT_PROD_AMBIENT:
3300 state_tokens[3] = STATE_AMBIENT;
3301 break;
3302 case LIGHT_PROD_DIFFUSE:
3303 state_tokens[3] = STATE_DIFFUSE;
3304 break;
3305 case LIGHT_PROD_SPECULAR:
3306 state_tokens[3] = STATE_SPECULAR;
3307 break;
3308 }
3309 break;
3310
3311
3312 case STATE_FOG:
3313 switch (*(*inst)++) {
3314 case FOG_COLOR:
3315 state_tokens[0] = STATE_FOG_COLOR;
3316 break;
3317 case FOG_PARAMS:
3318 state_tokens[0] = STATE_FOG_PARAMS;
3319 break;
3320 }
3321 break;
3322
3323 /* STATE_TEX_ENV == STATE_TEX_GEN */
3324 case STATE_TEX_ENV:
3325 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3326 state_tokens[1] = parse_integer (inst, Program);
3327 switch (*(*inst)++) {
3328 case TEX_ENV_COLOR:
3329 state_tokens[0] = STATE_TEXENV_COLOR;
3330 break;
3331 }
3332 }
3333 /* For vertex programs, this case is STATE_TEX_GEN */
3334 else {
3335 GLuint type, coord;
3336
3337 state_tokens[0] = STATE_TEXGEN;
3338 /*state_tokens[1] = parse_integer (inst, Program);*/ /* Texture Unit */
3339
3340 if (parse_texcoord_num (ctx, inst, Program, &coord))
3341 return 1;
3342 state_tokens[1] = coord;
3343
3344 /* EYE or OBJECT */
3345 type = *(*inst++);
3346
3347 /* 0 - s, 1 - t, 2 - r, 3 - q */
3348 coord = *(*inst++);
3349
3350 if (type == TEX_GEN_EYE) {
3351 switch (coord) {
3352 case COMPONENT_X:
3353 state_tokens[2] = STATE_TEXGEN_EYE_S;
3354 break;
3355 case COMPONENT_Y:
3356 state_tokens[2] = STATE_TEXGEN_EYE_T;
3357 break;
3358 case COMPONENT_Z:
3359 state_tokens[2] = STATE_TEXGEN_EYE_R;
3360 break;
3361 case COMPONENT_W:
3362 state_tokens[2] = STATE_TEXGEN_EYE_Q;
3363 break;
3364 }
3365 }
3366 else {
3367 switch (coord) {
3368 case COMPONENT_X:
3369 state_tokens[2] = STATE_TEXGEN_OBJECT_S;
3370 break;
3371 case COMPONENT_Y:
3372 state_tokens[2] = STATE_TEXGEN_OBJECT_T;
3373 break;
3374 case COMPONENT_Z:
3375 state_tokens[2] = STATE_TEXGEN_OBJECT_R;
3376 break;
3377 case COMPONENT_W:
3378 state_tokens[2] = STATE_TEXGEN_OBJECT_Q;
3379 break;
3380 }
3381 }
3382 }
3383 break;
3384
3385 /* STATE_DEPTH = STATE_CLIP_PLANE */
3386 case STATE_DEPTH:
3387 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3388 switch (*(*inst)++) {
3389 case DEPTH_RANGE:
3390 state_tokens[0] = STATE_DEPTH_RANGE;
3391 break;
3392 }
3393 }
3394 /* for vertex programs, we want STATE_CLIP_PLANE */
3395 else {
3396 state_tokens[0] = STATE_CLIPPLANE;
3397 state_tokens[1] = parse_integer (inst, Program);
3398 if (parse_clipplane_num (ctx, inst, Program, &state_tokens[1]))
3399 return 1;
3400 }
3401 break;
3402
3403 case STATE_POINT:
3404 switch (*(*inst++)) {
3405 case POINT_SIZE:
3406 state_tokens[0] = STATE_POINT_SIZE;
3407 break;
3408
3409 case POINT_ATTENUATION:
3410 state_tokens[0] = STATE_POINT_ATTENUATION;
3411 break;
3412 }
3413 break;
3414
3415 /* XXX: I think this is the correct format for a matrix row */
3416 case STATE_MATRIX_ROWS:
3417 state_tokens[0] = STATE_MATRIX;
3418
3419 if (parse_matrix
3420 (ctx, inst, Program, &state_tokens[1], &state_tokens[2],
3421 &state_tokens[5]))
3422 return 1;
3423
3424 state_tokens[3] = parse_integer (inst, Program); /* The first row to grab */
3425
3426 state_tokens[4] = parse_integer (inst, Program); /* Either the last row, 0 */
3427 if (state_tokens[4] == 0) {
3428 state_tokens[4] = state_tokens[3];
3429 }
3430 break;
3431 }
3432
3433 return 0;
3434 }
3435
3436 /**
3437 * This parses a state string (rather, the binary version of it) into
3438 * a 6-token similar for the state fetching code in program.c
3439 *
3440 * One might ask, why fetch these parameters into just like you fetch
3441 * state when they are already stored in other places?
3442 *
3443 * Because of array offsets -> We can stick env/local parameters in the
3444 * middle of a parameter array and then index someplace into the array
3445 * when we execute.
3446 *
3447 * One optimization might be to only do this for the cases where the
3448 * env/local parameters end up inside of an array, and leave the
3449 * single parameters (or arrays of pure env/local pareameters) in their
3450 * respective register files.
3451 *
3452 * For ENV parameters, the format is:
3453 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3454 * state_tokens[1] = STATE_ENV
3455 * state_tokens[2] = the parameter index
3456 *
3457 * for LOCAL parameters, the format is:
3458 * state_tokens[0] = STATE_FRAGMENT_PROGRAM / STATE_VERTEX_PROGRAM
3459 * state_tokens[1] = STATE_LOCAL
3460 * state_tokens[2] = the parameter index
3461 *
3462 * \param inst - the start in the binary arry to start working from
3463 * \param state_tokens - the storage for the 6-token state description
3464 * \return - 0 on sucess, 1 on failure
3465 */
3466 static GLuint
3467 parse_program_single_item (GLcontext * ctx, GLubyte ** inst,
3468 struct arb_program *Program, GLint * state_tokens)
3469 {
3470 if (Program->type == GL_FRAGMENT_PROGRAM_ARB)
3471 state_tokens[0] = STATE_FRAGMENT_PROGRAM;
3472 else
3473 state_tokens[0] = STATE_VERTEX_PROGRAM;
3474
3475
3476 switch (*(*inst)++) {
3477 case PROGRAM_PARAM_ENV:
3478 state_tokens[1] = STATE_ENV;
3479 state_tokens[2] = parse_integer (inst, Program);
3480
3481 /* Check state_tokens[2] against the number of ENV parameters available */
3482 if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
3483 (state_tokens[2] >= ctx->Const.MaxFragmentProgramEnvParams))
3484 ||
3485 ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
3486 (state_tokens[2] >= ctx->Const.MaxVertexProgramEnvParams))) {
3487 _mesa_set_program_error (ctx, Program->Position,
3488 "Invalid Program Env Parameter");
3489 _mesa_error (ctx, GL_INVALID_OPERATION,
3490 "Invalid Program Env Parameter: %d",
3491 state_tokens[2]);
3492 return 1;
3493 }
3494
3495 break;
3496
3497 case PROGRAM_PARAM_LOCAL:
3498 state_tokens[1] = STATE_LOCAL;
3499 state_tokens[2] = parse_integer (inst, Program);
3500
3501 /* Check state_tokens[2] against the number of LOCAL parameters available */
3502 if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
3503 (state_tokens[2] >= ctx->Const.MaxFragmentProgramLocalParams))
3504 ||
3505 ((Program->type == GL_VERTEX_PROGRAM_ARB) &&
3506 (state_tokens[2] >= ctx->Const.MaxVertexProgramLocalParams))) {
3507 _mesa_set_program_error (ctx, Program->Position,
3508 "Invalid Program Local Parameter");
3509 _mesa_error (ctx, GL_INVALID_OPERATION,
3510 "Invalid Program Local Parameter: %d",
3511 state_tokens[2]);
3512 return 1;
3513 }
3514 break;
3515 }
3516
3517 return 0;
3518 }
3519
3520 /**
3521 * For ARB_vertex_program, programs are not allowed to use both an explicit
3522 * vertex attribute and a generic vertex attribute corresponding to the same
3523 * state. See section 2.14.3.1 of the GL_ARB_vertex_program spec.
3524 *
3525 * This will walk our var_cache and make sure that nobody does anything fishy.
3526 *
3527 * \return 0 on sucess, 1 on error
3528 */
3529 static GLuint
3530 generic_attrib_check(struct var_cache *vc_head)
3531 {
3532 int a;
3533 struct var_cache *curr;
3534 GLubyte explicit[MAX_VERTEX_PROGRAM_ATTRIBS],
3535 generic[MAX_VERTEX_PROGRAM_ATTRIBS];
3536
3537 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
3538 explicit[a] = 0;
3539 generic[a] = 0;
3540 }
3541
3542 curr = vc_head;
3543 while (curr) {
3544 if (curr->type == vt_attrib) {
3545 if (curr->attrib_is_generic)
3546 generic[ curr->attrib_binding_idx ] = 1;
3547 else
3548 explicit[ curr->attrib_binding_idx ] = 1;
3549 }
3550
3551 curr = curr->next;
3552 }
3553
3554 for (a=0; a<MAX_VERTEX_PROGRAM_ATTRIBS; a++) {
3555 if ((explicit[a]) && (generic[a]))
3556 return 1;
3557 }
3558
3559 return 0;
3560 }
3561
3562 /**
3563 * This will handle the binding side of an ATTRIB var declaration
3564 *
3565 * \param binding - the fragment input register state, defined in nvfragprog.h
3566 * \param binding_idx - the index in the attrib register file that binding is associated with
3567 * \return returns 0 on sucess, 1 on error
3568 *
3569 * See nvfragparse.c for attrib register file layout
3570 */
3571 static GLuint
3572 parse_attrib_binding (GLcontext * ctx, GLubyte ** inst,
3573 struct arb_program *Program, GLuint * binding,
3574 GLuint * binding_idx, GLuint *is_generic)
3575 {
3576 GLuint texcoord;
3577 GLint coord;
3578 GLint err = 0;
3579
3580 *is_generic = 0;
3581 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3582 switch (*(*inst)++) {
3583 case FRAGMENT_ATTRIB_COLOR:
3584 err = parse_color_type (ctx, inst, Program, &coord);
3585 *binding = FRAG_ATTRIB_COL0 + coord;
3586 *binding_idx = 1 + coord;
3587 break;
3588
3589 case FRAGMENT_ATTRIB_TEXCOORD:
3590 err = parse_texcoord_num (ctx, inst, Program, &texcoord);
3591 *binding = FRAG_ATTRIB_TEX0 + texcoord;
3592 *binding_idx = 4 + texcoord;
3593 break;
3594
3595 case FRAGMENT_ATTRIB_FOGCOORD:
3596 *binding = FRAG_ATTRIB_FOGC;
3597 *binding_idx = 3;
3598 break;
3599
3600 case FRAGMENT_ATTRIB_POSITION:
3601 *binding = FRAG_ATTRIB_WPOS;
3602 *binding_idx = 0;
3603 break;
3604
3605 default:
3606 err = 1;
3607 break;
3608 }
3609 }
3610 else {
3611 switch (*(*inst)++) {
3612 case VERTEX_ATTRIB_POSITION:
3613 *binding = VERT_ATTRIB_POS;
3614 *binding_idx = 0;
3615 break;
3616
3617 case VERTEX_ATTRIB_WEIGHT:
3618 {
3619 GLint weight;
3620
3621 err = parse_weight_num (ctx, inst, Program, &weight);
3622 *binding = VERT_ATTRIB_WEIGHT;
3623 *binding_idx = 1;
3624 }
3625 break;
3626
3627 case VERTEX_ATTRIB_NORMAL:
3628 *binding = VERT_ATTRIB_NORMAL;
3629 *binding_idx = 2;
3630 break;
3631
3632 case VERTEX_ATTRIB_COLOR:
3633 {
3634 GLint color;
3635
3636 err = parse_color_type (ctx, inst, Program, &color);
3637 if (color) {
3638 *binding = VERT_ATTRIB_COLOR1;
3639 *binding_idx = 4;
3640 }
3641 else {
3642 *binding = VERT_ATTRIB_COLOR0;
3643 *binding_idx = 3;
3644 }
3645 }
3646 break;
3647
3648 case VERTEX_ATTRIB_FOGCOORD:
3649 *binding = VERT_ATTRIB_FOG;
3650 *binding_idx = 5;
3651 break;
3652
3653 case VERTEX_ATTRIB_TEXCOORD:
3654 {
3655 GLuint unit;
3656
3657 err = parse_texcoord_num (ctx, inst, Program, &unit);
3658 *binding = VERT_ATTRIB_TEX0 + unit;
3659 *binding_idx = 8 + unit;
3660 }
3661 break;
3662
3663 /* XXX: It looks like we don't support this at all, atm */
3664 case VERTEX_ATTRIB_MATRIXINDEX:
3665 parse_integer (inst, Program);
3666 break;
3667
3668 case VERTEX_ATTRIB_GENERIC:
3669 {
3670 GLuint attrib;
3671
3672 if (!parse_generic_attrib_num(ctx, inst, Program, &attrib)) {
3673 *is_generic = 1;
3674 switch (attrib) {
3675 case 0:
3676 *binding = VERT_ATTRIB_POS;
3677 break;
3678 case 1:
3679 *binding = VERT_ATTRIB_WEIGHT;
3680 break;
3681 case 2:
3682 *binding = VERT_ATTRIB_NORMAL;
3683 break;
3684 case 3:
3685 *binding = VERT_ATTRIB_COLOR0;
3686 break;
3687 case 4:
3688 *binding = VERT_ATTRIB_COLOR1;
3689 break;
3690 case 5:
3691 *binding = VERT_ATTRIB_FOG;
3692 break;
3693 case 6:
3694 break;
3695 case 7:
3696 break;
3697 default:
3698 *binding = VERT_ATTRIB_TEX0 + (attrib-8);
3699 break;
3700 }
3701 *binding_idx = attrib;
3702 }
3703 }
3704 break;
3705
3706 default:
3707 err = 1;
3708 break;
3709 }
3710 }
3711
3712 /* Can this even happen? */
3713 if (err) {
3714 _mesa_set_program_error (ctx, Program->Position,
3715 "Bad attribute binding");
3716 _mesa_error (ctx, GL_INVALID_OPERATION, "Bad attribute binding");
3717 }
3718
3719 Program->InputsRead |= (1 << *binding_idx);
3720
3721 return err;
3722 }
3723
3724 /**
3725 * This translates between a binary token for an output variable type
3726 * and the mesa token for the same thing.
3727 *
3728 *
3729 * XXX: What is the 'name' for vertex program state? -> do we need it?
3730 * I don't think we do;
3731 *
3732 * See nvfragprog.h for definitions
3733 *
3734 * \param inst - The parsed tokens
3735 * \param binding - The name of the state we are binding too
3736 * \param binding_idx - The index into the result register file that this is bound too
3737 *
3738 * See nvfragparse.c for the register file layout for fragment programs
3739 * See nvvertparse.c for the register file layout for vertex programs
3740 */
3741 static GLuint
3742 parse_result_binding (GLcontext * ctx, GLubyte ** inst, GLuint * binding,
3743 GLuint * binding_idx, struct arb_program *Program)
3744 {
3745 GLuint b;
3746
3747 switch (*(*inst)++) {
3748 case FRAGMENT_RESULT_COLOR:
3749 /* for frag programs, this is FRAGMENT_RESULT_COLOR */
3750 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3751 *binding = FRAG_OUTPUT_COLR;
3752 *binding_idx = 0;
3753 }
3754 /* for vtx programs, this is VERTEX_RESULT_POSITION */
3755 else {
3756 *binding_idx = 0;
3757 }
3758 break;
3759
3760 case FRAGMENT_RESULT_DEPTH:
3761 /* for frag programs, this is FRAGMENT_RESULT_DEPTH */
3762 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3763 *binding = FRAG_OUTPUT_DEPR;
3764 *binding_idx = 2;
3765 }
3766 /* for vtx programs, this is VERTEX_RESULT_COLOR */
3767 else {
3768 GLint color_type;
3769 GLuint face_type = parse_face_type(inst);
3770 GLint color_type_ret = parse_color_type(ctx, inst, Program, &color_type);
3771
3772 /* back face */
3773 if (face_type) {
3774 if (color_type_ret) return 1;
3775
3776 /* secondary color */
3777 if (color_type) {
3778 *binding_idx = 4;
3779 }
3780 /* primary color */
3781 else {
3782 *binding_idx = 3;
3783 }
3784 }
3785 /* front face */
3786 else {
3787 /* secondary color */
3788 if (color_type) {
3789 *binding_idx = 2;
3790 }
3791 /* primary color */
3792 else {
3793 *binding_idx = 1;
3794 }
3795 }
3796 }
3797 break;
3798
3799 case VERTEX_RESULT_FOGCOORD:
3800 *binding_idx = 5;
3801 break;
3802
3803 case VERTEX_RESULT_POINTSIZE:
3804 *binding_idx = 6;
3805 break;
3806
3807 case VERTEX_RESULT_TEXCOORD:
3808 if (parse_texcoord_num (ctx, inst, Program, &b))
3809 return 1;
3810 *binding_idx = 7 + b;
3811 break;
3812 }
3813
3814 Program->OutputsWritten |= (1 << *binding_idx);
3815
3816 return 0;
3817 }
3818
3819 /**
3820 * This handles the declaration of ATTRIB variables
3821 *
3822 * XXX: Still needs
3823 * parse_vert_attrib_binding(), or something like that
3824 *
3825 * \return 0 on sucess, 1 on error
3826 */
3827 static GLint
3828 parse_attrib (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
3829 struct arb_program *Program)
3830 {
3831 GLuint found;
3832 char *error_msg;
3833 struct var_cache *attrib_var;
3834
3835 attrib_var = parse_string (inst, vc_head, Program, &found);
3836 Program->Position = parse_position (inst);
3837 if (found) {
3838 error_msg =
3839 _mesa_malloc (_mesa_strlen ((char *) attrib_var->name) + 40);
3840 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
3841 attrib_var->name);
3842
3843 _mesa_set_program_error (ctx, Program->Position, error_msg);
3844 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
3845
3846 _mesa_free (error_msg);
3847 return 1;
3848 }
3849
3850 attrib_var->type = vt_attrib;
3851
3852 /* I think this is ok now - karl */
3853 /* XXX: */
3854 /*if (Program->type == GL_FRAGMENT_PROGRAM_ARB) */
3855 {
3856 if (parse_attrib_binding
3857 (ctx, inst, Program, &attrib_var->attrib_binding,
3858 &attrib_var->attrib_binding_idx, &attrib_var->attrib_is_generic))
3859 return 1;
3860 if (generic_attrib_check(*vc_head)) {
3861 _mesa_set_program_error (ctx, Program->Position,
3862 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3863 _mesa_error (ctx, GL_INVALID_OPERATION,
3864 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
3865 return 1;
3866 }
3867
3868 }
3869
3870 Program->Base.NumAttributes++;
3871 return 0;
3872 }
3873
3874 /**
3875 * \param use -- TRUE if we're called when declaring implicit parameters,
3876 * FALSE if we're declaraing variables. This has to do with
3877 * if we get a signed or unsigned float for scalar constants
3878 */
3879 static GLuint
3880 parse_param_elements (GLcontext * ctx, GLubyte ** inst,
3881 struct var_cache *param_var,
3882 struct arb_program *Program, GLboolean use)
3883 {
3884 GLint idx;
3885 GLuint err;
3886 GLint state_tokens[6];
3887 GLfloat const_values[4];
3888
3889 err = 0;
3890
3891 switch (*(*inst)++) {
3892 case PARAM_STATE_ELEMENT:
3893
3894 if (parse_state_single_item (ctx, inst, Program, state_tokens))
3895 return 1;
3896
3897 /* If we adding STATE_MATRIX that has multiple rows, we need to
3898 * unroll it and call _mesa_add_state_reference() for each row
3899 */
3900 if ((state_tokens[0] == STATE_MATRIX)
3901 && (state_tokens[3] != state_tokens[4])) {
3902 GLint row;
3903 GLint first_row = state_tokens[3];
3904 GLint last_row = state_tokens[4];
3905
3906 for (row = first_row; row <= last_row; row++) {
3907 state_tokens[3] = state_tokens[4] = row;
3908
3909 idx =
3910 _mesa_add_state_reference (Program->Parameters,
3911 state_tokens);
3912 if (param_var->param_binding_begin == -1)
3913 param_var->param_binding_begin = idx;
3914 param_var->param_binding_length++;
3915 Program->Base.NumParameters++;
3916 }
3917 }
3918 else {
3919 idx =
3920 _mesa_add_state_reference (Program->Parameters, state_tokens);
3921 if (param_var->param_binding_begin == -1)
3922 param_var->param_binding_begin = idx;
3923 param_var->param_binding_length++;
3924 Program->Base.NumParameters++;
3925 }
3926 break;
3927
3928 case PARAM_PROGRAM_ELEMENT:
3929
3930 if (parse_program_single_item (ctx, inst, Program, state_tokens))
3931 return 1;
3932 idx = _mesa_add_state_reference (Program->Parameters, state_tokens);
3933 if (param_var->param_binding_begin == -1)
3934 param_var->param_binding_begin = idx;
3935 param_var->param_binding_length++;
3936 Program->Base.NumParameters++;
3937
3938 /* Check if there is more: 0 -> we're done, else its an integer */
3939 if (**inst) {
3940 GLuint out_of_range, new_idx;
3941 GLuint start_idx = state_tokens[2] + 1;
3942 GLuint end_idx = parse_integer (inst, Program);
3943
3944 out_of_range = 0;
3945 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
3946 if (((state_tokens[1] == STATE_ENV)
3947 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
3948 || ((state_tokens[1] == STATE_LOCAL)
3949 && (end_idx >=
3950 ctx->Const.MaxFragmentProgramLocalParams)))
3951 out_of_range = 1;
3952 }
3953 else {
3954 if (((state_tokens[1] == STATE_ENV)
3955 && (end_idx >= ctx->Const.MaxFragmentProgramEnvParams))
3956 || ((state_tokens[1] == STATE_LOCAL)
3957 && (end_idx >=
3958 ctx->Const.MaxFragmentProgramLocalParams)))
3959 out_of_range = 1;
3960 }
3961 if (out_of_range) {
3962 _mesa_set_program_error (ctx, Program->Position,
3963 "Invalid Program Parameter");
3964 _mesa_error (ctx, GL_INVALID_OPERATION,
3965 "Invalid Program Parameter: %d", end_idx);
3966 return 1;
3967 }
3968
3969 for (new_idx = start_idx; new_idx <= end_idx; new_idx++) {
3970 state_tokens[2] = new_idx;
3971 idx =
3972 _mesa_add_state_reference (Program->Parameters,
3973 state_tokens);
3974 param_var->param_binding_length++;
3975 Program->Base.NumParameters++;
3976 }
3977 }
3978 else
3979 {
3980 (*(*inst)++);
3981 }
3982 break;
3983
3984 case PARAM_CONSTANT:
3985 parse_constant (inst, const_values, Program, use);
3986 idx =
3987 _mesa_add_named_constant (Program->Parameters,
3988 (char *) param_var->name, const_values);
3989 if (param_var->param_binding_begin == -1)
3990 param_var->param_binding_begin = idx;
3991 param_var->param_binding_length++;
3992 Program->Base.NumParameters++;
3993 break;
3994
3995 default:
3996 _mesa_set_program_error (ctx, Program->Position,
3997 "Unexpected token in parse_param_elements()");
3998 _mesa_error (ctx, GL_INVALID_OPERATION,
3999 "Unexpected token in parse_param_elements()");
4000 return 1;
4001 }
4002
4003 /* Make sure we haven't blown past our parameter limits */
4004 if (((Program->type == GL_VERTEX_PROGRAM_ARB) &&
4005 (Program->Base.NumParameters >=
4006 ctx->Const.MaxVertexProgramLocalParams))
4007 || ((Program->type == GL_FRAGMENT_PROGRAM_ARB)
4008 && (Program->Base.NumParameters >=
4009 ctx->Const.MaxFragmentProgramLocalParams))) {
4010 _mesa_set_program_error (ctx, Program->Position,
4011 "Too many parameter variables");
4012 _mesa_error (ctx, GL_INVALID_OPERATION, "Too many parameter variables");
4013 return 1;
4014 }
4015
4016 return err;
4017 }
4018
4019 /**
4020 * This picks out PARAM program parameter bindings.
4021 *
4022 * XXX: This needs to be stressed & tested
4023 *
4024 * \return 0 on sucess, 1 on error
4025 */
4026 static GLuint
4027 parse_param (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4028 struct arb_program *Program)
4029 {
4030 GLuint found, specified_length, err;
4031 char *error_msg;
4032 struct var_cache *param_var;
4033
4034 err = 0;
4035 param_var = parse_string (inst, vc_head, Program, &found);
4036 Program->Position = parse_position (inst);
4037
4038 if (found) {
4039 error_msg = _mesa_malloc (_mesa_strlen ((char *) param_var->name) + 40);
4040 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
4041 param_var->name);
4042
4043 _mesa_set_program_error (ctx, Program->Position, error_msg);
4044 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4045
4046 _mesa_free (error_msg);
4047 return 1;
4048 }
4049
4050 specified_length = parse_integer (inst, Program);
4051
4052 if (specified_length < 0) {
4053 _mesa_set_program_error (ctx, Program->Position,
4054 "Negative parameter array length");
4055 _mesa_error (ctx, GL_INVALID_OPERATION,
4056 "Negative parameter array length: %d", specified_length);
4057 return 1;
4058 }
4059
4060 param_var->type = vt_param;
4061 param_var->param_binding_length = 0;
4062
4063 /* Right now, everything is shoved into the main state register file.
4064 *
4065 * In the future, it would be nice to leave things ENV/LOCAL params
4066 * in their respective register files, if possible
4067 */
4068 param_var->param_binding_type = PROGRAM_STATE_VAR;
4069
4070 /* Remember to:
4071 * * - add each guy to the parameter list
4072 * * - increment the param_var->param_binding_len
4073 * * - store the param_var->param_binding_begin for the first one
4074 * * - compare the actual len to the specified len at the end
4075 */
4076 while (**inst != PARAM_NULL) {
4077 if (parse_param_elements (ctx, inst, param_var, Program, GL_FALSE))
4078 return 1;
4079 }
4080
4081 /* Test array length here! */
4082 if (specified_length) {
4083 if (specified_length != param_var->param_binding_length) {
4084 _mesa_set_program_error (ctx, Program->Position,
4085 "Declared parameter array lenght does not match parameter list");
4086 _mesa_error (ctx, GL_INVALID_OPERATION,
4087 "Declared parameter array lenght does not match parameter list");
4088 }
4089 }
4090
4091 (*inst)++;
4092
4093 return 0;
4094 }
4095
4096 /**
4097 *
4098 */
4099 static GLuint
4100 parse_param_use (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4101 struct arb_program *Program, struct var_cache **new_var)
4102 {
4103 struct var_cache *param_var;
4104
4105 /* First, insert a dummy entry into the var_cache */
4106 var_cache_create (&param_var);
4107 param_var->name = (GLubyte *) _mesa_strdup (" ");
4108 param_var->type = vt_param;
4109
4110 param_var->param_binding_length = 0;
4111 /* Don't fill in binding_begin; We use the default value of -1
4112 * to tell if its already initialized, elsewhere.
4113 *
4114 * param_var->param_binding_begin = 0;
4115 */
4116 param_var->param_binding_type = PROGRAM_STATE_VAR;
4117
4118 var_cache_append (vc_head, param_var);
4119
4120 /* Then fill it with juicy parameter goodness */
4121 if (parse_param_elements (ctx, inst, param_var, Program, GL_TRUE))
4122 return 1;
4123
4124 *new_var = param_var;
4125
4126 return 0;
4127 }
4128
4129
4130 /**
4131 * This handles the declaration of TEMP variables
4132 *
4133 * \return 0 on sucess, 1 on error
4134 */
4135 static GLuint
4136 parse_temp (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4137 struct arb_program *Program)
4138 {
4139 GLuint found;
4140 struct var_cache *temp_var;
4141 char *error_msg;
4142
4143 while (**inst != 0) {
4144 temp_var = parse_string (inst, vc_head, Program, &found);
4145 Program->Position = parse_position (inst);
4146 if (found) {
4147 error_msg =
4148 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
4149 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
4150 temp_var->name);
4151
4152 _mesa_set_program_error (ctx, Program->Position, error_msg);
4153 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4154
4155 _mesa_free (error_msg);
4156 return 1;
4157 }
4158
4159 temp_var->type = vt_temp;
4160
4161 if (((Program->type == GL_FRAGMENT_PROGRAM_ARB) &&
4162 (Program->Base.NumTemporaries >=
4163 ctx->Const.MaxFragmentProgramTemps))
4164 || ((Program->type == GL_VERTEX_PROGRAM_ARB)
4165 && (Program->Base.NumTemporaries >=
4166 ctx->Const.MaxVertexProgramTemps))) {
4167 _mesa_set_program_error (ctx, Program->Position,
4168 "Too many TEMP variables declared");
4169 _mesa_error (ctx, GL_INVALID_OPERATION,
4170 "Too many TEMP variables declared");
4171 return 1;
4172 }
4173
4174 temp_var->temp_binding = Program->Base.NumTemporaries;
4175 Program->Base.NumTemporaries++;
4176 }
4177 (*inst)++;
4178
4179 return 0;
4180 }
4181
4182 /**
4183 * This handles variables of the OUTPUT variety
4184 *
4185 * \return 0 on sucess, 1 on error
4186 */
4187 static GLuint
4188 parse_output (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4189 struct arb_program *Program)
4190 {
4191 GLuint found;
4192 struct var_cache *output_var;
4193
4194 output_var = parse_string (inst, vc_head, Program, &found);
4195 Program->Position = parse_position (inst);
4196 if (found) {
4197 char *error_msg;
4198 error_msg =
4199 _mesa_malloc (_mesa_strlen ((char *) output_var->name) + 40);
4200 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
4201 output_var->name);
4202
4203 _mesa_set_program_error (ctx, Program->Position, error_msg);
4204 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4205
4206 _mesa_free (error_msg);
4207 return 1;
4208 }
4209
4210 output_var->type = vt_output;
4211 return parse_result_binding (ctx, inst, &output_var->output_binding,
4212 &output_var->output_binding_idx, Program);
4213 }
4214
4215 /**
4216 * This handles variables of the ALIAS kind
4217 *
4218 * \return 0 on sucess, 1 on error
4219 */
4220 static GLuint
4221 parse_alias (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4222 struct arb_program *Program)
4223 {
4224 GLuint found;
4225 struct var_cache *temp_var;
4226 char *error_msg;
4227
4228
4229 temp_var = parse_string (inst, vc_head, Program, &found);
4230 Program->Position = parse_position (inst);
4231
4232 if (found) {
4233 error_msg =
4234 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
4235 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
4236 temp_var->name);
4237
4238 _mesa_set_program_error (ctx, Program->Position, error_msg);
4239 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4240
4241 _mesa_free (error_msg);
4242 return 1;
4243 }
4244
4245 temp_var->type = vt_alias;
4246 temp_var->alias_binding = parse_string (inst, vc_head, Program, &found);
4247 Program->Position = parse_position (inst);
4248
4249 if (!found)
4250 {
4251 error_msg =
4252 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
4253 _mesa_sprintf (error_msg, "Alias value %s is not defined",
4254 temp_var->alias_binding->name);
4255
4256 _mesa_set_program_error (ctx, Program->Position, error_msg);
4257 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4258
4259 _mesa_free (error_msg);
4260 return 1;
4261 }
4262
4263 return 0;
4264 }
4265
4266 /**
4267 * This handles variables of the ADDRESS kind
4268 *
4269 * \return 0 on sucess, 1 on error
4270 */
4271 static GLuint
4272 parse_address (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4273 struct arb_program *Program)
4274 {
4275 GLuint found;
4276 struct var_cache *temp_var;
4277 char *error_msg;
4278
4279 while (**inst != 0) {
4280 temp_var = parse_string (inst, vc_head, Program, &found);
4281 Program->Position = parse_position (inst);
4282 if (found) {
4283 error_msg =
4284 _mesa_malloc (_mesa_strlen ((char *) temp_var->name) + 40);
4285 _mesa_sprintf (error_msg, "Duplicate Varible Declaration: %s",
4286 temp_var->name);
4287
4288 _mesa_set_program_error (ctx, Program->Position, error_msg);
4289 _mesa_error (ctx, GL_INVALID_OPERATION, error_msg);
4290
4291 _mesa_free (error_msg);
4292 return 1;
4293 }
4294
4295 temp_var->type = vt_address;
4296
4297 if (Program->Base.NumAddressRegs >=
4298 ctx->Const.MaxVertexProgramAddressRegs) {
4299 _mesa_set_program_error (ctx, Program->Position,
4300 "Too many ADDRESS variables declared");
4301 _mesa_error (ctx, GL_INVALID_OPERATION,
4302 "Too many ADDRESS variables declared");
4303 return 1;
4304 }
4305
4306 temp_var->address_binding = Program->Base.NumAddressRegs;
4307 Program->Base.NumAddressRegs++;
4308 }
4309 (*inst)++;
4310
4311 return 0;
4312 }
4313
4314 /**
4315 * Parse a program declaration
4316 *
4317 * \return 0 on sucess, 1 on error
4318 */
4319 static GLint
4320 parse_declaration (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4321 struct arb_program *Program)
4322 {
4323 GLint err = 0;
4324
4325 switch (*(*inst)++) {
4326 case ADDRESS:
4327 err = parse_address (ctx, inst, vc_head, Program);
4328 break;
4329
4330 case ALIAS:
4331 err = parse_alias (ctx, inst, vc_head, Program);
4332 break;
4333
4334 case ATTRIB:
4335 err = parse_attrib (ctx, inst, vc_head, Program);
4336 break;
4337
4338 case OUTPUT:
4339 err = parse_output (ctx, inst, vc_head, Program);
4340 break;
4341
4342 case PARAM:
4343 err = parse_param (ctx, inst, vc_head, Program);
4344 break;
4345
4346 case TEMP:
4347 err = parse_temp (ctx, inst, vc_head, Program);
4348 break;
4349 }
4350
4351 return err;
4352 }
4353
4354 /**
4355 * Handle the parsing out of a masked destination register
4356 *
4357 * \param File - The register file we write to
4358 * \param Index - The register index we write to
4359 * \param WriteMask - The mask controlling which components we write (1->write)
4360 *
4361 * \return 0 on sucess, 1 on error
4362 */
4363 static GLuint
4364 parse_masked_dst_reg (GLcontext * ctx, GLubyte ** inst,
4365 struct var_cache **vc_head, struct arb_program *Program,
4366 GLint * File, GLint * Index, GLboolean * WriteMask)
4367 {
4368 GLuint result;
4369 GLubyte mask;
4370 struct var_cache *dst;
4371
4372 /* We either have a result register specified, or a
4373 * variable that may or may not be writable
4374 */
4375 switch (*(*inst)++) {
4376 case REGISTER_RESULT:
4377 if (parse_result_binding
4378 (ctx, inst, &result, (GLuint *) Index, Program))
4379 return 1;
4380 *File = PROGRAM_OUTPUT;
4381 break;
4382
4383 case REGISTER_ESTABLISHED_NAME:
4384 dst = parse_string (inst, vc_head, Program, &result);
4385 Program->Position = parse_position (inst);
4386
4387 /* If the name has never been added to our symbol table, we're hosed */
4388 if (!result) {
4389 _mesa_set_program_error (ctx, Program->Position,
4390 "0: Undefined variable");
4391 _mesa_error (ctx, GL_INVALID_OPERATION, "0: Undefined variable: %s",
4392 dst->name);
4393 return 1;
4394 }
4395
4396 switch (dst->type) {
4397 case vt_output:
4398 *File = PROGRAM_OUTPUT;
4399 *Index = dst->output_binding_idx;
4400 break;
4401
4402 case vt_temp:
4403 *File = PROGRAM_TEMPORARY;
4404 *Index = dst->temp_binding;
4405 break;
4406
4407 /* If the var type is not vt_output or vt_temp, no go */
4408 default:
4409 _mesa_set_program_error (ctx, Program->Position,
4410 "Destination register is read only");
4411 _mesa_error (ctx, GL_INVALID_OPERATION,
4412 "Destination register is read only: %s",
4413 dst->name);
4414 return 1;
4415 }
4416 break;
4417
4418 default:
4419 _mesa_set_program_error (ctx, Program->Position,
4420 "Unexpected opcode in parse_masked_dst_reg()");
4421 _mesa_error (ctx, GL_INVALID_OPERATION,
4422 "Unexpected opcode in parse_masked_dst_reg()");
4423 return 1;
4424 }
4425
4426 /* And then the mask.
4427 * w,a -> bit 0
4428 * z,b -> bit 1
4429 * y,g -> bit 2
4430 * x,r -> bit 3
4431 */
4432 mask = *(*inst)++;
4433
4434 WriteMask[0] = (mask & (1 << 3)) >> 3;
4435 WriteMask[1] = (mask & (1 << 2)) >> 2;
4436 WriteMask[2] = (mask & (1 << 1)) >> 1;
4437 WriteMask[3] = (mask & (1));
4438
4439 return 0;
4440 }
4441
4442 /**
4443 * Handle the parsing out of a masked address register
4444 *
4445 * \param Index - The register index we write to
4446 * \param WriteMask - The mask controlling which components we write (1->write)
4447 *
4448 * \return 0 on sucess, 1 on error
4449 */
4450 static GLuint
4451 parse_masked_address_reg (GLcontext * ctx, GLubyte ** inst,
4452 struct var_cache **vc_head,
4453 struct arb_program *Program, GLint * Index,
4454 GLboolean * WriteMask)
4455 {
4456 struct var_cache *dst;
4457 GLuint result;
4458
4459 dst = parse_string (inst, vc_head, Program, &result);
4460 Program->Position = parse_position (inst);
4461
4462 /* If the name has never been added to our symbol table, we're hosed */
4463 if (!result) {
4464 _mesa_set_program_error (ctx, Program->Position, "1: Undefined variable");
4465 _mesa_error (ctx, GL_INVALID_OPERATION, "1: Undefined variable: %s",
4466 dst->name);
4467 return 1;
4468 }
4469
4470 if (dst->type != vt_address) {
4471 _mesa_set_program_error (ctx, Program->Position,
4472 "Variable is not of type ADDRESS");
4473 _mesa_error (ctx, GL_INVALID_OPERATION,
4474 "Variable: %s is not of type ADDRESS", dst->name);
4475 return 1;
4476 }
4477
4478 /* Writemask of .x is implied */
4479 WriteMask[0] = 1;
4480 WriteMask[1] = WriteMask[2] = WriteMask[3] = 0;
4481
4482 return 0;
4483 }
4484
4485 /**
4486 * Parse out a swizzle mask.
4487 *
4488 * The values in the input stream are:
4489 * COMPONENT_X -> x/r
4490 * COMPONENT_Y -> y/g
4491 * COMPONENT_Z-> z/b
4492 * COMPONENT_W-> w/a
4493 *
4494 * The values in the output mask are:
4495 * 0 -> x/r
4496 * 1 -> y/g
4497 * 2 -> z/b
4498 * 3 -> w/a
4499 *
4500 * The len parameter allows us to grab 4 components for a vector
4501 * swizzle, or just 1 component for a scalar src register selection
4502 */
4503 static GLuint
4504 parse_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLint len)
4505 {
4506 GLint a;
4507
4508 for (a = 0; a < 4; a++)
4509 mask[a] = a;
4510
4511 for (a = 0; a < len; a++) {
4512 switch (*(*inst)++) {
4513 case COMPONENT_X:
4514 mask[a] = 0;
4515 break;
4516
4517 case COMPONENT_Y:
4518 mask[a] = 1;
4519 break;
4520
4521 case COMPONENT_Z:
4522 mask[a] = 2;
4523 break;
4524
4525 case COMPONENT_W:
4526 mask[a] = 3;
4527 break;
4528 }
4529 }
4530
4531 return 0;
4532 }
4533
4534 /**
4535 */
4536 static GLuint
4537 parse_extended_swizzle_mask (GLubyte ** inst, GLubyte * mask, GLboolean * Negate)
4538 {
4539 GLint a;
4540 GLubyte swz;
4541
4542 *Negate = GL_FALSE;
4543 for (a = 0; a < 4; a++) {
4544 if (parse_sign (inst))
4545 *Negate = GL_TRUE;
4546
4547 swz = *(*inst)++;
4548
4549 switch (swz) {
4550 case COMPONENT_0:
4551 mask[a] = SWIZZLE_ZERO;
4552 break;
4553 case COMPONENT_1:
4554 mask[a] = SWIZZLE_ONE;
4555 break;
4556 case COMPONENT_X:
4557 mask[a] = 0;
4558 break;
4559 case COMPONENT_Y:
4560 mask[a] = 1;
4561 break;
4562 case COMPONENT_Z:
4563 mask[a] = 2;
4564 break;
4565 case COMPONENT_W:
4566 mask[a] = 3;
4567 break;
4568
4569 }
4570 #if 0
4571 if (swz == 0)
4572 mask[a] = SWIZZLE_ZERO;
4573 else if (swz == 1)
4574 mask[a] = SWIZZLE_ONE;
4575 else
4576 mask[a] = swz - 2;
4577 #endif
4578
4579 }
4580
4581 return 0;
4582 }
4583
4584
4585 static GLuint
4586 parse_src_reg (GLcontext * ctx, GLubyte ** inst, struct var_cache **vc_head,
4587 struct arb_program *Program, GLint * File, GLint * Index)
4588 {
4589 struct var_cache *src;
4590 GLuint binding_state, binding_idx, is_generic, found, offset;
4591
4592 /* And the binding for the src */
4593 switch (*(*inst)++) {
4594 case REGISTER_ATTRIB:
4595 if (parse_attrib_binding
4596 (ctx, inst, Program, &binding_state, &binding_idx, &is_generic))
4597 return 1;
4598 *File = PROGRAM_INPUT;
4599 *Index = binding_idx;
4600
4601 /* We need to insert a dummy variable into the var_cache so we can
4602 * catch generic vertex attrib aliasing errors
4603 */
4604 var_cache_create(&src);
4605 src->type = vt_attrib;
4606 src->name = (GLubyte *)_mesa_strdup("Dummy Attrib Variable");
4607 src->attrib_binding = binding_state;
4608 src->attrib_binding_idx = binding_idx;
4609 src->attrib_is_generic = is_generic;
4610 var_cache_append(vc_head, src);
4611 if (generic_attrib_check(*vc_head)) {
4612 _mesa_set_program_error (ctx, Program->Position,
4613 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4614 _mesa_error (ctx, GL_INVALID_OPERATION,
4615 "Cannot use both a generic vertex attribute and a specific attribute of the same type");
4616 return 1;
4617 }
4618 break;
4619
4620 case REGISTER_PARAM:
4621 switch (**inst) {
4622 case PARAM_ARRAY_ELEMENT:
4623 *(*inst)++;
4624 src = parse_string (inst, vc_head, Program, &found);
4625 Program->Position = parse_position (inst);
4626
4627 if (!found) {
4628 _mesa_set_program_error (ctx, Program->Position,
4629 "2: Undefined variable");
4630 _mesa_error (ctx, GL_INVALID_OPERATION,
4631 "2: Undefined variable: %s", src->name);
4632 return 1;
4633 }
4634
4635 *File = src->param_binding_type;
4636
4637 switch (*(*inst)++) {
4638 case ARRAY_INDEX_ABSOLUTE:
4639 offset = parse_integer (inst, Program);
4640
4641 if ((offset < 0)
4642 || (offset >= src->param_binding_length)) {
4643 _mesa_set_program_error (ctx, Program->Position,
4644 "Index out of range");
4645 _mesa_error (ctx, GL_INVALID_OPERATION,
4646 "Index %d out of range for %s", offset,
4647 src->name);
4648 return 1;
4649 }
4650
4651 *Index = src->param_binding_begin + offset;
4652 break;
4653
4654 /* XXX: */
4655 case ARRAY_INDEX_RELATIVE:
4656 break;
4657 }
4658 break;
4659
4660 default:
4661
4662 if (parse_param_use (ctx, inst, vc_head, Program, &src))
4663 return 1;
4664
4665 *File = src->param_binding_type;
4666 *Index = src->param_binding_begin;
4667 break;
4668 }
4669 break;
4670
4671 case REGISTER_ESTABLISHED_NAME:
4672
4673 src = parse_string (inst, vc_head, Program, &found);
4674 Program->Position = parse_position (inst);
4675
4676 /* If the name has never been added to our symbol table, we're hosed */
4677 if (!found) {
4678 _mesa_set_program_error (ctx, Program->Position,
4679 "3: Undefined variable");
4680 _mesa_error (ctx, GL_INVALID_OPERATION, "3: Undefined variable: %s",
4681 src->name);
4682 return 1;
4683 }
4684
4685 switch (src->type) {
4686 case vt_attrib:
4687 *File = PROGRAM_INPUT;
4688 *Index = src->attrib_binding_idx;
4689 break;
4690
4691 /* XXX: We have to handle offsets someplace in here! -- or are those above? */
4692 case vt_param:
4693 *File = src->param_binding_type;
4694 *Index = src->param_binding_begin;
4695 break;
4696
4697 case vt_temp:
4698 *File = PROGRAM_TEMPORARY;
4699 *Index = src->temp_binding;
4700 break;
4701
4702 /* If the var type is vt_output no go */
4703 default:
4704 _mesa_set_program_error (ctx, Program->Position,
4705 "destination register is read only");
4706 _mesa_error (ctx, GL_INVALID_OPERATION,
4707 "destination register is read only: %s",
4708 src->name);
4709 return 1;
4710 }
4711 break;
4712
4713 default:
4714 _mesa_set_program_error (ctx, Program->Position,
4715 "Unknown token in parse_src_reg");
4716 _mesa_error (ctx, GL_INVALID_OPERATION,
4717 "Unknown token in parse_src_reg");
4718 return 1;
4719 }
4720
4721 return 0;
4722 }
4723
4724 /**
4725 */
4726 static GLuint
4727 parse_vector_src_reg (GLcontext * ctx, GLubyte ** inst,
4728 struct var_cache **vc_head, struct arb_program *Program,
4729 GLint * File, GLint * Index, GLboolean * Negate,
4730 GLubyte * Swizzle)
4731 {
4732 /* Grab the sign */
4733 *Negate = parse_sign (inst);
4734
4735 /* And the src reg */
4736 if (parse_src_reg (ctx, inst, vc_head, Program, File, Index))
4737 return 1;
4738
4739 /* finally, the swizzle */
4740 parse_swizzle_mask (inst, Swizzle, 4);
4741
4742 return 0;
4743 }
4744
4745 /**
4746 */
4747 static GLuint
4748 parse_scalar_src_reg (GLcontext * ctx, GLubyte ** inst,
4749 struct var_cache **vc_head, struct arb_program *Program,
4750 GLint * File, GLint * Index, GLboolean * Negate,
4751 GLubyte * Swizzle)
4752 {
4753 /* Grab the sign */
4754 *Negate = parse_sign (inst);
4755
4756 /* And the src reg */
4757 if (parse_src_reg (ctx, inst, vc_head, Program, File, Index))
4758 return 1;
4759
4760 /* Now, get the component and shove it into all the swizzle slots */
4761 parse_swizzle_mask (inst, Swizzle, 1);
4762
4763 return 0;
4764 }
4765
4766 /**
4767 * This is a big mother that handles getting opcodes into the instruction
4768 * and handling the src & dst registers for fragment program instructions
4769 */
4770 static GLuint
4771 parse_fp_instruction (GLcontext * ctx, GLubyte ** inst,
4772 struct var_cache **vc_head, struct arb_program *Program,
4773 struct fp_instruction *fp)
4774 {
4775 GLint a, b;
4776 GLubyte swz[4]; /* FP's swizzle mask is a GLubyte, while VP's is GLuint */
4777 GLuint texcoord;
4778 GLubyte class, type, code;
4779
4780 /* No condition codes in ARB_fp */
4781 fp->UpdateCondRegister = 0;
4782
4783 /* Record the position in the program string for debugging */
4784 fp->StringPos = Program->Position;
4785
4786 /* F_ALU_INST or F_TEX_INST */
4787 class = *(*inst)++;
4788
4789 /* F_ALU_{VECTOR, SCALAR, BINSC, BIN, TRI, SWZ},
4790 * F_TEX_{SAMPLE, KIL}
4791 */
4792 type = *(*inst)++;
4793
4794 /* The actual opcode name */
4795 code = *(*inst)++;
4796
4797 /* Increment the correct count */
4798 switch (class) {
4799 case F_ALU_INST:
4800 Program->NumAluInstructions++;
4801 break;
4802 case F_TEX_INST:
4803 Program->NumTexInstructions++;
4804 break;
4805 }
4806
4807 fp->Saturate = 0;
4808 fp->Precision = FLOAT32;
4809
4810 fp->DstReg.CondMask = COND_TR;
4811
4812 switch (type) {
4813 case F_ALU_VECTOR:
4814 switch (code) {
4815 case F_ABS_SAT:
4816 fp->Saturate = 1;
4817 case F_ABS:
4818 fp->Opcode = FP_OPCODE_ABS;
4819 break;
4820
4821 case F_FLR_SAT:
4822 fp->Saturate = 1;
4823 case F_FLR:
4824 fp->Opcode = FP_OPCODE_FLR;
4825 break;
4826
4827 case F_FRC_SAT:
4828 fp->Saturate = 1;
4829 case F_FRC:
4830 fp->Opcode = FP_OPCODE_FRC;
4831 break;
4832
4833 case F_LIT_SAT:
4834 fp->Saturate = 1;
4835 case F_LIT:
4836 fp->Opcode = FP_OPCODE_LIT;
4837 break;
4838
4839 case F_MOV_SAT:
4840 fp->Saturate = 1;
4841 case F_MOV:
4842 fp->Opcode = FP_OPCODE_MOV;
4843 break;
4844 }
4845
4846 if (parse_masked_dst_reg
4847 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
4848 &fp->DstReg.Index, fp->DstReg.WriteMask))
4849 return 1;
4850
4851 fp->SrcReg[0].Abs = GL_FALSE;
4852 fp->SrcReg[0].NegateAbs = GL_FALSE;
4853 if (parse_vector_src_reg
4854 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
4855 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
4856 swz))
4857 return 1;
4858 for (b=0; b<4; b++)
4859 fp->SrcReg[0].Swizzle[b] = swz[b];
4860 break;
4861
4862 case F_ALU_SCALAR:
4863 switch (code) {
4864 case F_COS_SAT:
4865 fp->Saturate = 1;
4866 case F_COS:
4867 fp->Opcode = FP_OPCODE_COS;
4868 break;
4869
4870 case F_EX2_SAT:
4871 fp->Saturate = 1;
4872 case F_EX2:
4873 fp->Opcode = FP_OPCODE_EX2;
4874 break;
4875
4876 case F_LG2_SAT:
4877 fp->Saturate = 1;
4878 case F_LG2:
4879 fp->Opcode = FP_OPCODE_LG2;
4880 break;
4881
4882 case F_RCP_SAT:
4883 fp->Saturate = 1;
4884 case F_RCP:
4885 fp->Opcode = FP_OPCODE_RCP;
4886 break;
4887
4888 case F_RSQ_SAT:
4889 fp->Saturate = 1;
4890 case F_RSQ:
4891 fp->Opcode = FP_OPCODE_RSQ;
4892 break;
4893
4894 case F_SIN_SAT:
4895 fp->Saturate = 1;
4896 case F_SIN:
4897 fp->Opcode = FP_OPCODE_SIN;
4898 break;
4899
4900 case F_SCS_SAT:
4901 fp->Saturate = 1;
4902 case F_SCS:
4903 fp->Opcode = FP_OPCODE_SCS;
4904 break;
4905 }
4906
4907 if (parse_masked_dst_reg
4908 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
4909 &fp->DstReg.Index, fp->DstReg.WriteMask))
4910 return 1;
4911 fp->SrcReg[0].Abs = GL_FALSE;
4912 fp->SrcReg[0].NegateAbs = GL_FALSE;
4913 if (parse_scalar_src_reg
4914 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
4915 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
4916 swz))
4917 return 1;
4918 for (b=0; b<4; b++)
4919 fp->SrcReg[0].Swizzle[b] = swz[b];
4920 break;
4921
4922 case F_ALU_BINSC:
4923 switch (code) {
4924 case F_POW_SAT:
4925 fp->Saturate = 1;
4926 case F_POW:
4927 fp->Opcode = FP_OPCODE_POW;
4928 break;
4929 }
4930
4931 if (parse_masked_dst_reg
4932 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
4933 &fp->DstReg.Index, fp->DstReg.WriteMask))
4934 return 1;
4935 for (a = 0; a < 2; a++) {
4936 fp->SrcReg[a].Abs = GL_FALSE;
4937 fp->SrcReg[a].NegateAbs = GL_FALSE;
4938 if (parse_scalar_src_reg
4939 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
4940 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
4941 swz))
4942 return 1;
4943 for (b=0; b<4; b++)
4944 fp->SrcReg[a].Swizzle[b] = swz[b];
4945 }
4946 break;
4947
4948
4949 case F_ALU_BIN:
4950 switch (code) {
4951 case F_ADD_SAT:
4952 fp->Saturate = 1;
4953 case F_ADD:
4954 fp->Opcode = FP_OPCODE_ADD;
4955 break;
4956
4957 case F_DP3_SAT:
4958 fp->Saturate = 1;
4959 case F_DP3:
4960 fp->Opcode = FP_OPCODE_DP3;
4961 break;
4962
4963 case F_DP4_SAT:
4964 fp->Saturate = 1;
4965 case F_DP4:
4966 fp->Opcode = FP_OPCODE_DP4;
4967 break;
4968
4969 case F_DPH_SAT:
4970 fp->Saturate = 1;
4971 case F_DPH:
4972 fp->Opcode = FP_OPCODE_DPH;
4973 break;
4974
4975 case F_DST_SAT:
4976 fp->Saturate = 1;
4977 case F_DST:
4978 fp->Opcode = FP_OPCODE_DST;
4979 break;
4980
4981 case F_MAX_SAT:
4982 fp->Saturate = 1;
4983 case F_MAX:
4984 fp->Opcode = FP_OPCODE_MAX;
4985 break;
4986
4987 case F_MIN_SAT:
4988 fp->Saturate = 1;
4989 case F_MIN:
4990 fp->Opcode = FP_OPCODE_MIN;
4991 break;
4992
4993 case F_MUL_SAT:
4994 fp->Saturate = 1;
4995 case F_MUL:
4996 fp->Opcode = FP_OPCODE_MUL;
4997 break;
4998
4999 case F_SGE_SAT:
5000 fp->Saturate = 1;
5001 case F_SGE:
5002 fp->Opcode = FP_OPCODE_SGE;
5003 break;
5004
5005 case F_SLT_SAT:
5006 fp->Saturate = 1;
5007 case F_SLT:
5008 fp->Opcode = FP_OPCODE_SLT;
5009 break;
5010
5011 case F_SUB_SAT:
5012 fp->Saturate = 1;
5013 case F_SUB:
5014 fp->Opcode = FP_OPCODE_SUB;
5015 break;
5016
5017 case F_XPD_SAT:
5018 fp->Saturate = 1;
5019 case F_XPD:
5020 fp->Opcode = FP_OPCODE_X2D;
5021 break;
5022 }
5023
5024 if (parse_masked_dst_reg
5025 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
5026 &fp->DstReg.Index, fp->DstReg.WriteMask))
5027 return 1;
5028 for (a = 0; a < 2; a++) {
5029 fp->SrcReg[a].Abs = GL_FALSE;
5030 fp->SrcReg[a].NegateAbs = GL_FALSE;
5031 if (parse_vector_src_reg
5032 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
5033 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
5034 swz))
5035 return 1;
5036 for (b=0; b<4; b++)
5037 fp->SrcReg[a].Swizzle[b] = swz[b];
5038 }
5039 break;
5040
5041 case F_ALU_TRI:
5042 switch (code) {
5043 case F_CMP_SAT:
5044 fp->Saturate = 1;
5045 case F_CMP:
5046 fp->Opcode = FP_OPCODE_CMP;
5047 break;
5048
5049 case F_LRP_SAT:
5050 fp->Saturate = 1;
5051 case F_LRP:
5052 fp->Opcode = FP_OPCODE_LRP;
5053 break;
5054
5055 case F_MAD_SAT:
5056 fp->Saturate = 1;
5057 case F_MAD:
5058 fp->Opcode = FP_OPCODE_MAD;
5059 break;
5060 }
5061
5062 if (parse_masked_dst_reg
5063 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
5064 &fp->DstReg.Index, fp->DstReg.WriteMask))
5065 return 1;
5066 for (a = 0; a < 3; a++) {
5067 fp->SrcReg[a].Abs = GL_FALSE;
5068 fp->SrcReg[a].NegateAbs = GL_FALSE;
5069 if (parse_vector_src_reg
5070 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[a].File,
5071 &fp->SrcReg[a].Index, &fp->SrcReg[a].NegateBase,
5072 swz))
5073 return 1;
5074 for (b=0; b<4; b++)
5075 fp->SrcReg[a].Swizzle[b] = swz[b];
5076 }
5077 break;
5078
5079 case F_ALU_SWZ:
5080 switch (code) {
5081 case F_SWZ_SAT:
5082 fp->Saturate = 1;
5083 case F_SWZ:
5084 fp->Opcode = FP_OPCODE_SWZ;
5085 break;
5086 }
5087 if (parse_masked_dst_reg
5088 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
5089 &fp->DstReg.Index, fp->DstReg.WriteMask))
5090 return 1;
5091
5092 if (parse_src_reg
5093 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
5094 &fp->SrcReg[0].Index))
5095 return 1;
5096 parse_extended_swizzle_mask (inst, swz,
5097 &fp->SrcReg[0].NegateBase);
5098 for (b=0; b<4; b++)
5099 fp->SrcReg[0].Swizzle[b] = swz[b];
5100 break;
5101
5102 case F_TEX_SAMPLE:
5103 switch (code) {
5104 case F_TEX_SAT:
5105 fp->Saturate = 1;
5106 case F_TEX:
5107 fp->Opcode = FP_OPCODE_TEX;
5108 break;
5109
5110 case F_TXP_SAT:
5111 fp->Saturate = 1;
5112 case F_TXP:
5113 fp->Opcode = FP_OPCODE_TXP;
5114 break;
5115
5116 case F_TXB_SAT:
5117 fp->Saturate = 1;
5118 case F_TXB:
5119 fp->Opcode = FP_OPCODE_TXB;
5120 break;
5121 }
5122
5123 if (parse_masked_dst_reg
5124 (ctx, inst, vc_head, Program, (GLint *) & fp->DstReg.File,
5125 &fp->DstReg.Index, fp->DstReg.WriteMask))
5126 return 1;
5127 fp->SrcReg[0].Abs = GL_FALSE;
5128 fp->SrcReg[0].NegateAbs = GL_FALSE;
5129 if (parse_vector_src_reg
5130 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
5131 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
5132 swz))
5133 return 1;
5134 for (b=0; b<4; b++)
5135 fp->SrcReg[0].Swizzle[b] = swz[b];
5136
5137 /* texImageUnit */
5138 if (parse_texcoord_num (ctx, inst, Program, &texcoord))
5139 return 1;
5140 fp->TexSrcUnit = texcoord;
5141
5142 /* texTarget */
5143 switch (*(*inst)++) {
5144 case TEXTARGET_1D:
5145 fp->TexSrcBit = TEXTURE_1D_BIT;
5146 break;
5147 case TEXTARGET_2D:
5148 fp->TexSrcBit = TEXTURE_2D_BIT;
5149 break;
5150 case TEXTARGET_3D:
5151 fp->TexSrcBit = TEXTURE_3D_BIT;
5152 break;
5153 case TEXTARGET_RECT:
5154 fp->TexSrcBit = TEXTURE_RECT_BIT;
5155 break;
5156 case TEXTARGET_CUBE:
5157 fp->TexSrcBit = TEXTURE_CUBE_BIT;
5158 break;
5159 }
5160 break;
5161
5162 case F_TEX_KIL:
5163 fp->Opcode = FP_OPCODE_KIL;
5164 fp->SrcReg[0].Abs = GL_FALSE;
5165 fp->SrcReg[0].NegateAbs = GL_FALSE;
5166 if (parse_vector_src_reg
5167 (ctx, inst, vc_head, Program, (GLint *) & fp->SrcReg[0].File,
5168 &fp->SrcReg[0].Index, &fp->SrcReg[0].NegateBase,
5169 swz))
5170 return 1;
5171 for (b=0; b<4; b++)
5172 fp->SrcReg[0].Swizzle[b] = swz[b];
5173 break;
5174 }
5175
5176 return 0;
5177 }
5178
5179 /**
5180 * This is a big mother that handles getting opcodes into the instruction
5181 * and handling the src & dst registers for vertex program instructions
5182 */
5183 static GLuint
5184 parse_vp_instruction (GLcontext * ctx, GLubyte ** inst,
5185 struct var_cache **vc_head, struct arb_program *Program,
5186 struct vp_instruction *vp)
5187 {
5188 GLint a;
5189 GLubyte type, code;
5190
5191 /* V_GEN_{ARL, VECTOR, SCALAR, BINSC, BIN, TRI, SWZ} */
5192 type = *(*inst)++;
5193
5194 /* The actual opcode name */
5195 code = *(*inst)++;
5196
5197 vp->SrcReg[0].RelAddr = vp->SrcReg[1].RelAddr = vp->SrcReg[2].RelAddr = 0;
5198
5199 for (a = 0; a < 4; a++) {
5200 vp->SrcReg[0].Swizzle[a] = a;
5201 vp->SrcReg[1].Swizzle[a] = a;
5202 vp->SrcReg[2].Swizzle[a] = a;
5203 vp->DstReg.WriteMask[a] = 1;
5204 }
5205
5206 switch (type) {
5207 /* XXX: */
5208 case V_GEN_ARL:
5209 vp->Opcode = VP_OPCODE_ARL;
5210
5211 /* Remember to set SrcReg.RelAddr; */
5212
5213 /* Get the masked address register [dst] */
5214 if (parse_masked_address_reg
5215 (ctx, inst, vc_head, Program, &vp->DstReg.Index,
5216 vp->DstReg.WriteMask))
5217 return 1;
5218 vp->DstReg.File = PROGRAM_ADDRESS;
5219
5220
5221 /* Get a scalar src register */
5222 if (parse_scalar_src_reg
5223 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
5224 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
5225 vp->SrcReg[0].Swizzle))
5226 return 1;
5227
5228 break;
5229
5230 case V_GEN_VECTOR:
5231 switch (code) {
5232 case V_ABS:
5233 vp->Opcode = VP_OPCODE_ABS;
5234 break;
5235 case V_FLR:
5236 vp->Opcode = VP_OPCODE_FLR;
5237 break;
5238 case V_FRC:
5239 vp->Opcode = VP_OPCODE_FRC;
5240 break;
5241 case V_LIT:
5242 vp->Opcode = VP_OPCODE_LIT;
5243 break;
5244 case V_MOV:
5245 vp->Opcode = VP_OPCODE_MOV;
5246 break;
5247 }
5248 if (parse_masked_dst_reg
5249 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5250 &vp->DstReg.Index, vp->DstReg.WriteMask))
5251 return 1;
5252 if (parse_vector_src_reg
5253 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
5254 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
5255 vp->SrcReg[0].Swizzle))
5256 return 1;
5257 break;
5258
5259 case V_GEN_SCALAR:
5260 switch (code) {
5261 case V_EX2:
5262 vp->Opcode = VP_OPCODE_EX2;
5263 break;
5264 case V_EXP:
5265 vp->Opcode = VP_OPCODE_EXP;
5266 break;
5267 case V_LG2:
5268 vp->Opcode = VP_OPCODE_LG2;
5269 break;
5270 case V_LOG:
5271 vp->Opcode = VP_OPCODE_LOG;
5272 break;
5273 case V_RCP:
5274 vp->Opcode = VP_OPCODE_RCP;
5275 break;
5276 case V_RSQ:
5277 vp->Opcode = VP_OPCODE_RSQ;
5278 break;
5279 }
5280 if (parse_masked_dst_reg
5281 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5282 &vp->DstReg.Index, vp->DstReg.WriteMask))
5283 return 1;
5284 if (parse_scalar_src_reg
5285 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
5286 &vp->SrcReg[0].Index, &vp->SrcReg[0].Negate,
5287 vp->SrcReg[0].Swizzle))
5288 return 1;
5289 break;
5290
5291 case V_GEN_BINSC:
5292 switch (code) {
5293 case V_POW:
5294 vp->Opcode = VP_OPCODE_POW;
5295 break;
5296 }
5297 if (parse_masked_dst_reg
5298 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5299 &vp->DstReg.Index, vp->DstReg.WriteMask))
5300 return 1;
5301 for (a = 0; a < 2; a++) {
5302 if (parse_scalar_src_reg
5303 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
5304 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
5305 vp->SrcReg[a].Swizzle))
5306 return 1;
5307 }
5308 break;
5309
5310 case V_GEN_BIN:
5311 switch (code) {
5312 case V_ADD:
5313 vp->Opcode = VP_OPCODE_ADD;
5314 break;
5315 case V_DP3:
5316 vp->Opcode = VP_OPCODE_DP3;
5317 break;
5318 case V_DP4:
5319 vp->Opcode = VP_OPCODE_DP4;
5320 break;
5321 case V_DPH:
5322 vp->Opcode = VP_OPCODE_DPH;
5323 break;
5324 case V_DST:
5325 vp->Opcode = VP_OPCODE_DST;
5326 break;
5327 case V_MAX:
5328 vp->Opcode = VP_OPCODE_MAX;
5329 break;
5330 case V_MIN:
5331 vp->Opcode = VP_OPCODE_MIN;
5332 break;
5333 case V_MUL:
5334 vp->Opcode = VP_OPCODE_MUL;
5335 break;
5336 case V_SGE:
5337 vp->Opcode = VP_OPCODE_SGE;
5338 break;
5339 case V_SLT:
5340 vp->Opcode = VP_OPCODE_SLT;
5341 break;
5342 case V_SUB:
5343 vp->Opcode = VP_OPCODE_SUB;
5344 break;
5345 case V_XPD:
5346 vp->Opcode = VP_OPCODE_XPD;
5347 break;
5348 }
5349 if (parse_masked_dst_reg
5350 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5351 &vp->DstReg.Index, vp->DstReg.WriteMask))
5352 return 1;
5353 for (a = 0; a < 2; a++) {
5354 if (parse_vector_src_reg
5355 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
5356 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
5357 vp->SrcReg[a].Swizzle))
5358 return 1;
5359 }
5360 break;
5361
5362 case V_GEN_TRI:
5363 switch (code) {
5364 case V_MAD:
5365 vp->Opcode = VP_OPCODE_MAD;
5366 break;
5367 }
5368
5369 if (parse_masked_dst_reg
5370 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5371 &vp->DstReg.Index, vp->DstReg.WriteMask))
5372 return 1;
5373 for (a = 0; a < 3; a++) {
5374 if (parse_vector_src_reg
5375 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[a].File,
5376 &vp->SrcReg[a].Index, &vp->SrcReg[a].Negate,
5377 vp->SrcReg[a].Swizzle))
5378 return 1;
5379 }
5380 break;
5381
5382 case V_GEN_SWZ:
5383 switch (code) {
5384 case V_SWZ:
5385 vp->Opcode = VP_OPCODE_SWZ;
5386 break;
5387 }
5388 if (parse_masked_dst_reg
5389 (ctx, inst, vc_head, Program, (GLint *) & vp->DstReg.File,
5390 &vp->DstReg.Index, vp->DstReg.WriteMask))
5391 return 1;
5392
5393 if (parse_src_reg
5394 (ctx, inst, vc_head, Program, (GLint *) & vp->SrcReg[0].File,
5395 &vp->SrcReg[0].Index))
5396 return 1;
5397 parse_extended_swizzle_mask (inst, vp->SrcReg[0].Swizzle,
5398 &vp->SrcReg[0].Negate);
5399 break;
5400 }
5401 return 0;
5402 }
5403
5404 #if DEBUG_PARSING
5405
5406 static GLvoid
5407 print_state_token (GLint token)
5408 {
5409 switch (token) {
5410 case STATE_MATERIAL:
5411 fprintf (stderr, "STATE_MATERIAL ");
5412 break;
5413 case STATE_LIGHT:
5414 fprintf (stderr, "STATE_LIGHT ");
5415 break;
5416
5417 case STATE_LIGHTMODEL_AMBIENT:
5418 fprintf (stderr, "STATE_AMBIENT ");
5419 break;
5420
5421 case STATE_LIGHTMODEL_SCENECOLOR:
5422 fprintf (stderr, "STATE_SCENECOLOR ");
5423 break;
5424
5425 case STATE_LIGHTPROD:
5426 fprintf (stderr, "STATE_LIGHTPROD ");
5427 break;
5428
5429 case STATE_TEXGEN:
5430 fprintf (stderr, "STATE_TEXGEN ");
5431 break;
5432
5433 case STATE_FOG_COLOR:
5434 fprintf (stderr, "STATE_FOG_COLOR ");
5435 break;
5436
5437 case STATE_FOG_PARAMS:
5438 fprintf (stderr, "STATE_FOG_PARAMS ");
5439 break;
5440
5441 case STATE_CLIPPLANE:
5442 fprintf (stderr, "STATE_CLIPPLANE ");
5443 break;
5444
5445 case STATE_POINT_SIZE:
5446 fprintf (stderr, "STATE_POINT_SIZE ");
5447 break;
5448
5449 case STATE_POINT_ATTENUATION:
5450 fprintf (stderr, "STATE_ATTENUATION ");
5451 break;
5452
5453 case STATE_MATRIX:
5454 fprintf (stderr, "STATE_MATRIX ");
5455 break;
5456
5457 case STATE_MODELVIEW:
5458 fprintf (stderr, "STATE_MODELVIEW ");
5459 break;
5460
5461 case STATE_PROJECTION:
5462 fprintf (stderr, "STATE_PROJECTION ");
5463 break;
5464
5465 case STATE_MVP:
5466 fprintf (stderr, "STATE_MVP ");
5467 break;
5468
5469 case STATE_TEXTURE:
5470 fprintf (stderr, "STATE_TEXTURE ");
5471 break;
5472
5473 case STATE_PROGRAM:
5474 fprintf (stderr, "STATE_PROGRAM ");
5475 break;
5476
5477 case STATE_MATRIX_INVERSE:
5478 fprintf (stderr, "STATE_INVERSE ");
5479 break;
5480
5481 case STATE_MATRIX_TRANSPOSE:
5482 fprintf (stderr, "STATE_TRANSPOSE ");
5483 break;
5484
5485 case STATE_MATRIX_INVTRANS:
5486 fprintf (stderr, "STATE_INVTRANS ");
5487 break;
5488
5489 case STATE_AMBIENT:
5490 fprintf (stderr, "STATE_AMBIENT ");
5491 break;
5492
5493 case STATE_DIFFUSE:
5494 fprintf (stderr, "STATE_DIFFUSE ");
5495 break;
5496
5497 case STATE_SPECULAR:
5498 fprintf (stderr, "STATE_SPECULAR ");
5499 break;
5500
5501 case STATE_EMISSION:
5502 fprintf (stderr, "STATE_EMISSION ");
5503 break;
5504
5505 case STATE_SHININESS:
5506 fprintf (stderr, "STATE_SHININESS ");
5507 break;
5508
5509 case STATE_HALF:
5510 fprintf (stderr, "STATE_HALF ");
5511 break;
5512
5513 case STATE_POSITION:
5514 fprintf (stderr, "STATE_POSITION ");
5515 break;
5516
5517 case STATE_ATTENUATION:
5518 fprintf (stderr, "STATE_ATTENUATION ");
5519 break;
5520
5521 case STATE_SPOT_DIRECTION:
5522 fprintf (stderr, "STATE_DIRECTION ");
5523 break;
5524
5525 case STATE_TEXGEN_EYE_S:
5526 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
5527 break;
5528
5529 case STATE_TEXGEN_EYE_T:
5530 fprintf (stderr, "STATE_TEXGEN_EYE_T ");
5531 break;
5532
5533 case STATE_TEXGEN_EYE_R:
5534 fprintf (stderr, "STATE_TEXGEN_EYE_R ");
5535 break;
5536
5537 case STATE_TEXGEN_EYE_Q:
5538 fprintf (stderr, "STATE_TEXGEN_EYE_Q ");
5539 break;
5540
5541 case STATE_TEXGEN_OBJECT_S:
5542 fprintf (stderr, "STATE_TEXGEN_EYE_S ");
5543 break;
5544
5545 case STATE_TEXGEN_OBJECT_T:
5546 fprintf (stderr, "STATE_TEXGEN_OBJECT_T ");
5547 break;
5548
5549 case STATE_TEXGEN_OBJECT_R:
5550 fprintf (stderr, "STATE_TEXGEN_OBJECT_R ");
5551 break;
5552
5553 case STATE_TEXGEN_OBJECT_Q:
5554 fprintf (stderr, "STATE_TEXGEN_OBJECT_Q ");
5555 break;
5556
5557 case STATE_TEXENV_COLOR:
5558 fprintf (stderr, "STATE_TEXENV_COLOR ");
5559 break;
5560
5561 case STATE_DEPTH_RANGE:
5562 fprintf (stderr, "STATE_DEPTH_RANGE ");
5563 break;
5564
5565 case STATE_VERTEX_PROGRAM:
5566 fprintf (stderr, "STATE_VERTEX_PROGRAM ");
5567 break;
5568
5569 case STATE_FRAGMENT_PROGRAM:
5570 fprintf (stderr, "STATE_FRAGMENT_PROGRAM ");
5571 break;
5572
5573 case STATE_ENV:
5574 fprintf (stderr, "STATE_ENV ");
5575 break;
5576
5577 case STATE_LOCAL:
5578 fprintf (stderr, "STATE_LOCAL ");
5579 break;
5580
5581 }
5582 fprintf (stderr, "[%d] ", token);
5583 }
5584
5585
5586 static GLvoid
5587 debug_variables (GLcontext * ctx, struct var_cache *vc_head,
5588 struct arb_program *Program)
5589 {
5590 struct var_cache *vc;
5591 GLint a, b;
5592
5593 fprintf (stderr, "debug_variables, vc_head: %x\n", vc_head);
5594
5595 /* First of all, print out the contents of the var_cache */
5596 vc = vc_head;
5597 while (vc) {
5598 fprintf (stderr, "[%x]\n", vc);
5599 switch (vc->type) {
5600 case vt_none:
5601 fprintf (stderr, "UNDEFINED %s\n", vc->name);
5602 break;
5603 case vt_attrib:
5604 fprintf (stderr, "ATTRIB %s\n", vc->name);
5605 fprintf (stderr, " binding: 0x%x\n", vc->attrib_binding);
5606 break;
5607 case vt_param:
5608 fprintf (stderr, "PARAM %s begin: %d len: %d\n", vc->name,
5609 vc->param_binding_begin, vc->param_binding_length);
5610 b = vc->param_binding_begin;
5611 for (a = 0; a < vc->param_binding_length; a++) {
5612 fprintf (stderr, "%s\n",
5613 Program->Parameters->Parameters[a + b].Name);
5614 if (Program->Parameters->Parameters[a + b].Type == STATE) {
5615 print_state_token (Program->Parameters->Parameters[a + b].
5616 StateIndexes[0]);
5617 print_state_token (Program->Parameters->Parameters[a + b].
5618 StateIndexes[1]);
5619 print_state_token (Program->Parameters->Parameters[a + b].
5620 StateIndexes[2]);
5621 print_state_token (Program->Parameters->Parameters[a + b].
5622 StateIndexes[3]);
5623 print_state_token (Program->Parameters->Parameters[a + b].
5624 StateIndexes[4]);
5625 print_state_token (Program->Parameters->Parameters[a + b].
5626 StateIndexes[5]);
5627 }
5628 else
5629 fprintf (stderr, "%f %f %f %f\n",
5630 Program->Parameters->Parameters[a + b].Values[0],
5631 Program->Parameters->Parameters[a + b].Values[1],
5632 Program->Parameters->Parameters[a + b].Values[2],
5633 Program->Parameters->Parameters[a + b].Values[3]);
5634 }
5635 break;
5636 case vt_temp:
5637 fprintf (stderr, "TEMP %s\n", vc->name);
5638 fprintf (stderr, " binding: 0x%x\n", vc->temp_binding);
5639 break;
5640 case vt_output:
5641 fprintf (stderr, "OUTPUT %s\n", vc->name);
5642 fprintf (stderr, " binding: 0x%x\n", vc->output_binding);
5643 break;
5644 case vt_alias:
5645 fprintf (stderr, "ALIAS %s\n", vc->name);
5646 fprintf (stderr, " binding: 0x%x (%s)\n",
5647 vc->alias_binding, vc->alias_binding->name);
5648 break;
5649 }
5650 vc = vc->next;
5651 }
5652 }
5653
5654 #endif
5655
5656
5657 /**
5658 * The main loop for parsing a fragment or vertex program
5659 *
5660 * \return 0 on sucess, 1 on error
5661 */
5662 static GLint
5663 parse_arb_program (GLcontext * ctx, GLubyte * inst, struct var_cache **vc_head,
5664 struct arb_program *Program)
5665 {
5666 GLint err = 0;
5667
5668 Program->MajorVersion = (GLuint) * inst++;
5669 Program->MinorVersion = (GLuint) * inst++;
5670
5671 while (*inst != END) {
5672 switch (*inst++) {
5673 /* XXX: */
5674 case OPTION:
5675
5676 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
5677 switch (*inst++) {
5678 case ARB_PRECISION_HINT_FASTEST:
5679 Program->HintPrecisionFastest = 1;
5680 break;
5681
5682 case ARB_PRECISION_HINT_NICEST:
5683 Program->HintPrecisionNicest = 1;
5684 break;
5685
5686 case ARB_FOG_EXP:
5687 Program->HintFogExp = 1;
5688 break;
5689
5690 case ARB_FOG_EXP2:
5691 Program->HintFogExp2 = 1;
5692 break;
5693
5694 case ARB_FOG_LINEAR:
5695 Program->HintFogLinear = 1;
5696 break;
5697 }
5698 }
5699 else {
5700 switch (*inst++) {
5701 case ARB_POSITION_INVARIANT:
5702 Program->HintPositionInvariant = 1;
5703 break;
5704 }
5705 }
5706 break;
5707
5708 case INSTRUCTION:
5709 Program->Position = parse_position (&inst);
5710
5711 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
5712 /* Realloc Program->FPInstructions */
5713 Program->FPInstructions =
5714 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
5715 Program->Base.NumInstructions*sizeof(struct fp_instruction),
5716 (Program->Base.NumInstructions+1)*sizeof (struct fp_instruction));
5717
5718 /* parse the current instruction */
5719 err = parse_fp_instruction (ctx, &inst, vc_head, Program,
5720 &Program->FPInstructions[Program->Base.NumInstructions]);
5721
5722 }
5723 else {
5724 /* Realloc Program->VPInstructions */
5725 Program->VPInstructions =
5726 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
5727 Program->Base.NumInstructions*sizeof(struct vp_instruction),
5728 (Program->Base.NumInstructions +1)*sizeof(struct vp_instruction));
5729
5730 /* parse the current instruction */
5731 err = parse_vp_instruction (ctx, &inst, vc_head, Program,
5732 &Program->VPInstructions[Program->Base.NumInstructions]);
5733 }
5734
5735 /* increment Program->Base.NumInstructions */
5736 Program->Base.NumInstructions++;
5737 break;
5738
5739 case DECLARATION:
5740 err = parse_declaration (ctx, &inst, vc_head, Program);
5741 break;
5742
5743 default:
5744 break;
5745 }
5746
5747 if (err)
5748 break;
5749 }
5750
5751 /* Finally, tag on an OPCODE_END instruction */
5752 if (Program->type == GL_FRAGMENT_PROGRAM_ARB) {
5753 Program->FPInstructions =
5754 (struct fp_instruction *) _mesa_realloc (Program->FPInstructions,
5755 Program->Base.NumInstructions*sizeof(struct fp_instruction),
5756 (Program->Base.NumInstructions+1)*sizeof(struct fp_instruction));
5757
5758 Program->FPInstructions[Program->Base.NumInstructions].Opcode = FP_OPCODE_END;
5759 }
5760 else {
5761 Program->VPInstructions =
5762 (struct vp_instruction *) _mesa_realloc (Program->VPInstructions,
5763 Program->Base.NumInstructions*sizeof(struct vp_instruction),
5764 (Program->Base.NumInstructions+1)*sizeof(struct vp_instruction));
5765
5766 Program->VPInstructions[Program->Base.NumInstructions].Opcode = VP_OPCODE_END;
5767 }
5768
5769 /* increment Program->Base.NumInstructions */
5770 Program->Base.NumInstructions++;
5771
5772 return err;
5773 }
5774
5775
5776 /**
5777 * This kicks everything off.
5778 *
5779 * \param ctx - The GL Context
5780 * \param str - The program string
5781 * \param len - The program string length
5782 * \param Program - The arb_program struct to return all the parsed info in
5783 * \return 0 on sucess, 1 on error
5784 */
5785 GLuint
5786 _mesa_parse_arb_program (GLcontext * ctx, const GLubyte * str, GLsizei len,
5787 struct arb_program * program)
5788 {
5789 GLint a, err, error_pos;
5790 char error_msg[300];
5791 GLuint parsed_len;
5792 struct var_cache *vc_head;
5793 dict *dt;
5794 GLubyte *parsed, *inst;
5795
5796 #if DEBUG_PARSING
5797 fprintf (stderr, "Loading grammar text!\n");
5798 #endif
5799 dt = grammar_load_from_text ((GLubyte *) arb_grammar_text);
5800 if (!dt) {
5801 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
5802 _mesa_set_program_error (ctx, error_pos, error_msg);
5803 _mesa_error (ctx, GL_INVALID_OPERATION,
5804 "Error loading grammer rule set");
5805 return 1;
5806 }
5807
5808 #if DEBUG_PARSING
5809 printf ("Checking Grammar!\n");
5810 #endif
5811 err = grammar_check (dt, str, &parsed, &parsed_len);
5812
5813
5814 /* Syntax parse error */
5815 if (err == 0) {
5816 grammar_get_last_error ((GLubyte *) error_msg, 300, &error_pos);
5817 _mesa_set_program_error (ctx, error_pos, error_msg);
5818 _mesa_error (ctx, GL_INVALID_OPERATION, "Parse Error");
5819
5820 dict_destroy (&dt);
5821 return 1;
5822 }
5823
5824 #if DEBUG_PARSING
5825 printf ("Destroying grammer dict [parse retval: %d]\n", err);
5826 #endif
5827 dict_destroy (&dt);
5828
5829 /* Initialize the arb_program struct */
5830 program->Base.NumInstructions =
5831 program->Base.NumTemporaries =
5832 program->Base.NumParameters =
5833 program->Base.NumAttributes = program->Base.NumAddressRegs = 0;
5834 program->Parameters = _mesa_new_parameter_list ();
5835 program->InputsRead = 0;
5836 program->OutputsWritten = 0;
5837 program->Position = 0;
5838 program->MajorVersion = program->MinorVersion = 0;
5839 program->HintPrecisionFastest =
5840 program->HintPrecisionNicest =
5841 program->HintFogExp2 =
5842 program->HintFogExp =
5843 program->HintFogLinear = program->HintPositionInvariant = 0;
5844 for (a = 0; a < MAX_TEXTURE_IMAGE_UNITS; a++)
5845 program->TexturesUsed[a] = 0;
5846 program->NumAluInstructions =
5847 program->NumTexInstructions =
5848 program->NumTexIndirections = 0;
5849
5850 program->FPInstructions = NULL;
5851 program->VPInstructions = NULL;
5852
5853 vc_head = NULL;
5854 err = 0;
5855
5856 /* Start examining the tokens in the array */
5857 inst = parsed;
5858
5859 /* Check the grammer rev */
5860 if (*inst++ != REVISION) {
5861 _mesa_set_program_error (ctx, 0, "Grammar version mismatch");
5862 _mesa_error (ctx, GL_INVALID_OPERATION, "Grammar verison mismatch");
5863 err = 1;
5864 }
5865 else {
5866 switch (*inst++) {
5867 case FRAGMENT_PROGRAM:
5868 program->type = GL_FRAGMENT_PROGRAM_ARB;
5869 break;
5870
5871 case VERTEX_PROGRAM:
5872 program->type = GL_VERTEX_PROGRAM_ARB;
5873 break;
5874 }
5875
5876 err = parse_arb_program (ctx, inst, &vc_head, program);
5877 #if DEBUG_PARSING
5878 fprintf (stderr, "Symantic analysis returns %d [1 is bad!]\n", err);
5879 #endif
5880 }
5881
5882 /*debug_variables(ctx, vc_head, program); */
5883
5884 /* We're done with the parsed binary array */
5885 var_cache_destroy (&vc_head);
5886
5887 _mesa_free (parsed);
5888 #if DEBUG_PARSING
5889 printf ("_mesa_parse_arb_program() done\n");
5890 #endif
5891 return err;
5892 }