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