Commit 60ed9810 by Jamie Madill Committed by Shannon Woods

Move the parsing of single declarations into TParseContext.

TRAC #23268 Signed-off-by: Geoff Lang Signed-off-by: Nicolas Capens Authored-by: Jamie Madill
parent 63491eae
...@@ -759,7 +759,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type) ...@@ -759,7 +759,7 @@ bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable) bool TParseContext::arrayErrorCheck(int line, const TString& identifier, const TPublicType &type, TVariable*& variable)
{ {
// //
// Don't check for reserved word use until after we know it's not in the symbol table, // Don't check for reserved word use until after we know it's not in the symbol table,
...@@ -873,7 +873,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, ...@@ -873,7 +873,7 @@ bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size,
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array) bool TParseContext::nonInitConstErrorCheck(int line, const TString& identifier, TPublicType& type, bool array)
{ {
if (type.qualifier == EvqConst) if (type.qualifier == EvqConst)
{ {
...@@ -905,7 +905,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli ...@@ -905,7 +905,7 @@ bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPubli
// //
// Returns true if there was an error. // Returns true if there was an error.
// //
bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable) bool TParseContext::nonInitErrorCheck(int line, const TString& identifier, const TPublicType& type, TVariable*& variable)
{ {
if (reservedErrorCheck(line, identifier)) if (reservedErrorCheck(line, identifier))
recover(); recover();
...@@ -1023,7 +1023,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, int shad ...@@ -1023,7 +1023,7 @@ const TFunction* TParseContext::findFunction(int line, TFunction* call, int shad
// Initializers show up in several places in the grammar. Have one set of // Initializers show up in several places in the grammar. Have one set of
// code to handle them here. // code to handle them here.
// //
bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool TParseContext::executeInitializer(TSourceLoc line, const TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
{ {
TType type = TType(pType); TType type = TType(pType);
...@@ -1179,6 +1179,95 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, const TPu ...@@ -1179,6 +1179,95 @@ TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, const TPu
return returnType; return returnType;
} }
TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier)
{
TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation);
TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
if (identifier != "")
{
if (structQualifierErrorCheck(identifierLocation, publicType))
recover();
// this error check can mutate the type
if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false))
recover();
TVariable* variable = 0;
if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable))
recover();
if (variable && symbol)
{
symbol->setId(variable->getUniqueId());
}
}
return aggregate;
}
TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc indexLocation, TIntermTyped *indexExpression)
{
if (structQualifierErrorCheck(identifierLocation, publicType))
recover();
// this error check can mutate the type
if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true))
recover();
if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType))
{
recover();
}
TPublicType arrayType = publicType;
int size;
if (arraySizeErrorCheck(identifierLocation, indexExpression, size))
{
recover();
}
else
{
arrayType.setArray(true, size);
}
TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation);
TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation);
TVariable* variable = 0;
if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable))
recover();
if (variable && symbol)
{
symbol->setId(variable->getUniqueId());
}
return aggregate;
}
TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc initLocation, TIntermTyped *initializer)
{
if (structQualifierErrorCheck(identifierLocation, publicType))
recover();
TIntermNode* intermNode;
if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode))
{
//
// Build intermediate representation
//
return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL;
}
else
{
recover();
return NULL;
}
}
TFunction *TParseContext::addConstructorFunc(TPublicType publicType) TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
{ {
TOperator op = EOpNull; TOperator op = EOpNull;
......
...@@ -89,15 +89,15 @@ struct TParseContext { ...@@ -89,15 +89,15 @@ struct TParseContext {
bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size); bool arraySizeErrorCheck(int line, TIntermTyped* expr, int& size);
bool arrayQualifierErrorCheck(int line, TPublicType type); bool arrayQualifierErrorCheck(int line, TPublicType type);
bool arrayTypeErrorCheck(int line, TPublicType type); bool arrayTypeErrorCheck(int line, TPublicType type);
bool arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable); bool arrayErrorCheck(int line, const TString& identifier, const TPublicType &type, TVariable*& variable);
bool voidErrorCheck(int, const TString&, const TPublicType&); bool voidErrorCheck(int, const TString&, const TPublicType&);
bool boolErrorCheck(int, const TIntermTyped*); bool boolErrorCheck(int, const TIntermTyped*);
bool boolErrorCheck(int, const TPublicType&); bool boolErrorCheck(int, const TPublicType&);
bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason); bool samplerErrorCheck(int line, const TPublicType& pType, const char* reason);
bool structQualifierErrorCheck(int line, const TPublicType& pType); bool structQualifierErrorCheck(int line, const TPublicType& pType);
bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type); bool parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type);
bool nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type, bool array); bool nonInitConstErrorCheck(int line, const TString& identifier, TPublicType& type, bool array);
bool nonInitErrorCheck(int line, TString& identifier, TPublicType& type, TVariable*& variable); bool nonInitErrorCheck(int line, const TString& identifier, const TPublicType& type, TVariable*& variable);
bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type); bool paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type);
bool extensionErrorCheck(int line, const TString&); bool extensionErrorCheck(int line, const TString&);
...@@ -111,11 +111,14 @@ struct TParseContext { ...@@ -111,11 +111,14 @@ struct TParseContext {
bool containsSampler(TType& type); bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode); bool areAllChildConst(TIntermAggregate* aggrNode);
const TFunction* findFunction(int line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0); const TFunction* findFunction(int line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0);
bool executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType, bool executeInitializer(TSourceLoc line, const TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc); bool arraySetMaxSize(TIntermSymbol*, TType*, int, bool, TSourceLoc);
TPublicType addFullySpecifiedType(TQualifier qualifier, const TPublicType& typeSpecifier); TPublicType addFullySpecifiedType(TQualifier qualifier, const TPublicType& typeSpecifier);
TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier);
TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc indexLocation, TIntermTyped *indexExpression);
TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, TSourceLoc identifierLocation, const TString &identifier, TSourceLoc initLocation, TIntermTyped *initializer);
TFunction *addConstructorFunc(TPublicType publicType); TFunction *addConstructorFunc(TPublicType publicType);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc); TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
......
...@@ -1100,85 +1100,26 @@ init_declarator_list ...@@ -1100,85 +1100,26 @@ init_declarator_list
single_declaration single_declaration
: fully_specified_type { : fully_specified_type {
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), $1.line), $1.line); $$.intermAggregate = context->parseSingleDeclaration($$.type, $1.line, "");
} }
| fully_specified_type identifier { | fully_specified_type identifier {
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line); $$.type = $1;
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line); $$.intermAggregate = context->parseSingleDeclaration($$.type, $2.line, *$2.string);
if (context->structQualifierErrorCheck($2.line, $$.type))
context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $$.type, false))
context->recover();
$$.type = $1;
TVariable* variable = 0;
if (context->nonInitErrorCheck($2.line, *$2.string, $$.type, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
} }
| fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET {
context->error($2.line, "unsized array declarations not supported", $2.string->c_str()); context->error($2.line, "unsized array declarations not supported", $2.string->c_str());
context->recover(); context->recover();
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleDeclaration($$.type, $2.line, *$2.string);
} }
| fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
TType type = TType($1);
int size;
if (context->arraySizeErrorCheck($2.line, $4, size))
context->recover();
type.setArraySize(size);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, $2.line);
$$.intermAggregate = context->intermediate.makeAggregate(symbol, $2.line);
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
if (context->nonInitConstErrorCheck($2.line, *$2.string, $1, true))
context->recover();
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleArrayDeclaration($$.type, $2.line, *$2.string, $3.line, $4);
if (context->arrayTypeErrorCheck($3.line, $1) || context->arrayQualifierErrorCheck($3.line, $1))
context->recover();
else {
int size;
if (context->arraySizeErrorCheck($3.line, $4, size))
context->recover();
$1.setArray(true, size);
TVariable* variable = 0;
if (context->arrayErrorCheck($3.line, *$2.string, $1, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
} }
| fully_specified_type identifier EQUAL initializer { | fully_specified_type identifier EQUAL initializer {
if (context->structQualifierErrorCheck($2.line, $1))
context->recover();
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleInitDeclaration($$.type, $2.line, *$2.string, $3.line, $4);
TIntermNode* intermNode;
if (!context->executeInitializer($2.line, *$2.string, $1, $4, intermNode)) {
//
// Build intermediate representation
//
if(intermNode)
$$.intermAggregate = context->intermediate.makeAggregate(intermNode, $3.line);
else
$$.intermAggregate = 0;
} else {
context->recover();
$$.intermAggregate = 0;
}
} }
| INVARIANT IDENTIFIER { | INVARIANT IDENTIFIER {
VERTEX_ONLY("invariant declaration", $1.line); VERTEX_ONLY("invariant declaration", $1.line);
......
...@@ -751,20 +751,20 @@ static const yytype_uint16 yyrline[] = ...@@ -751,20 +751,20 @@ static const yytype_uint16 yyrline[] =
733, 736, 747, 755, 763, 790, 795, 806, 810, 814, 733, 736, 747, 755, 763, 790, 795, 806, 810, 814,
821, 859, 862, 869, 877, 898, 919, 930, 959, 964, 821, 859, 862, 869, 877, 898, 919, 930, 959, 964,
974, 979, 989, 992, 995, 998, 1004, 1011, 1014, 1036, 974, 979, 989, 992, 995, 998, 1004, 1011, 1014, 1036,
1054, 1078, 1101, 1105, 1123, 1131, 1163, 1183, 1272, 1281, 1054, 1078, 1101, 1105, 1109, 1116, 1120, 1124, 1213, 1222,
1287, 1291, 1298, 1304, 1311, 1320, 1329, 1332, 1368, 1375, 1228, 1232, 1239, 1245, 1252, 1261, 1270, 1273, 1309, 1316,
1379, 1386, 1390, 1395, 1400, 1410, 1420, 1429, 1439, 1446, 1320, 1327, 1331, 1336, 1341, 1351, 1361, 1370, 1380, 1387,
1449, 1452, 1458, 1465, 1468, 1474, 1477, 1480, 1486, 1489, 1390, 1393, 1399, 1406, 1409, 1415, 1418, 1421, 1427, 1430,
1504, 1508, 1512, 1516, 1520, 1524, 1529, 1534, 1539, 1544, 1445, 1449, 1453, 1457, 1461, 1465, 1470, 1475, 1480, 1485,
1549, 1554, 1559, 1564, 1569, 1574, 1579, 1584, 1590, 1596, 1490, 1495, 1500, 1505, 1510, 1515, 1520, 1525, 1531, 1537,
1602, 1607, 1612, 1617, 1622, 1627, 1632, 1637, 1642, 1651, 1543, 1548, 1553, 1558, 1563, 1568, 1573, 1578, 1583, 1592,
1660, 1665, 1678, 1678, 1681, 1681, 1687, 1690, 1705, 1708, 1601, 1606, 1619, 1619, 1622, 1622, 1628, 1631, 1646, 1649,
1716, 1720, 1726, 1734, 1750, 1754, 1758, 1759, 1765, 1766, 1657, 1661, 1667, 1675, 1691, 1695, 1699, 1700, 1706, 1707,
1767, 1768, 1769, 1773, 1774, 1774, 1774, 1784, 1785, 1789, 1708, 1709, 1710, 1714, 1715, 1715, 1715, 1725, 1726, 1730,
1789, 1790, 1790, 1795, 1798, 1808, 1811, 1817, 1818, 1822, 1730, 1731, 1731, 1736, 1739, 1749, 1752, 1758, 1759, 1763,
1830, 1834, 1844, 1849, 1866, 1866, 1871, 1871, 1878, 1878, 1771, 1775, 1785, 1790, 1807, 1807, 1812, 1812, 1819, 1819,
1886, 1889, 1895, 1898, 1904, 1908, 1915, 1922, 1929, 1936, 1827, 1830, 1836, 1839, 1845, 1849, 1856, 1863, 1870, 1877,
1947, 1956, 1960, 1967, 1970, 1976, 1976 1888, 1897, 1901, 1908, 1911, 1917, 1917
}; };
#endif #endif
...@@ -3470,29 +3470,15 @@ yyreduce: ...@@ -3470,29 +3470,15 @@ yyreduce:
{ {
(yyval.interm).type = (yyvsp[(1) - (1)].interm.type); (yyval.interm).type = (yyvsp[(1) - (1)].interm.type);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType((yyvsp[(1) - (1)].interm.type)), (yyvsp[(1) - (1)].interm.type).line), (yyvsp[(1) - (1)].interm.type).line); (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(1) - (1)].interm.type).line, "");
} }
break; break;
case 103: case 103:
{ {
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (2)].lex).string, TType((yyvsp[(1) - (2)].interm.type)), (yyvsp[(2) - (2)].lex).line); (yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (2)].lex).line); (yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string);
if (context->structQualifierErrorCheck((yyvsp[(2) - (2)].lex).line, (yyval.interm).type))
context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, false))
context->recover();
(yyval.interm).type = (yyvsp[(1) - (2)].interm.type);
TVariable* variable = 0;
if (context->nonInitErrorCheck((yyvsp[(2) - (2)].lex).line, *(yyvsp[(2) - (2)].lex).string, (yyval.interm).type, variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
} }
break; break;
...@@ -3502,69 +3488,24 @@ yyreduce: ...@@ -3502,69 +3488,24 @@ yyreduce:
context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str()); context->error((yyvsp[(2) - (4)].lex).line, "unsized array declarations not supported", (yyvsp[(2) - (4)].lex).string->c_str());
context->recover(); context->recover();
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (4)].lex).string, TType((yyvsp[(1) - (4)].interm.type)), (yyvsp[(2) - (4)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (4)].lex).line);
(yyval.interm).type = (yyvsp[(1) - (4)].interm.type); (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
(yyval.interm).intermAggregate = context->parseSingleDeclaration((yyval.interm).type, (yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string);
} }
break; break;
case 105: case 105:
{ {
TType type = TType((yyvsp[(1) - (5)].interm.type));
int size;
if (context->arraySizeErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
context->recover();
type.setArraySize(size);
TIntermSymbol* symbol = context->intermediate.addSymbol(0, *(yyvsp[(2) - (5)].lex).string, type, (yyvsp[(2) - (5)].lex).line);
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(symbol, (yyvsp[(2) - (5)].lex).line);
if (context->structQualifierErrorCheck((yyvsp[(2) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
context->recover();
if (context->nonInitConstErrorCheck((yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), true))
context->recover();
(yyval.interm).type = (yyvsp[(1) - (5)].interm.type); (yyval.interm).type = (yyvsp[(1) - (5)].interm.type);
(yyval.interm).intermAggregate = context->parseSingleArrayDeclaration((yyval.interm).type, (yyvsp[(2) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode));
if (context->arrayTypeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)) || context->arrayQualifierErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(1) - (5)].interm.type)))
context->recover();
else {
int size;
if (context->arraySizeErrorCheck((yyvsp[(3) - (5)].lex).line, (yyvsp[(4) - (5)].interm.intermTypedNode), size))
context->recover();
(yyvsp[(1) - (5)].interm.type).setArray(true, size);
TVariable* variable = 0;
if (context->arrayErrorCheck((yyvsp[(3) - (5)].lex).line, *(yyvsp[(2) - (5)].lex).string, (yyvsp[(1) - (5)].interm.type), variable))
context->recover();
if (variable && symbol)
symbol->setId(variable->getUniqueId());
}
} }
break; break;
case 106: case 106:
{ {
if (context->structQualifierErrorCheck((yyvsp[(2) - (4)].lex).line, (yyvsp[(1) - (4)].interm.type)))
context->recover();
(yyval.interm).type = (yyvsp[(1) - (4)].interm.type); (yyval.interm).type = (yyvsp[(1) - (4)].interm.type);
(yyval.interm).intermAggregate = context->parseSingleInitDeclaration((yyval.interm).type, (yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(3) - (4)].lex).line, (yyvsp[(4) - (4)].interm.intermTypedNode));
TIntermNode* intermNode;
if (!context->executeInitializer((yyvsp[(2) - (4)].lex).line, *(yyvsp[(2) - (4)].lex).string, (yyvsp[(1) - (4)].interm.type), (yyvsp[(4) - (4)].interm.intermTypedNode), intermNode)) {
//
// Build intermediate representation
//
if(intermNode)
(yyval.interm).intermAggregate = context->intermediate.makeAggregate(intermNode, (yyvsp[(3) - (4)].lex).line);
else
(yyval.interm).intermAggregate = 0;
} else {
context->recover();
(yyval.interm).intermAggregate = 0;
}
} }
break; break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment