1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_idlc.hxx" 26 #include <idlc/astunion.hxx> 27 #include <idlc/astbasetype.hxx> 28 #include <idlc/errorhandler.hxx> 29 30 #include "registry/version.h" 31 #include "registry/writer.hxx" 32 33 using namespace ::rtl; 34 35 AstUnion::AstUnion(const ::rtl::OString& name, AstType* pDiscType, AstScope* pScope) 36 : AstStruct(NT_union, name, NULL, pScope) 37 , m_pDiscriminantType(pDiscType) 38 , m_discExprType(ET_long) 39 { 40 AstBaseType* pBaseType; 41 42 if ( !pDiscType ) 43 { 44 m_pDiscriminantType = NULL; 45 m_discExprType = ET_none; 46 return; 47 } 48 /* 49 * If the discriminator type is a predefined type 50 * then install the equivalent coercion target type in 51 * the pd_udisc_type field. 52 */ 53 if ( pDiscType->getNodeType() == NT_predefined ) 54 { 55 pBaseType = (AstBaseType*)pDiscType; 56 if ( !pBaseType ) 57 { 58 m_pDiscriminantType = NULL; 59 m_discExprType = ET_none; 60 return; 61 } 62 m_pDiscriminantType = pDiscType; 63 switch (pBaseType->getExprType()) 64 { 65 case ET_long: 66 case ET_ulong: 67 case ET_short: 68 case ET_ushort: 69 case ET_char: 70 case ET_boolean: 71 m_discExprType = pBaseType->getExprType(); 72 break; 73 default: 74 m_discExprType = ET_none; 75 m_pDiscriminantType = NULL; 76 break; 77 } 78 } else 79 if (pDiscType->getNodeType() == NT_enum) 80 { 81 m_discExprType = ET_any; 82 m_pDiscriminantType = pDiscType; 83 } else 84 { 85 m_discExprType = ET_none; 86 m_pDiscriminantType = NULL; 87 } 88 89 if ( !m_pDiscriminantType ) 90 idlc()->error()->error2(EIDL_DISC_TYPE, this, pDiscType); 91 } 92 93 AstUnion::~AstUnion() 94 { 95 } 96 97 AstDeclaration* AstUnion::addDeclaration(AstDeclaration* pDecl) 98 { 99 if ( pDecl->getNodeType() == NT_union_branch ) 100 { 101 AstUnionBranch* pBranch = (AstUnionBranch*)pDecl; 102 if ( lookupBranch(pBranch) ) 103 { 104 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pDecl); 105 return NULL; 106 } 107 } 108 109 return AstScope::addDeclaration(pDecl); 110 } 111 112 AstUnionBranch* AstUnion::lookupBranch(AstUnionBranch* pBranch) 113 { 114 AstUnionLabel* pLabel = NULL; 115 116 if ( pBranch ) 117 pLabel = pBranch->getLabel(); 118 119 if ( pLabel ) 120 { 121 if (pLabel->getLabelKind() == UL_default) 122 return lookupDefault(); 123 if (m_discExprType == ET_any) 124 /* CONVENTION: indicates enum discr */ 125 return lookupEnum(pBranch); 126 return lookupLabel(pBranch); 127 } 128 return NULL; 129 } 130 131 AstUnionBranch* AstUnion::lookupDefault(sal_Bool bReportError) 132 { 133 DeclList::const_iterator iter = getIteratorBegin(); 134 DeclList::const_iterator end = getIteratorEnd(); 135 AstUnionBranch *pBranch = NULL; 136 AstDeclaration *pDecl = NULL; 137 138 while ( iter != end ) 139 { 140 pDecl = *iter; 141 if ( pDecl->getNodeType() == NT_union_branch ) 142 { 143 pBranch = (AstUnionBranch*)pDecl; 144 if (pBranch == NULL) 145 { 146 ++iter; 147 continue; 148 } 149 if ( pBranch->getLabel() != NULL && 150 pBranch->getLabel()->getLabelKind() == UL_default) 151 { 152 if ( bReportError ) 153 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); 154 return pBranch; 155 } 156 } 157 ++iter; 158 } 159 return NULL; 160 } 161 162 AstUnionBranch* AstUnion::lookupLabel(AstUnionBranch* pBranch) 163 { 164 AstUnionLabel* pLabel = pBranch->getLabel(); 165 166 if ( !pLabel->getLabelValue() ) 167 return pBranch; 168 // pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False)); 169 AstExprValue* pLabelValue = pLabel->getLabelValue()->coerce( 170 m_discExprType, sal_False); 171 if ( !pLabelValue ) 172 { 173 idlc()->error()->evalError(pLabel->getLabelValue()); 174 return pBranch; 175 } else 176 { 177 pLabel->getLabelValue()->setExprValue(pLabelValue); 178 } 179 180 DeclList::const_iterator iter = getIteratorBegin(); 181 DeclList::const_iterator end = getIteratorEnd(); 182 AstUnionBranch* pB = NULL; 183 AstDeclaration* pDecl = NULL; 184 185 while ( iter != end ) 186 { 187 pDecl = *iter; 188 if ( pDecl->getNodeType() == NT_union_branch ) 189 { 190 pB = (AstUnionBranch*)pDecl; 191 if ( !pB ) 192 { 193 ++iter; 194 continue; 195 } 196 if ( pB->getLabel() != NULL && 197 pB->getLabel()->getLabelKind() == UL_label && 198 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) ) 199 { 200 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); 201 return pBranch; 202 } 203 } 204 ++iter; 205 } 206 return NULL; 207 } 208 209 AstUnionBranch* AstUnion::lookupEnum(AstUnionBranch* pBranch) 210 { 211 AstDeclaration const * pType = resolveTypedefs(m_pDiscriminantType); 212 if ( pType->getNodeType() != NT_enum ) 213 return NULL; 214 215 AstUnionLabel* pLabel = pBranch->getLabel(); 216 AstExpression* pExpr = pLabel->getLabelValue(); 217 if ( !pExpr ) 218 return pBranch; 219 220 /* 221 * Expecting a symbol label 222 */ 223 if ( pExpr->getCombOperator() != EC_symbol) 224 { 225 idlc()->error()->enumValExpected(this); 226 return pBranch; 227 } 228 229 /* 230 * See if the symbol defines a constant in the discriminator enum 231 */ 232 AstEnum* pEnum = (AstEnum*)pType; 233 AstDeclaration* pDecl = pEnum->lookupByName(*pExpr->getSymbolicName()); 234 if ( pDecl == NULL || pDecl->getScope() != pEnum) 235 { 236 idlc()->error()->enumValLookupFailure(this, pEnum, *pExpr->getSymbolicName()); 237 return pBranch; 238 } 239 240 241 DeclList::const_iterator iter = getIteratorBegin(); 242 DeclList::const_iterator end = getIteratorEnd(); 243 AstUnionBranch* pB = NULL; 244 pDecl = NULL; 245 246 while ( iter != end ) 247 { 248 pDecl = *iter; 249 if ( pDecl->getNodeType() == NT_union_branch ) 250 { 251 pB = (AstUnionBranch*)pDecl; 252 if ( !pB ) 253 { 254 ++iter; 255 continue; 256 } 257 if ( pB->getLabel() != NULL && 258 pB->getLabel()->getLabelKind() == UL_label && 259 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) ) 260 { 261 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); 262 return pBranch; 263 } 264 } 265 ++iter; 266 } 267 return NULL; 268 } 269 270 sal_Bool AstUnion::dump(RegistryKey& rKey) 271 { 272 RegistryKey localKey; 273 if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) 274 { 275 fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", 276 idlc()->getOptions()->getProgramName().getStr(), 277 getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); 278 return sal_False; 279 } 280 281 sal_uInt16 nMember = getNodeCount(NT_union_branch); 282 283 OUString emptyStr; 284 typereg::Writer aBlob( 285 TYPEREG_VERSION_0, getDocumentation(), emptyStr, RT_TYPE_UNION, 286 false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1, 287 nMember, 0, 0); 288 aBlob.setSuperTypeName( 289 0, 290 OStringToOUString( 291 getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8)); 292 293 if ( nMember > 0 ) 294 { 295 DeclList::const_iterator iter = getIteratorBegin(); 296 DeclList::const_iterator end = getIteratorEnd(); 297 AstDeclaration* pDecl = NULL; 298 AstUnionBranch* pBranch = NULL; 299 AstUnionBranch* pDefault = lookupDefault(sal_False); 300 AstUnionLabel* pLabel = NULL; 301 AstExprValue* pExprValue = NULL; 302 RTConstValue aConst; 303 RTFieldAccess access = RT_ACCESS_READWRITE; 304 OUString docu; 305 sal_uInt16 index = 0; 306 if ( pDefault ) 307 index = 1; 308 309 sal_Int64 disc = 0; 310 while ( iter != end ) 311 { 312 pDecl = *iter; 313 if ( pDecl->getNodeType() == NT_union_branch ) 314 { 315 pBranch = (AstUnionBranch*)pDecl; 316 if (pBranch == pDefault) 317 { 318 ++iter; 319 continue; 320 } 321 322 pLabel = pBranch->getLabel(); 323 pExprValue = pLabel->getLabelValue()->coerce(ET_hyper, sal_False); 324 aConst.m_type = RT_TYPE_INT64; 325 aConst.m_value.aHyper = pExprValue->u.hval; 326 if ( aConst.m_value.aHyper > disc ) 327 disc = aConst.m_value.aHyper; 328 329 aBlob.setFieldData( 330 index++, pBranch->getDocumentation(), emptyStr, RT_ACCESS_READWRITE, 331 OStringToOUString( 332 pBranch->getLocalName(), RTL_TEXTENCODING_UTF8), 333 OStringToOUString( 334 pBranch->getType()->getRelativName(), 335 RTL_TEXTENCODING_UTF8), 336 aConst); 337 } 338 ++iter; 339 } 340 341 if ( pDefault ) 342 { 343 access = RT_ACCESS_DEFAULT; 344 aConst.m_type = RT_TYPE_INT64; 345 aConst.m_value.aHyper = disc + 1; 346 aBlob.setFieldData( 347 0, pDefault->getDocumentation(), emptyStr, RT_ACCESS_DEFAULT, 348 OStringToOUString( 349 pDefault->getLocalName(), RTL_TEXTENCODING_UTF8), 350 OStringToOUString( 351 pDefault->getType()->getRelativName(), 352 RTL_TEXTENCODING_UTF8), 353 aConst); 354 } 355 } 356 357 sal_uInt32 aBlobSize; 358 void const * pBlob = aBlob.getBlob(&aBlobSize); 359 360 if (localKey.setValue(OUString(), RG_VALUETYPE_BINARY, 361 (RegValue)pBlob, aBlobSize)) 362 { 363 fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", 364 idlc()->getOptions()->getProgramName().getStr(), 365 getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); 366 return sal_False; 367 } 368 369 return sal_True; 370 } 371 372 AstUnionBranch::AstUnionBranch(AstUnionLabel* pLabel, AstType const * pType, const ::rtl::OString& name, AstScope* pScope) 373 : AstMember(NT_union_branch, pType, name, pScope) 374 , m_pLabel(pLabel) 375 { 376 } 377 378 AstUnionBranch::~AstUnionBranch() 379 { 380 if ( m_pLabel ) 381 delete m_pLabel; 382 } 383 384 AstUnionLabel::AstUnionLabel(UnionLabel labelKind, AstExpression* pExpr) 385 : m_label(labelKind) 386 , m_pLabelValue(pExpr) 387 { 388 if ( m_pLabelValue ) 389 m_pLabelValue->evaluate(EK_const); 390 } 391 392 AstUnionLabel::~AstUnionLabel() 393 { 394 if ( m_pLabelValue ) 395 delete m_pLabelValue; 396 } 397 398