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