OSDN Git Service

Adding Struct related types
[android-x86/external-swiftshader.git] / src / OpenGL / compiler / ParseHelper.cpp
1 //
2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "ParseHelper.h"
8
9 #include <stdarg.h>
10 #include <stdio.h>
11
12 #include "glslang.h"
13 #include "preprocessor/SourceLocation.h"
14
15 ///////////////////////////////////////////////////////////////////////
16 //
17 // Sub- vector and matrix fields
18 //
19 ////////////////////////////////////////////////////////////////////////
20
21 //
22 // Look at a '.' field selector string and change it into offsets
23 // for a vector.
24 //
25 bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
26 {
27     fields.num = (int) compString.size();
28     if (fields.num > 4) {
29         error(line, "illegal vector field selection", compString.c_str());
30         return false;
31     }
32
33     enum {
34         exyzw,
35         ergba,
36         estpq
37     } fieldSet[4];
38
39     for (int i = 0; i < fields.num; ++i) {
40         switch (compString[i])  {
41         case 'x':
42             fields.offsets[i] = 0;
43             fieldSet[i] = exyzw;
44             break;
45         case 'r':
46             fields.offsets[i] = 0;
47             fieldSet[i] = ergba;
48             break;
49         case 's':
50             fields.offsets[i] = 0;
51             fieldSet[i] = estpq;
52             break;
53         case 'y':
54             fields.offsets[i] = 1;
55             fieldSet[i] = exyzw;
56             break;
57         case 'g':
58             fields.offsets[i] = 1;
59             fieldSet[i] = ergba;
60             break;
61         case 't':
62             fields.offsets[i] = 1;
63             fieldSet[i] = estpq;
64             break;
65         case 'z':
66             fields.offsets[i] = 2;
67             fieldSet[i] = exyzw;
68             break;
69         case 'b':
70             fields.offsets[i] = 2;
71             fieldSet[i] = ergba;
72             break;
73         case 'p':
74             fields.offsets[i] = 2;
75             fieldSet[i] = estpq;
76             break;
77         case 'w':
78             fields.offsets[i] = 3;
79             fieldSet[i] = exyzw;
80             break;
81         case 'a':
82             fields.offsets[i] = 3;
83             fieldSet[i] = ergba;
84             break;
85         case 'q':
86             fields.offsets[i] = 3;
87             fieldSet[i] = estpq;
88             break;
89         default:
90             error(line, "illegal vector field selection", compString.c_str());
91             return false;
92         }
93     }
94
95     for (int i = 0; i < fields.num; ++i) {
96         if (fields.offsets[i] >= vecSize) {
97             error(line, "vector field selection out of range",  compString.c_str());
98             return false;
99         }
100
101         if (i > 0) {
102             if (fieldSet[i] != fieldSet[i-1]) {
103                 error(line, "illegal - vector component fields not from the same set", compString.c_str());
104                 return false;
105             }
106         }
107     }
108
109     return true;
110 }
111
112
113 //
114 // Look at a '.' field selector string and change it into offsets
115 // for a matrix.
116 //
117 bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, int line)
118 {
119     fields.wholeRow = false;
120     fields.wholeCol = false;
121     fields.row = -1;
122     fields.col = -1;
123
124     if (compString.size() != 2) {
125         error(line, "illegal length of matrix field selection", compString.c_str());
126         return false;
127     }
128
129     if (compString[0] == '_') {
130         if (compString[1] < '0' || compString[1] > '3') {
131             error(line, "illegal matrix field selection", compString.c_str());
132             return false;
133         }
134         fields.wholeCol = true;
135         fields.col = compString[1] - '0';
136     } else if (compString[1] == '_') {
137         if (compString[0] < '0' || compString[0] > '3') {
138             error(line, "illegal matrix field selection", compString.c_str());
139             return false;
140         }
141         fields.wholeRow = true;
142         fields.row = compString[0] - '0';
143     } else {
144         if (compString[0] < '0' || compString[0] > '3' ||
145             compString[1] < '0' || compString[1] > '3') {
146             error(line, "illegal matrix field selection", compString.c_str());
147             return false;
148         }
149         fields.row = compString[0] - '0';
150         fields.col = compString[1] - '0';
151     }
152
153     if (fields.row >= matRows || fields.col >= matCols) {
154         error(line, "matrix field selection out of range", compString.c_str());
155         return false;
156     }
157
158     return true;
159 }
160
161 ///////////////////////////////////////////////////////////////////////
162 //
163 // Errors
164 //
165 ////////////////////////////////////////////////////////////////////////
166
167 //
168 // Track whether errors have occurred.
169 //
170 void TParseContext::recover()
171 {
172 }
173
174 //
175 // Used by flex/bison to output all syntax and parsing errors.
176 //
177 void TParseContext::error(TSourceLoc loc,
178                           const char* reason, const char* token,
179                           const char* extraInfo)
180 {
181     pp::SourceLocation srcLoc;
182     DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
183     diagnostics.writeInfo(pp::Diagnostics::PP_ERROR,
184                           srcLoc, reason, token, extraInfo);
185
186 }
187
188 void TParseContext::warning(TSourceLoc loc,
189                             const char* reason, const char* token,
190                             const char* extraInfo) {
191     pp::SourceLocation srcLoc;
192     DecodeSourceLoc(loc, &srcLoc.file, &srcLoc.line);
193     diagnostics.writeInfo(pp::Diagnostics::PP_WARNING,
194                           srcLoc, reason, token, extraInfo);
195 }
196
197 void TParseContext::trace(const char* str)
198 {
199     diagnostics.writeDebug(str);
200 }
201
202 //
203 // Same error message for all places assignments don't work.
204 //
205 void TParseContext::assignError(int line, const char* op, TString left, TString right)
206 {
207     std::stringstream extraInfoStream;
208     extraInfoStream << "cannot convert from '" << right << "' to '" << left << "'";
209     std::string extraInfo = extraInfoStream.str();
210     error(line, "", op, extraInfo.c_str());
211 }
212
213 //
214 // Same error message for all places unary operations don't work.
215 //
216 void TParseContext::unaryOpError(int line, const char* op, TString operand)
217 {
218     std::stringstream extraInfoStream;
219     extraInfoStream << "no operation '" << op << "' exists that takes an operand of type " << operand
220                     << " (or there is no acceptable conversion)";
221     std::string extraInfo = extraInfoStream.str();
222     error(line, " wrong operand type", op, extraInfo.c_str());
223 }
224
225 //
226 // Same error message for all binary operations don't work.
227 //
228 void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
229 {
230     std::stringstream extraInfoStream;
231     extraInfoStream << "no operation '" << op << "' exists that takes a left-hand operand of type '" << left 
232                     << "' and a right operand of type '" << right << "' (or there is no acceptable conversion)";
233     std::string extraInfo = extraInfoStream.str();
234     error(line, " wrong operand types ", op, extraInfo.c_str());
235 }
236
237 bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
238     if (!checksPrecisionErrors)
239         return false;
240     switch( type ){
241     case EbtFloat:
242         if( precision == EbpUndefined ){
243             error( line, "No precision specified for (float)", "" );
244             return true;
245         }
246         break;
247     case EbtInt:
248         if( precision == EbpUndefined ){
249             error( line, "No precision specified (int)", "" );
250             return true;
251         }
252         break;
253     default:
254         return false;
255     }
256     return false;
257 }
258
259 //
260 // Both test and if necessary, spit out an error, to see if the node is really
261 // an l-value that can be operated on this way.
262 //
263 // Returns true if the was an error.
264 //
265 bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
266 {
267     TIntermSymbol* symNode = node->getAsSymbolNode();
268     TIntermBinary* binaryNode = node->getAsBinaryNode();
269
270     if (binaryNode) {
271         bool errorReturn;
272
273         switch(binaryNode->getOp()) {
274         case EOpIndexDirect:
275         case EOpIndexIndirect:
276         case EOpIndexDirectStruct:
277             return lValueErrorCheck(line, op, binaryNode->getLeft());
278         case EOpVectorSwizzle:
279             errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
280             if (!errorReturn) {
281                 int offset[4] = {0,0,0,0};
282
283                 TIntermTyped* rightNode = binaryNode->getRight();
284                 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
285
286                 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
287                                                p != aggrNode->getSequence().end(); p++) {
288                     int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0);
289                     offset[value]++;
290                     if (offset[value] > 1) {
291                         error(line, " l-value of swizzle cannot have duplicate components", op);
292
293                         return true;
294                     }
295                 }
296             }
297
298             return errorReturn;
299         default:
300             break;
301         }
302         error(line, " l-value required", op);
303
304         return true;
305     }
306
307
308     const char* symbol = 0;
309     if (symNode != 0)
310         symbol = symNode->getSymbol().c_str();
311
312     const char* message = 0;
313     switch (node->getQualifier()) {
314     case EvqConstExpr:      message = "can't modify a const";        break;
315     case EvqConstReadOnly:  message = "can't modify a const";        break;
316     case EvqAttribute:      message = "can't modify an attribute";   break;
317     case EvqFragmentIn:     message = "can't modify an input";       break;
318     case EvqVertexIn:       message = "can't modify an input";       break;
319     case EvqUniform:        message = "can't modify a uniform";      break;
320     case EvqSmoothIn:
321     case EvqFlatIn:
322     case EvqCentroidIn:
323     case EvqVaryingIn:      message = "can't modify a varying";      break;
324     case EvqInput:          message = "can't modify an input";       break;
325     case EvqFragCoord:      message = "can't modify gl_FragCoord";   break;
326     case EvqFrontFacing:    message = "can't modify gl_FrontFacing"; break;
327     case EvqPointCoord:     message = "can't modify gl_PointCoord";  break;
328     case EvqInstanceID:     message = "can't modify gl_InstanceID";  break;
329     default:
330
331         //
332         // Type that can't be written to?
333         //
334         if(IsSampler(node->getBasicType()))
335         {
336             message = "can't modify a sampler";
337         }
338         else if(node->getBasicType() == EbtVoid)
339         {
340             message = "can't modify void";
341         }
342     }
343
344     if (message == 0 && binaryNode == 0 && symNode == 0) {
345         error(line, " l-value required", op);
346
347         return true;
348     }
349
350
351     //
352     // Everything else is okay, no error.
353     //
354     if (message == 0)
355         return false;
356
357     //
358     // If we get here, we have an error and a message.
359     //
360     if (symNode) {
361         std::stringstream extraInfoStream;
362         extraInfoStream << "\"" << symbol << "\" (" << message << ")";
363         std::string extraInfo = extraInfoStream.str();
364         error(line, " l-value required", op, extraInfo.c_str());
365     }
366     else {
367         std::stringstream extraInfoStream;
368         extraInfoStream << "(" << message << ")";
369         std::string extraInfo = extraInfoStream.str();
370         error(line, " l-value required", op, extraInfo.c_str());
371     }
372
373     return true;
374 }
375
376 //
377 // Both test, and if necessary spit out an error, to see if the node is really
378 // a constant.
379 //
380 // Returns true if the was an error.
381 //
382 bool TParseContext::constErrorCheck(TIntermTyped* node)
383 {
384     if (node->getQualifier() == EvqConstExpr)
385         return false;
386
387     error(node->getLine(), "constant expression required", "");
388
389     return true;
390 }
391
392 //
393 // Both test, and if necessary spit out an error, to see if the node is really
394 // an integer.
395 //
396 // Returns true if the was an error.
397 //
398 bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
399 {
400     if (node->isScalarInt())
401         return false;
402
403     error(node->getLine(), "integer expression required", token);
404
405     return true;
406 }
407
408 //
409 // Both test, and if necessary spit out an error, to see if we are currently
410 // globally scoped.
411 //
412 // Returns true if the was an error.
413 //
414 bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
415 {
416     if (global)
417         return false;
418
419     error(line, "only allowed at global scope", token);
420
421     return true;
422 }
423
424 //
425 // For now, keep it simple:  if it starts "gl_", it's reserved, independent
426 // of scope.  Except, if the symbol table is at the built-in push-level,
427 // which is when we are parsing built-ins.
428 // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
429 // webgl shader.
430 //
431 // Returns true if there was an error.
432 //
433 bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
434 {
435     static const char* reservedErrMsg = "reserved built-in name";
436     if (!symbolTable.atBuiltInLevel()) {
437         if (identifier.compare(0, 3, "gl_") == 0) {
438             error(line, reservedErrMsg, "gl_");
439             return true;
440         }
441         if (identifier.find("__") != TString::npos) {
442             error(line, "identifiers containing two consecutive underscores (__) are reserved as possible future keywords", identifier.c_str());
443             return true;
444         }
445     }
446
447     return false;
448 }
449
450 //
451 // Make sure there is enough data provided to the constructor to build
452 // something of the type of the constructor.  Also returns the type of
453 // the constructor.
454 //
455 // Returns true if there was an error in construction.
456 //
457 bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
458 {
459     *type = function.getReturnType();
460
461     bool constructingMatrix = false;
462     switch(op) {
463     case EOpConstructMat2:
464     case EOpConstructMat3:
465     case EOpConstructMat4:
466         constructingMatrix = true;
467         break;
468     default:
469         break;
470     }
471
472     //
473     // Note: It's okay to have too many components available, but not okay to have unused
474     // arguments.  'full' will go to true when enough args have been seen.  If we loop
475     // again, there is an extra argument, so 'overfull' will become true.
476     //
477
478     int size = 0;
479     bool constType = true;
480     bool full = false;
481     bool overFull = false;
482     bool matrixInMatrix = false;
483     bool arrayArg = false;
484     for (int i = 0; i < function.getParamCount(); ++i) {
485         const TParameter& param = function.getParam(i);
486         size += param.type->getObjectSize();
487
488         if (constructingMatrix && param.type->isMatrix())
489             matrixInMatrix = true;
490         if (full)
491             overFull = true;
492         if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
493             full = true;
494         if (param.type->getQualifier() != EvqConstExpr)
495             constType = false;
496         if (param.type->isArray())
497             arrayArg = true;
498     }
499
500     if (constType)
501         type->setQualifier(EvqConstExpr);
502
503     if (type->isArray() && type->getArraySize() != function.getParamCount()) {
504         error(line, "array constructor needs one argument per array element", "constructor");
505         return true;
506     }
507
508     if (arrayArg && op != EOpConstructStruct) {
509         error(line, "constructing from a non-dereferenced array", "constructor");
510         return true;
511     }
512
513     if (matrixInMatrix && !type->isArray()) {
514         if (function.getParamCount() != 1) {
515           error(line, "constructing matrix from matrix can only take one argument", "constructor");
516           return true;
517         }
518     }
519
520     if (overFull) {
521         error(line, "too many arguments", "constructor");
522         return true;
523     }
524
525     if (op == EOpConstructStruct && !type->isArray() && int(type->getStruct()->fields().size()) != function.getParamCount()) {
526         error(line, "Number of constructor parameters does not match the number of structure fields", "constructor");
527         return true;
528     }
529
530     if (!type->isMatrix() || !matrixInMatrix) {
531         if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
532             (op == EOpConstructStruct && size < type->getObjectSize())) {
533             error(line, "not enough data provided for construction", "constructor");
534             return true;
535         }
536     }
537
538     TIntermTyped *typed = node ? node->getAsTyped() : 0;
539     if (typed == 0) {
540         error(line, "constructor argument does not have a type", "constructor");
541         return true;
542     }
543     if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
544         error(line, "cannot convert a sampler", "constructor");
545         return true;
546     }
547     if (typed->getBasicType() == EbtVoid) {
548         error(line, "cannot convert a void", "constructor");
549         return true;
550     }
551
552     return false;
553 }
554
555 // This function checks to see if a void variable has been declared and raise an error message for such a case
556 //
557 // returns true in case of an error
558 //
559 bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
560 {
561     if (pubType.type == EbtVoid) {
562         error(line, "illegal use of type 'void'", identifier.c_str());
563         return true;
564     }
565
566     return false;
567 }
568
569 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
570 //
571 // returns true in case of an error
572 //
573 bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
574 {
575     if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
576         error(line, "boolean expression expected", "");
577         return true;
578     }
579
580     return false;
581 }
582
583 // This function checks to see if the node (for the expression) contains a scalar boolean expression or not
584 //
585 // returns true in case of an error
586 //
587 bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
588 {
589     if (pType.type != EbtBool || pType.array || (pType.primarySize > 1) || (pType.secondarySize > 1)) {
590         error(line, "boolean expression expected", "");
591         return true;
592     }
593
594     return false;
595 }
596
597 bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
598 {
599     if (pType.type == EbtStruct) {
600         if (containsSampler(*pType.userDef)) {
601             error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
602
603             return true;
604         }
605
606         return false;
607     } else if (IsSampler(pType.type)) {
608         error(line, reason, getBasicString(pType.type));
609
610         return true;
611     }
612
613     return false;
614 }
615
616 bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
617 {
618         switch(pType.qualifier)
619         {
620         case EvqVaryingOut:
621         case EvqSmooth:
622         case EvqFlat:
623         case EvqCentroidOut:
624         case EvqVaryingIn:
625         case EvqSmoothIn:
626         case EvqFlatIn:
627         case EvqCentroidIn:
628         case EvqAttribute:
629         case EvqVertexIn:
630         case EvqFragmentOut:
631                 if(pType.type == EbtStruct)
632                 {
633                         error(line, "cannot be used with a structure", getQualifierString(pType.qualifier));
634
635                         return true;
636                 }
637                 break;
638         default:
639                 break;
640         }
641
642     if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
643         return true;
644
645         // check for layout qualifier issues
646         const TLayoutQualifier layoutQualifier = pType.layoutQualifier;
647
648         if (pType.qualifier != EvqVertexIn && pType.qualifier != EvqFragmentOut &&
649             layoutLocationErrorCheck(line, pType.layoutQualifier))
650         {
651                 return true;
652         }
653
654     return false;
655 }
656
657 bool TParseContext::layoutLocationErrorCheck(const TSourceLoc &location, const TLayoutQualifier &layoutQualifier)\r
658 {\r
659         if(layoutQualifier.location != -1)\r
660         {\r
661                 error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs");\r
662                 return true;\r
663         }\r
664 \r
665         return false;\r
666 }\r
667
668 bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
669 {
670     if ((qualifier == EvqOut || qualifier == EvqInOut) &&
671              type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
672         error(line, "samplers cannot be output parameters", type.getBasicString());
673         return true;
674     }
675
676     return false;
677 }
678
679 bool TParseContext::containsSampler(TType& type)
680 {
681     if (IsSampler(type.getBasicType()))
682         return true;
683
684     if (type.getBasicType() == EbtStruct) {
685         const TFieldList& fields = type.getStruct()->fields();
686         for(unsigned int i = 0; i < fields.size(); ++i) {
687             if (containsSampler(*fields[i]->type()))
688                 return true;
689         }
690     }
691
692     return false;
693 }
694
695 //
696 // Do size checking for an array type's size.
697 //
698 // Returns true if there was an error.
699 //
700 bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
701 {
702     TIntermConstantUnion* constant = expr->getAsConstantUnion();
703
704     if (constant == 0 || !constant->isScalarInt())
705     {
706         error(line, "array size must be a constant integer expression", "");
707         return true;
708     }
709
710     if (constant->getBasicType() == EbtUInt)
711     {
712         unsigned int uintSize = constant->getUConst(0);
713         if (uintSize > static_cast<unsigned int>(std::numeric_limits<int>::max()))
714         {
715             error(line, "array size too large", "");
716             size = 1;
717             return true;
718         }
719
720         size = static_cast<int>(uintSize);
721     }
722     else
723     {
724         size = constant->getIConst(0);
725
726         if (size <= 0)
727         {
728             error(line, "array size must be a positive integer", "");
729             size = 1;
730             return true;
731         }
732     }
733
734     return false;
735 }
736
737 //
738 // See if this qualifier can be an array.
739 //
740 // Returns true if there is an error.
741 //
742 bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
743 {
744     if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConstExpr)) {
745         error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str());
746         return true;
747     }
748
749     return false;
750 }
751
752 //
753 // See if this type can be an array.
754 //
755 // Returns true if there is an error.
756 //
757 bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
758 {
759     //
760     // Can the type be an array?
761     //
762     if (type.array) {
763         error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str());
764         return true;
765     }
766
767     return false;
768 }
769
770 //
771 // Do all the semantic checking for declaring an array, with and
772 // without a size, and make the right changes to the symbol table.
773 //
774 // size == 0 means no specified size.
775 //
776 // Returns true if there was an error.
777 //
778 bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
779 {
780     //
781     // Don't check for reserved word use until after we know it's not in the symbol table,
782     // because reserved arrays can be redeclared.
783     //
784
785     bool builtIn = false;
786     bool sameScope = false;
787     TSymbol* symbol = symbolTable.find(identifier, shaderVersion, &builtIn, &sameScope);
788     if (symbol == 0 || !sameScope) {
789         if (reservedErrorCheck(line, identifier))
790             return true;
791
792         variable = new TVariable(&identifier, TType(type));
793
794         if (type.arraySize)
795             variable->getType().setArraySize(type.arraySize);
796
797         if (! symbolTable.declare(*variable)) {
798             delete variable;
799             error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str());
800             return true;
801         }
802     } else {
803         if (! symbol->isVariable()) {
804             error(line, "variable expected", identifier.c_str());
805             return true;
806         }
807
808         variable = static_cast<TVariable*>(symbol);
809         if (! variable->getType().isArray()) {
810             error(line, "redeclaring non-array as array", identifier.c_str());
811             return true;
812         }
813         if (variable->getType().getArraySize() > 0) {
814             error(line, "redeclaration of array with size", identifier.c_str());
815             return true;
816         }
817
818         if (! variable->getType().sameElementType(TType(type))) {
819             error(line, "redeclaration of array with a different type", identifier.c_str());
820             return true;
821         }
822
823         TType* t = variable->getArrayInformationType();
824         while (t != 0) {
825             if (t->getMaxArraySize() > type.arraySize) {
826                 error(line, "higher index value already used for the array", identifier.c_str());
827                 return true;
828             }
829             t->setArraySize(type.arraySize);
830             t = t->getArrayInformationType();
831         }
832
833         if (type.arraySize)
834             variable->getType().setArraySize(type.arraySize);
835     }
836
837     if (voidErrorCheck(line, identifier, type))
838         return true;
839
840     return false;
841 }
842
843 bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
844 {
845     bool builtIn = false;
846     TSymbol* symbol = symbolTable.find(node->getSymbol(), shaderVersion, &builtIn);
847     if (symbol == 0) {
848         error(line, " undeclared identifier", node->getSymbol().c_str());
849         return true;
850     }
851     TVariable* variable = static_cast<TVariable*>(symbol);
852
853     type->setArrayInformationType(variable->getArrayInformationType());
854     variable->updateArrayInformationType(type);
855
856     // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
857     // its an error
858     if (node->getSymbol() == "gl_FragData") {
859         TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", shaderVersion, &builtIn);
860         ASSERT(fragData);
861
862         int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
863         if (fragDataValue <= size) {
864             error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers");
865             return true;
866         }
867     }
868
869     // we dont want to update the maxArraySize when this flag is not set, we just want to include this
870     // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
871     if (!updateFlag)
872         return false;
873
874     size++;
875     variable->getType().setMaxArraySize(size);
876     type->setMaxArraySize(size);
877     TType* tt = type;
878
879     while(tt->getArrayInformationType() != 0) {
880         tt = tt->getArrayInformationType();
881         tt->setMaxArraySize(size);
882     }
883
884     return false;
885 }
886
887 //
888 // Enforce non-initializer type/qualifier rules.
889 //
890 // Returns true if there was an error.
891 //
892 bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array)
893 {
894     if (type.qualifier == EvqConstExpr)
895     {
896         // Make the qualifier make sense.
897         type.qualifier = EvqTemporary;
898
899         if (array)
900         {
901             error(line, "arrays may not be declared constant since they cannot be initialized", identifier.c_str());
902         }
903         else if (type.isStructureContainingArrays())
904         {
905             error(line, "structures containing arrays may not be declared constant since they cannot be initialized", identifier.c_str());
906         }
907         else
908         {
909             error(line, "variables with qualifier 'const' must be initialized", identifier.c_str());
910         }
911
912         return true;
913     }
914
915     return false;
916 }
917
918 //
919 // Do semantic checking for a variable declaration that has no initializer,
920 // and update the symbol table.
921 //
922 // Returns true if there was an error.
923 //
924 bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable)
925 {
926     if (reservedErrorCheck(line, identifier))
927         recover();
928
929     variable = new TVariable(&identifier, TType(type));
930
931     if (! symbolTable.declare(*variable)) {
932         error(line, "redefinition", variable->getName().c_str());
933         delete variable;
934         variable = 0;
935         return true;
936     }
937
938     if (voidErrorCheck(line, identifier, type))
939         return true;
940
941     return false;
942 }
943
944 bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
945 {
946     if (qualifier != EvqConstReadOnly && qualifier != EvqTemporary) {
947         error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier));
948         return true;
949     }
950     if (qualifier == EvqConstReadOnly && paramQualifier != EvqIn) {
951         error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
952         return true;
953     }
954
955     if (qualifier == EvqConstReadOnly)
956         type->setQualifier(EvqConstReadOnly);
957     else
958         type->setQualifier(paramQualifier);
959
960     return false;
961 }
962
963 bool TParseContext::extensionErrorCheck(int line, const TString& extension)
964 {
965     const TExtensionBehavior& extBehavior = extensionBehavior();
966     TExtensionBehavior::const_iterator iter = extBehavior.find(extension.c_str());
967     if (iter == extBehavior.end()) {
968         error(line, "extension", extension.c_str(), "is not supported");
969         return true;
970     }
971     // In GLSL ES, an extension's default behavior is "disable".
972     if (iter->second == EBhDisable || iter->second == EBhUndefined) {
973         error(line, "extension", extension.c_str(), "is disabled");
974         return true;
975     }
976     if (iter->second == EBhWarn) {
977         warning(line, "extension", extension.c_str(), "is being used");
978         return false;
979     }
980
981     return false;
982 }
983
984 bool TParseContext::supportsExtension(const char* extension)
985 {
986     const TExtensionBehavior& extbehavior = extensionBehavior();
987     TExtensionBehavior::const_iterator iter = extbehavior.find(extension);
988     return (iter != extbehavior.end());
989 }
990
991 void TParseContext::handleExtensionDirective(int line, const char* extName, const char* behavior)
992 {
993     pp::SourceLocation loc;
994     DecodeSourceLoc(line, &loc.file, &loc.line);
995     directiveHandler.handleExtension(loc, extName, behavior);
996 }
997
998 void TParseContext::handlePragmaDirective(int line, const char* name, const char* value)
999 {
1000     pp::SourceLocation loc;
1001     DecodeSourceLoc(line, &loc.file, &loc.line);
1002     directiveHandler.handlePragma(loc, name, value);
1003 }
1004
1005 /////////////////////////////////////////////////////////////////////////////////
1006 //
1007 // Non-Errors.
1008 //
1009 /////////////////////////////////////////////////////////////////////////////////
1010
1011 //
1012 // Look up a function name in the symbol table, and make sure it is a function.
1013 //
1014 // Return the function symbol if found, otherwise 0.
1015 //
1016 const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
1017 {
1018     // First find by unmangled name to check whether the function name has been
1019     // hidden by a variable name or struct typename.
1020     const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
1021     if (symbol == 0) {
1022         symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
1023     }
1024
1025     if (symbol == 0) {
1026         error(line, "no matching overloaded function found", call->getName().c_str());
1027         return 0;
1028     }
1029
1030     if (!symbol->isFunction()) {
1031         error(line, "function name expected", call->getName().c_str());
1032         return 0;
1033     }
1034
1035     return static_cast<const TFunction*>(symbol);
1036 }
1037
1038 //
1039 // Initializers show up in several places in the grammar.  Have one set of
1040 // code to handle them here.
1041 //
1042 bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
1043                                        TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
1044 {
1045     TType type = TType(pType);
1046
1047     if (variable == 0) {
1048         if (reservedErrorCheck(line, identifier))
1049             return true;
1050
1051         if (voidErrorCheck(line, identifier, pType))
1052             return true;
1053
1054         //
1055         // add variable to symbol table
1056         //
1057         variable = new TVariable(&identifier, type);
1058         if (! symbolTable.declare(*variable)) {
1059             error(line, "redefinition", variable->getName().c_str());
1060             return true;
1061             // don't delete variable, it's used by error recovery, and the pool
1062             // pop will take care of the memory
1063         }
1064     }
1065
1066     //
1067     // identifier must be of type constant, a global, or a temporary
1068     //
1069     TQualifier qualifier = variable->getType().getQualifier();
1070     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConstExpr)) {
1071         error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString());
1072         return true;
1073     }
1074     //
1075     // test for and propagate constant
1076     //
1077
1078     if (qualifier == EvqConstExpr) {
1079         if (qualifier != initializer->getType().getQualifier()) {
1080             std::stringstream extraInfoStream;
1081             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1082             std::string extraInfo = extraInfoStream.str();
1083             error(line, " assigning non-constant to", "=", extraInfo.c_str());
1084             variable->getType().setQualifier(EvqTemporary);
1085             return true;
1086         }
1087         if (type != initializer->getType()) {
1088             error(line, " non-matching types for const initializer ",
1089                 variable->getType().getQualifierString());
1090             variable->getType().setQualifier(EvqTemporary);
1091             return true;
1092         }
1093         if (initializer->getAsConstantUnion()) {
1094             ConstantUnion* unionArray = variable->getConstPointer();
1095
1096             if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
1097                 *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
1098             } else {
1099                 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
1100             }
1101         } else if (initializer->getAsSymbolNode()) {
1102             const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), shaderVersion);
1103             const TVariable* tVar = static_cast<const TVariable*>(symbol);
1104
1105             ConstantUnion* constArray = tVar->getConstPointer();
1106             variable->shareConstPointer(constArray);
1107         } else {
1108             std::stringstream extraInfoStream;
1109             extraInfoStream << "'" << variable->getType().getCompleteString() << "'";
1110             std::string extraInfo = extraInfoStream.str();
1111             error(line, " cannot assign to", "=", extraInfo.c_str());
1112             variable->getType().setQualifier(EvqTemporary);
1113             return true;
1114         }
1115     }
1116
1117     if (qualifier != EvqConstExpr) {
1118         TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1119         intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
1120         if (intermNode == 0) {
1121             assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1122             return true;
1123         }
1124     } else
1125         intermNode = 0;
1126
1127     return false;
1128 }
1129
1130 bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
1131 {
1132     ASSERT(aggrNode != NULL);
1133     if (!aggrNode->isConstructor())
1134         return false;
1135
1136     bool allConstant = true;
1137
1138     // check if all the child nodes are constants so that they can be inserted into
1139     // the parent node
1140     TIntermSequence &sequence = aggrNode->getSequence() ;
1141     for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) {
1142         if (!(*p)->getAsTyped()->getAsConstantUnion())
1143             return false;
1144     }
1145
1146     return allConstant;
1147 }
1148
1149 TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, bool invariant, TLayoutQualifier layoutQualifier, const TPublicType &typeSpecifier)
1150 {
1151         TPublicType returnType = typeSpecifier;
1152         returnType.qualifier = qualifier;
1153         returnType.invariant = invariant;
1154         returnType.layoutQualifier = layoutQualifier;
1155
1156         if(typeSpecifier.array)
1157         {
1158                 error(typeSpecifier.line, "not supported", "first-class array");
1159                 recover();
1160                 returnType.clearArrayness();
1161         }
1162
1163         if(shaderVersion < 300)
1164         {
1165                 if(qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1166                 {
1167                         error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1168                         recover();
1169                 }
1170
1171                 if((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) &&
1172                         (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt))
1173                 {
1174                         error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier));
1175                         recover();
1176                 }
1177         }
1178         else
1179         {
1180                 switch(qualifier)
1181                 {
1182                 case EvqSmoothIn:
1183                 case EvqSmoothOut:
1184                 case EvqVertexOut:
1185                 case EvqFragmentIn:
1186                 case EvqCentroidOut:
1187                 case EvqCentroidIn:
1188                         if(typeSpecifier.type == EbtBool)
1189                         {
1190                                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
1191                                 recover();
1192                         }
1193                         if(typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt)
1194                         {
1195                                 error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier));
1196                                 recover();
1197                         }
1198                         break;
1199
1200                 case EvqVertexIn:
1201                 case EvqFragmentOut:
1202                 case EvqFlatIn:
1203                 case EvqFlatOut:
1204                         if(typeSpecifier.type == EbtBool)
1205                         {
1206                                 error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier));
1207                                 recover();
1208                         }
1209                         break;
1210
1211                 default: break;
1212                 }
1213         }
1214
1215         return returnType;
1216 }
1217
1218 // This function is used to test for the correctness of the parameters passed to various constructor functions
1219 // and also convert them to the right datatype if it is allowed and required.
1220 //
1221 // Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1222 //
1223 TIntermTyped* TParseContext::addConstructor(TIntermNode* arguments, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
1224 {
1225     TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
1226
1227     if(!aggregateArguments)
1228     {
1229         aggregateArguments = new TIntermAggregate;
1230         aggregateArguments->getSequence().push_back(arguments);
1231     }
1232
1233     if(op == EOpConstructStruct)
1234     {
1235         const TFieldList &fields = type->getStruct()->fields();
1236         TIntermSequence &args = aggregateArguments->getSequence();
1237
1238         for(size_t i = 0; i < fields.size(); i++)
1239         {
1240             if(args[i]->getAsTyped()->getType() != *fields[i]->type())
1241             {
1242                 error(line, "Structure constructor arguments do not match structure fields", "Error");
1243                 recover();
1244
1245                 return 0;
1246             }
1247         }
1248     }
1249
1250     // Turn the argument list itself into a constructor
1251     TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
1252     TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
1253     if(constConstructor)
1254     {
1255         return constConstructor;
1256     }
1257
1258     return constructor;
1259 }
1260
1261 TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
1262 {
1263     bool canBeFolded = areAllChildConst(aggrNode);
1264     aggrNode->setType(type);
1265     if (canBeFolded) {
1266         bool returnVal = false;
1267         ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
1268         if (aggrNode->getSequence().size() == 1)  {
1269             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true);
1270         }
1271         else {
1272             returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type);
1273         }
1274         if (returnVal)
1275             return 0;
1276
1277         return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
1278     }
1279
1280     return 0;
1281 }
1282
1283 //
1284 // This function returns the tree representation for the vector field(s) being accessed from contant vector.
1285 // If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
1286 // returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
1287 // node or it could be the intermediate tree representation of accessing fields in a constant structure or column of 
1288 // a constant matrix.
1289 //
1290 TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
1291 {
1292     TIntermTyped* typedNode;
1293     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1294
1295     ConstantUnion *unionArray;
1296     if (tempConstantNode) {
1297         unionArray = tempConstantNode->getUnionArrayPointer();
1298
1299         if (!unionArray) {
1300             return node;
1301         }
1302     } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
1303         error(line, "Cannot offset into the vector", "Error");
1304         recover();
1305
1306         return 0;
1307     }
1308
1309     ConstantUnion* constArray = new ConstantUnion[fields.num];
1310
1311     for (int i = 0; i < fields.num; i++) {
1312         if (fields.offsets[i] >= node->getType().getObjectSize()) {
1313             std::stringstream extraInfoStream;
1314             extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'";
1315             std::string extraInfo = extraInfoStream.str();
1316             error(line, "", "[", extraInfo.c_str());
1317             recover();
1318             fields.offsets[i] = 0;
1319         }
1320
1321         constArray[i] = unionArray[fields.offsets[i]];
1322
1323     }
1324     typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
1325     return typedNode;
1326 }
1327
1328 //
1329 // This function returns the column being accessed from a constant matrix. The values are retrieved from
1330 // the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
1331 // to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
1332 // constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
1333 //
1334 TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
1335 {
1336     TIntermTyped* typedNode;
1337     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1338
1339     if (index >= node->getType().getNominalSize()) {
1340         std::stringstream extraInfoStream;
1341         extraInfoStream << "matrix field selection out of range '" << index << "'";
1342         std::string extraInfo = extraInfoStream.str();
1343         error(line, "", "[", extraInfo.c_str());
1344         recover();
1345         index = 0;
1346     }
1347
1348     if (tempConstantNode) {
1349          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1350          int size = tempConstantNode->getType().getNominalSize();
1351          typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
1352     } else {
1353         error(line, "Cannot offset into the matrix", "Error");
1354         recover();
1355
1356         return 0;
1357     }
1358
1359     return typedNode;
1360 }
1361
1362
1363 //
1364 // This function returns an element of an array accessed from a constant array. The values are retrieved from
1365 // the symbol table and parse-tree is built for the type of the element. The input
1366 // to the function could either be a symbol node (a[0] where a is a constant array)that represents a
1367 // constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
1368 //
1369 TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
1370 {
1371     TIntermTyped* typedNode;
1372     TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1373     TType arrayElementType = node->getType();
1374     arrayElementType.clearArrayness();
1375
1376     if (index >= node->getType().getArraySize()) {
1377         std::stringstream extraInfoStream;
1378         extraInfoStream << "array field selection out of range '" << index << "'";
1379         std::string extraInfo = extraInfoStream.str();
1380         error(line, "", "[", extraInfo.c_str());
1381         recover();
1382         index = 0;
1383     }
1384
1385     int arrayElementSize = arrayElementType.getObjectSize();
1386
1387     if (tempConstantNode) {
1388          ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
1389          typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
1390     } else {
1391         error(line, "Cannot offset into the array", "Error");
1392         recover();
1393
1394         return 0;
1395     }
1396
1397     return typedNode;
1398 }
1399
1400
1401 //
1402 // This function returns the value of a particular field inside a constant structure from the symbol table.
1403 // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
1404 // function and returns the parse-tree with the values of the embedded/nested struct.
1405 //
1406 TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
1407 {
1408     const TFieldList &fields = node->getType().getStruct()->fields();
1409     TIntermTyped *typedNode;
1410     int instanceSize = 0;
1411     unsigned int index = 0;
1412     TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
1413
1414     for ( index = 0; index < fields.size(); ++index) {
1415         if (fields[index]->name() == identifier) {
1416             break;
1417         } else {
1418             instanceSize += fields[index]->type()->getObjectSize();
1419         }
1420     }
1421
1422     if (tempConstantNode) {
1423          ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
1424
1425          typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
1426     } else {
1427         error(line, "Cannot offset into the structure", "Error");
1428         recover();
1429
1430         return 0;
1431     }
1432
1433     return typedNode;
1434 }
1435
1436 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine)
1437 {
1438     TLayoutQualifier qualifier;
1439
1440     qualifier.location = -1;
1441
1442     if (qualifierType == "location")
1443     {
1444         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument");
1445         recover();
1446     }
1447     else
1448     {
1449         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str());
1450         recover();
1451     }
1452
1453     return qualifier;
1454 }
1455
1456 TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine)
1457 {
1458     TLayoutQualifier qualifier;
1459
1460     qualifier.location = -1;
1461
1462     if (qualifierType != "location")
1463     {
1464         error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments");
1465         recover();
1466     }
1467     else
1468     {
1469         // must check that location is non-negative
1470         if (intValue < 0)
1471         {
1472             error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative");
1473             recover();
1474         }
1475         else
1476         {
1477             qualifier.location = intValue;
1478         }
1479     }
1480
1481     return qualifier;
1482 }
1483
1484 TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier)
1485 {
1486     TLayoutQualifier joinedQualifier = leftQualifier;
1487
1488     if (rightQualifier.location != -1)
1489     {
1490         joinedQualifier.location = rightQualifier.location;
1491     }
1492
1493     return joinedQualifier;
1494 }
1495
1496
1497 TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier,
1498         const TSourceLoc &storageLoc, TQualifier storageQualifier)
1499 {
1500         TQualifier mergedQualifier = EvqSmoothIn;
1501
1502         if(storageQualifier == EvqFragmentIn) {
1503                 if(interpolationQualifier == EvqSmooth)
1504                         mergedQualifier = EvqSmoothIn;
1505                 else if(interpolationQualifier == EvqFlat)
1506                         mergedQualifier = EvqFlatIn;
1507                 else UNREACHABLE();
1508         }
1509         else if(storageQualifier == EvqCentroidIn) {
1510                 if(interpolationQualifier == EvqSmooth)
1511                         mergedQualifier = EvqCentroidIn;
1512                 else if(interpolationQualifier == EvqFlat)
1513                         mergedQualifier = EvqFlatIn;
1514                 else UNREACHABLE();
1515         }
1516         else if(storageQualifier == EvqVertexOut) {
1517                 if(interpolationQualifier == EvqSmooth)
1518                         mergedQualifier = EvqSmoothOut;
1519                 else if(interpolationQualifier == EvqFlat)
1520                         mergedQualifier = EvqFlatOut;
1521                 else UNREACHABLE();
1522         }
1523         else if(storageQualifier == EvqCentroidOut) {
1524                 if(interpolationQualifier == EvqSmooth)
1525                         mergedQualifier = EvqCentroidOut;
1526                 else if(interpolationQualifier == EvqFlat)
1527                         mergedQualifier = EvqFlatOut;
1528                 else UNREACHABLE();
1529         }
1530         else {
1531                 error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getQualifierString(interpolationQualifier));
1532                 recover();
1533
1534                 mergedQualifier = storageQualifier;
1535         }
1536
1537         TPublicType type;
1538         type.setBasic(EbtVoid, mergedQualifier, storageLoc);
1539         return type;
1540 }
1541
1542 bool TParseContext::enterStructDeclaration(int line, const TString& identifier)
1543 {
1544     ++structNestingLevel;
1545
1546     // Embedded structure definitions are not supported per GLSL ES spec.
1547     // They aren't allowed in GLSL either, but we need to detect this here
1548     // so we don't rely on the GLSL compiler to catch it.
1549     if (structNestingLevel > 1) {
1550         error(line, "", "Embedded struct definitions are not allowed");
1551         return true;
1552     }
1553
1554     return false;
1555 }
1556
1557 void TParseContext::exitStructDeclaration()
1558 {
1559     --structNestingLevel;
1560 }
1561
1562 //
1563 // Parse an array of strings using yyparse.
1564 //
1565 // Returns 0 for success.
1566 //
1567 int PaParseStrings(int count, const char* const string[], const int length[],
1568                    TParseContext* context) {
1569     if ((count == 0) || (string == NULL))
1570         return 1;
1571
1572     if (glslang_initialize(context))
1573         return 1;
1574
1575     int error = glslang_scan(count, string, length, context);
1576     if (!error)
1577         error = glslang_parse(context);
1578
1579     glslang_finalize(context);
1580
1581     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
1582 }
1583
1584
1585