update dev300-m58
[ooovba.git] / idlc / source / astunion.cxx
blob794aed9b23685ef5ee524e15a90aaa9518e16203
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: astunion.cxx,v $
10 * $Revision: 1.11 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_idlc.hxx"
33 #include <idlc/astunion.hxx>
34 #include <idlc/astbasetype.hxx>
35 #include <idlc/errorhandler.hxx>
37 #include "registry/version.h"
38 #include "registry/writer.hxx"
40 using namespace ::rtl;
42 AstUnion::AstUnion(const ::rtl::OString& name, AstType* pDiscType, AstScope* pScope)
43 : AstStruct(NT_union, name, NULL, pScope)
44 , m_pDiscriminantType(pDiscType)
45 , m_discExprType(ET_long)
47 AstBaseType* pBaseType;
49 if ( !pDiscType )
51 m_pDiscriminantType = NULL;
52 m_discExprType = ET_none;
53 return;
56 * If the discriminator type is a predefined type
57 * then install the equivalent coercion target type in
58 * the pd_udisc_type field.
60 if ( pDiscType->getNodeType() == NT_predefined )
62 pBaseType = (AstBaseType*)pDiscType;
63 if ( !pBaseType )
65 m_pDiscriminantType = NULL;
66 m_discExprType = ET_none;
67 return;
69 m_pDiscriminantType = pDiscType;
70 switch (pBaseType->getExprType())
72 case ET_long:
73 case ET_ulong:
74 case ET_short:
75 case ET_ushort:
76 case ET_char:
77 case ET_boolean:
78 m_discExprType = pBaseType->getExprType();
79 break;
80 default:
81 m_discExprType = ET_none;
82 m_pDiscriminantType = NULL;
83 break;
85 } else
86 if (pDiscType->getNodeType() == NT_enum)
88 m_discExprType = ET_any;
89 m_pDiscriminantType = pDiscType;
90 } else
92 m_discExprType = ET_none;
93 m_pDiscriminantType = NULL;
96 if ( !m_pDiscriminantType )
97 idlc()->error()->error2(EIDL_DISC_TYPE, this, pDiscType);
100 AstUnion::~AstUnion()
104 AstDeclaration* AstUnion::addDeclaration(AstDeclaration* pDecl)
106 if ( pDecl->getNodeType() == NT_union_branch )
108 AstUnionBranch* pBranch = (AstUnionBranch*)pDecl;
109 if ( lookupBranch(pBranch) )
111 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pDecl);
112 return NULL;
116 return AstScope::addDeclaration(pDecl);
119 AstUnionBranch* AstUnion::lookupBranch(AstUnionBranch* pBranch)
121 AstUnionLabel* pLabel = NULL;
123 if ( pBranch )
124 pLabel = pBranch->getLabel();
126 if ( pLabel )
128 if (pLabel->getLabelKind() == UL_default)
129 return lookupDefault();
130 if (m_discExprType == ET_any)
131 /* CONVENTION: indicates enum discr */
132 return lookupEnum(pBranch);
133 return lookupLabel(pBranch);
135 return NULL;
138 AstUnionBranch* AstUnion::lookupDefault(sal_Bool bReportError)
140 DeclList::const_iterator iter = getIteratorBegin();
141 DeclList::const_iterator end = getIteratorEnd();
142 AstUnionBranch *pBranch = NULL;
143 AstDeclaration *pDecl = NULL;
145 while ( iter != end )
147 pDecl = *iter;
148 if ( pDecl->getNodeType() == NT_union_branch )
150 pBranch = (AstUnionBranch*)pDecl;
151 if (pBranch == NULL)
153 ++iter;
154 continue;
156 if ( pBranch->getLabel() != NULL &&
157 pBranch->getLabel()->getLabelKind() == UL_default)
159 if ( bReportError )
160 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
161 return pBranch;
164 ++iter;
166 return NULL;
169 AstUnionBranch* AstUnion::lookupLabel(AstUnionBranch* pBranch)
171 AstUnionLabel* pLabel = pBranch->getLabel();
173 if ( !pLabel->getLabelValue() )
174 return pBranch;
175 // pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False));
176 AstExprValue* pLabelValue = pLabel->getLabelValue()->coerce(
177 m_discExprType, sal_False);
178 if ( !pLabelValue )
180 idlc()->error()->evalError(pLabel->getLabelValue());
181 return pBranch;
182 } else
184 pLabel->getLabelValue()->setExprValue(pLabelValue);
187 DeclList::const_iterator iter = getIteratorBegin();
188 DeclList::const_iterator end = getIteratorEnd();
189 AstUnionBranch* pB = NULL;
190 AstDeclaration* pDecl = NULL;
192 while ( iter != end )
194 pDecl = *iter;
195 if ( pDecl->getNodeType() == NT_union_branch )
197 pB = (AstUnionBranch*)pDecl;
198 if ( !pB )
200 ++iter;
201 continue;
203 if ( pB->getLabel() != NULL &&
204 pB->getLabel()->getLabelKind() == UL_label &&
205 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) )
207 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
208 return pBranch;
211 ++iter;
213 return NULL;
216 AstUnionBranch* AstUnion::lookupEnum(AstUnionBranch* pBranch)
218 AstDeclaration const * pType = resolveTypedefs(m_pDiscriminantType);
219 if ( pType->getNodeType() != NT_enum )
220 return NULL;
222 AstUnionLabel* pLabel = pBranch->getLabel();
223 AstExpression* pExpr = pLabel->getLabelValue();
224 if ( !pExpr )
225 return pBranch;
228 * Expecting a symbol label
230 if ( pExpr->getCombOperator() != EC_symbol)
232 idlc()->error()->enumValExpected(this);
233 return pBranch;
237 * See if the symbol defines a constant in the discriminator enum
239 AstEnum* pEnum = (AstEnum*)pType;
240 AstDeclaration* pDecl = pEnum->lookupByName(*pExpr->getSymbolicName());
241 if ( pDecl == NULL || pDecl->getScope() != pEnum)
243 idlc()->error()->enumValLookupFailure(this, pEnum, *pExpr->getSymbolicName());
244 return pBranch;
248 DeclList::const_iterator iter = getIteratorBegin();
249 DeclList::const_iterator end = getIteratorEnd();
250 AstUnionBranch* pB = NULL;
251 pDecl = NULL;
253 while ( iter != end )
255 pDecl = *iter;
256 if ( pDecl->getNodeType() == NT_union_branch )
258 pB = (AstUnionBranch*)pDecl;
259 if ( !pB )
261 ++iter;
262 continue;
264 if ( pB->getLabel() != NULL &&
265 pB->getLabel()->getLabelKind() == UL_label &&
266 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) )
268 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
269 return pBranch;
272 ++iter;
274 return NULL;
277 sal_Bool AstUnion::dump(RegistryKey& rKey)
279 RegistryKey localKey;
280 if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey))
282 fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n",
283 idlc()->getOptions()->getProgramName().getStr(),
284 getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
285 return sal_False;
288 sal_uInt16 nMember = getNodeCount(NT_union_branch);
290 OUString emptyStr;
291 typereg::Writer aBlob(
292 TYPEREG_VERSION_0, getDocumentation(), emptyStr, RT_TYPE_UNION,
293 false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1,
294 nMember, 0, 0);
295 aBlob.setSuperTypeName(
297 OStringToOUString(
298 getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8));
300 if ( nMember > 0 )
302 DeclList::const_iterator iter = getIteratorBegin();
303 DeclList::const_iterator end = getIteratorEnd();
304 AstDeclaration* pDecl = NULL;
305 AstUnionBranch* pBranch = NULL;
306 AstUnionBranch* pDefault = lookupDefault(sal_False);
307 AstUnionLabel* pLabel = NULL;
308 AstExprValue* pExprValue = NULL;
309 RTConstValue aConst;
310 RTFieldAccess access = RT_ACCESS_READWRITE;
311 OUString docu;
312 sal_uInt16 index = 0;
313 if ( pDefault )
314 index = 1;
316 sal_Int64 disc = 0;
317 while ( iter != end )
319 pDecl = *iter;
320 if ( pDecl->getNodeType() == NT_union_branch )
322 pBranch = (AstUnionBranch*)pDecl;
323 if (pBranch == pDefault)
325 ++iter;
326 continue;
329 pLabel = pBranch->getLabel();
330 pExprValue = pLabel->getLabelValue()->coerce(ET_hyper, sal_False);
331 aConst.m_type = RT_TYPE_INT64;
332 aConst.m_value.aHyper = pExprValue->u.hval;
333 if ( aConst.m_value.aHyper > disc )
334 disc = aConst.m_value.aHyper;
336 aBlob.setFieldData(
337 index++, pBranch->getDocumentation(), emptyStr, RT_ACCESS_READWRITE,
338 OStringToOUString(
339 pBranch->getLocalName(), RTL_TEXTENCODING_UTF8),
340 OStringToOUString(
341 pBranch->getType()->getRelativName(),
342 RTL_TEXTENCODING_UTF8),
343 aConst);
345 ++iter;
348 if ( pDefault )
350 access = RT_ACCESS_DEFAULT;
351 aConst.m_type = RT_TYPE_INT64;
352 aConst.m_value.aHyper = disc + 1;
353 aBlob.setFieldData(
354 0, pDefault->getDocumentation(), emptyStr, RT_ACCESS_DEFAULT,
355 OStringToOUString(
356 pDefault->getLocalName(), RTL_TEXTENCODING_UTF8),
357 OStringToOUString(
358 pDefault->getType()->getRelativName(),
359 RTL_TEXTENCODING_UTF8),
360 aConst);
364 sal_uInt32 aBlobSize;
365 void const * pBlob = aBlob.getBlob(&aBlobSize);
367 if (localKey.setValue(OUString(), RG_VALUETYPE_BINARY,
368 (RegValue)pBlob, aBlobSize))
370 fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n",
371 idlc()->getOptions()->getProgramName().getStr(),
372 getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
373 return sal_False;
376 return sal_True;
379 AstUnionBranch::AstUnionBranch(AstUnionLabel* pLabel, AstType const * pType, const ::rtl::OString& name, AstScope* pScope)
380 : AstMember(NT_union_branch, pType, name, pScope)
381 , m_pLabel(pLabel)
385 AstUnionBranch::~AstUnionBranch()
387 if ( m_pLabel )
388 delete m_pLabel;
391 AstUnionLabel::AstUnionLabel(UnionLabel labelKind, AstExpression* pExpr)
392 : m_label(labelKind)
393 , m_pLabelValue(pExpr)
395 if ( m_pLabelValue )
396 m_pLabelValue->evaluate(EK_const);
399 AstUnionLabel::~AstUnionLabel()
401 if ( m_pLabelValue )
402 delete m_pLabelValue;