1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: astunion.cxx,v $
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
;
51 m_pDiscriminantType
= NULL
;
52 m_discExprType
= ET_none
;
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
;
65 m_pDiscriminantType
= NULL
;
66 m_discExprType
= ET_none
;
69 m_pDiscriminantType
= pDiscType
;
70 switch (pBaseType
->getExprType())
78 m_discExprType
= pBaseType
->getExprType();
81 m_discExprType
= ET_none
;
82 m_pDiscriminantType
= NULL
;
86 if (pDiscType
->getNodeType() == NT_enum
)
88 m_discExprType
= ET_any
;
89 m_pDiscriminantType
= pDiscType
;
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
);
116 return AstScope::addDeclaration(pDecl
);
119 AstUnionBranch
* AstUnion::lookupBranch(AstUnionBranch
* pBranch
)
121 AstUnionLabel
* pLabel
= NULL
;
124 pLabel
= pBranch
->getLabel();
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
);
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
)
148 if ( pDecl
->getNodeType() == NT_union_branch
)
150 pBranch
= (AstUnionBranch
*)pDecl
;
156 if ( pBranch
->getLabel() != NULL
&&
157 pBranch
->getLabel()->getLabelKind() == UL_default
)
160 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH
, this, pBranch
);
169 AstUnionBranch
* AstUnion::lookupLabel(AstUnionBranch
* pBranch
)
171 AstUnionLabel
* pLabel
= pBranch
->getLabel();
173 if ( !pLabel
->getLabelValue() )
175 // pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False));
176 AstExprValue
* pLabelValue
= pLabel
->getLabelValue()->coerce(
177 m_discExprType
, sal_False
);
180 idlc()->error()->evalError(pLabel
->getLabelValue());
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
)
195 if ( pDecl
->getNodeType() == NT_union_branch
)
197 pB
= (AstUnionBranch
*)pDecl
;
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
);
216 AstUnionBranch
* AstUnion::lookupEnum(AstUnionBranch
* pBranch
)
218 AstDeclaration
const * pType
= resolveTypedefs(m_pDiscriminantType
);
219 if ( pType
->getNodeType() != NT_enum
)
222 AstUnionLabel
* pLabel
= pBranch
->getLabel();
223 AstExpression
* pExpr
= pLabel
->getLabelValue();
228 * Expecting a symbol label
230 if ( pExpr
->getCombOperator() != EC_symbol
)
232 idlc()->error()->enumValExpected(this);
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());
248 DeclList::const_iterator iter
= getIteratorBegin();
249 DeclList::const_iterator end
= getIteratorEnd();
250 AstUnionBranch
* pB
= NULL
;
253 while ( iter
!= end
)
256 if ( pDecl
->getNodeType() == NT_union_branch
)
258 pB
= (AstUnionBranch
*)pDecl
;
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
);
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());
288 sal_uInt16 nMember
= getNodeCount(NT_union_branch
);
291 typereg::Writer
aBlob(
292 TYPEREG_VERSION_0
, getDocumentation(), emptyStr
, RT_TYPE_UNION
,
293 false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8
), 1,
295 aBlob
.setSuperTypeName(
298 getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8
));
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
;
310 RTFieldAccess access
= RT_ACCESS_READWRITE
;
312 sal_uInt16 index
= 0;
317 while ( iter
!= end
)
320 if ( pDecl
->getNodeType() == NT_union_branch
)
322 pBranch
= (AstUnionBranch
*)pDecl
;
323 if (pBranch
== pDefault
)
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
;
337 index
++, pBranch
->getDocumentation(), emptyStr
, RT_ACCESS_READWRITE
,
339 pBranch
->getLocalName(), RTL_TEXTENCODING_UTF8
),
341 pBranch
->getType()->getRelativName(),
342 RTL_TEXTENCODING_UTF8
),
350 access
= RT_ACCESS_DEFAULT
;
351 aConst
.m_type
= RT_TYPE_INT64
;
352 aConst
.m_value
.aHyper
= disc
+ 1;
354 0, pDefault
->getDocumentation(), emptyStr
, RT_ACCESS_DEFAULT
,
356 pDefault
->getLocalName(), RTL_TEXTENCODING_UTF8
),
358 pDefault
->getType()->getRelativName(),
359 RTL_TEXTENCODING_UTF8
),
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());
379 AstUnionBranch::AstUnionBranch(AstUnionLabel
* pLabel
, AstType
const * pType
, const ::rtl::OString
& name
, AstScope
* pScope
)
380 : AstMember(NT_union_branch
, pType
, name
, pScope
)
385 AstUnionBranch::~AstUnionBranch()
391 AstUnionLabel::AstUnionLabel(UnionLabel labelKind
, AstExpression
* pExpr
)
393 , m_pLabelValue(pExpr
)
396 m_pLabelValue
->evaluate(EK_const
);
399 AstUnionLabel::~AstUnionLabel()
402 delete m_pLabelValue
;