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