bump product version to 4.1.6.2
[LibreOffice.git] / idlc / source / astunion.cxx
blob45e2f3128345ad8fd4a28963c964d86c999d3551
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <idlc/astunion.hxx>
21 #include <idlc/astbasetype.hxx>
22 #include <idlc/errorhandler.hxx>
24 #include "registry/version.h"
25 #include "registry/writer.hxx"
27 using namespace ::rtl;
29 AstUnion::AstUnion(const OString& name, AstType* pDiscType, AstScope* pScope)
30 : AstStruct(NT_union, name, NULL, pScope)
31 , m_pDiscriminantType(pDiscType)
32 , m_discExprType(ET_long)
34 AstBaseType* pBaseType;
36 if ( !pDiscType )
38 m_pDiscriminantType = NULL;
39 m_discExprType = ET_none;
40 return;
43 * If the discriminator type is a predefined type
44 * then install the equivalent coercion target type in
45 * the pd_udisc_type field.
47 if ( pDiscType->getNodeType() == NT_predefined )
49 pBaseType = (AstBaseType*)pDiscType;
50 m_pDiscriminantType = pDiscType;
51 switch (pBaseType->getExprType())
53 case ET_long:
54 case ET_ulong:
55 case ET_short:
56 case ET_ushort:
57 case ET_char:
58 case ET_boolean:
59 m_discExprType = pBaseType->getExprType();
60 break;
61 default:
62 m_discExprType = ET_none;
63 m_pDiscriminantType = NULL;
64 break;
66 } else
67 if (pDiscType->getNodeType() == NT_enum)
69 m_discExprType = ET_any;
70 m_pDiscriminantType = pDiscType;
71 } else
73 m_discExprType = ET_none;
74 m_pDiscriminantType = NULL;
77 if ( !m_pDiscriminantType )
78 idlc()->error()->error2(EIDL_DISC_TYPE, this, pDiscType);
81 AstUnion::~AstUnion()
85 AstDeclaration* AstUnion::addDeclaration(AstDeclaration* pDecl)
87 if ( pDecl->getNodeType() == NT_union_branch )
89 AstUnionBranch* pBranch = (AstUnionBranch*)pDecl;
90 if ( lookupBranch(pBranch) )
92 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pDecl);
93 return NULL;
97 return AstScope::addDeclaration(pDecl);
100 AstUnionBranch* AstUnion::lookupBranch(AstUnionBranch* pBranch)
102 AstUnionLabel* pLabel = NULL;
104 if ( pBranch )
105 pLabel = pBranch->getLabel();
107 if ( pLabel )
109 if (pLabel->getLabelKind() == UL_default)
110 return lookupDefault();
111 if (m_discExprType == ET_any)
112 /* CONVENTION: indicates enum discr */
113 return lookupEnum(pBranch);
114 return lookupLabel(pBranch);
116 return NULL;
119 AstUnionBranch* AstUnion::lookupDefault(sal_Bool bReportError)
121 DeclList::const_iterator iter = getIteratorBegin();
122 DeclList::const_iterator end = getIteratorEnd();
123 AstUnionBranch *pBranch = NULL;
124 AstDeclaration *pDecl = NULL;
126 while ( iter != end )
128 pDecl = *iter;
129 if ( pDecl->getNodeType() == NT_union_branch )
131 pBranch = (AstUnionBranch*)pDecl;
132 if (pBranch == NULL)
134 ++iter;
135 continue;
137 if ( pBranch->getLabel() != NULL &&
138 pBranch->getLabel()->getLabelKind() == UL_default)
140 if ( bReportError )
141 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
142 return pBranch;
145 ++iter;
147 return NULL;
150 AstUnionBranch* AstUnion::lookupLabel(AstUnionBranch* pBranch)
152 AstUnionLabel* pLabel = pBranch->getLabel();
154 if ( !pLabel->getLabelValue() )
155 return pBranch;
156 // pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False));
157 AstExprValue* pLabelValue = pLabel->getLabelValue()->coerce(
158 m_discExprType, sal_False);
159 if ( !pLabelValue )
161 idlc()->error()->evalError(pLabel->getLabelValue());
162 return pBranch;
163 } else
165 pLabel->getLabelValue()->setExprValue(pLabelValue);
168 DeclList::const_iterator iter = getIteratorBegin();
169 DeclList::const_iterator end = getIteratorEnd();
170 AstUnionBranch* pB = NULL;
171 AstDeclaration* pDecl = NULL;
173 while ( iter != end )
175 pDecl = *iter;
176 if ( pDecl->getNodeType() == NT_union_branch )
178 pB = (AstUnionBranch*)pDecl;
179 if ( !pB )
181 ++iter;
182 continue;
184 if ( pB->getLabel() != NULL &&
185 pB->getLabel()->getLabelKind() == UL_label &&
186 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) )
188 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
189 return pBranch;
192 ++iter;
194 return NULL;
197 AstUnionBranch* AstUnion::lookupEnum(AstUnionBranch* pBranch)
199 AstDeclaration const * pType = resolveTypedefs(m_pDiscriminantType);
200 if ( pType->getNodeType() != NT_enum )
201 return NULL;
203 AstUnionLabel* pLabel = pBranch->getLabel();
204 AstExpression* pExpr = pLabel->getLabelValue();
205 if ( !pExpr )
206 return pBranch;
209 * Expecting a symbol label
211 if ( pExpr->getCombOperator() != EC_symbol)
213 idlc()->error()->enumValExpected(this);
214 return pBranch;
218 * See if the symbol defines a constant in the discriminator enum
220 AstEnum* pEnum = (AstEnum*)pType;
221 AstDeclaration* pDecl = pEnum->lookupByName(*pExpr->getSymbolicName());
222 if ( pDecl == NULL || pDecl->getScope() != pEnum)
224 idlc()->error()->enumValLookupFailure(this, pEnum, *pExpr->getSymbolicName());
225 return pBranch;
229 DeclList::const_iterator iter = getIteratorBegin();
230 DeclList::const_iterator end = getIteratorEnd();
231 AstUnionBranch* pB = NULL;
232 pDecl = NULL;
234 while ( iter != end )
236 pDecl = *iter;
237 if ( pDecl->getNodeType() == NT_union_branch )
239 pB = (AstUnionBranch*)pDecl;
240 if ( !pB )
242 ++iter;
243 continue;
245 if ( pB->getLabel() != NULL &&
246 pB->getLabel()->getLabelKind() == UL_label &&
247 pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) )
249 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch);
250 return pBranch;
253 ++iter;
255 return NULL;
258 sal_Bool AstUnion::dump(RegistryKey& rKey)
260 RegistryKey localKey;
261 if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey))
263 fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n",
264 idlc()->getOptions()->getProgramName().getStr(),
265 getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
266 return sal_False;
269 sal_uInt16 nMember = getNodeCount(NT_union_branch);
271 OUString emptyStr;
272 typereg::Writer aBlob(
273 TYPEREG_VERSION_0, getDocumentation(), emptyStr, RT_TYPE_UNION,
274 false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1,
275 nMember, 0, 0);
276 aBlob.setSuperTypeName(
278 OStringToOUString(
279 getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8));
281 if ( nMember > 0 )
283 DeclList::const_iterator iter = getIteratorBegin();
284 DeclList::const_iterator end = getIteratorEnd();
285 AstDeclaration* pDecl = NULL;
286 AstUnionBranch* pBranch = NULL;
287 AstUnionBranch* pDefault = lookupDefault(sal_False);
288 AstUnionLabel* pLabel = NULL;
289 AstExprValue* pExprValue = NULL;
290 RTConstValue aConst;
291 sal_uInt16 index = 0;
292 if ( pDefault )
293 index = 1;
295 sal_Int64 disc = 0;
296 while ( iter != end )
298 pDecl = *iter;
299 if ( pDecl->getNodeType() == NT_union_branch )
301 pBranch = (AstUnionBranch*)pDecl;
302 if (pBranch == pDefault)
304 ++iter;
305 continue;
308 pLabel = pBranch->getLabel();
309 pExprValue = pLabel->getLabelValue()->coerce(ET_hyper, sal_False);
310 aConst.m_type = RT_TYPE_INT64;
311 aConst.m_value.aHyper = pExprValue->u.hval;
312 if ( aConst.m_value.aHyper > disc )
313 disc = aConst.m_value.aHyper;
315 aBlob.setFieldData(
316 index++, pBranch->getDocumentation(), emptyStr, RT_ACCESS_READWRITE,
317 OStringToOUString(
318 pBranch->getLocalName(), RTL_TEXTENCODING_UTF8),
319 OStringToOUString(
320 pBranch->getType()->getRelativName(),
321 RTL_TEXTENCODING_UTF8),
322 aConst);
324 ++iter;
327 if ( pDefault )
329 aConst.m_type = RT_TYPE_INT64;
330 aConst.m_value.aHyper = disc + 1;
331 aBlob.setFieldData(
332 0, pDefault->getDocumentation(), emptyStr, RT_ACCESS_DEFAULT,
333 OStringToOUString(
334 pDefault->getLocalName(), RTL_TEXTENCODING_UTF8),
335 OStringToOUString(
336 pDefault->getType()->getRelativName(),
337 RTL_TEXTENCODING_UTF8),
338 aConst);
342 sal_uInt32 aBlobSize;
343 void const * pBlob = aBlob.getBlob(&aBlobSize);
345 if (localKey.setValue(OUString(), RG_VALUETYPE_BINARY,
346 (RegValue)pBlob, aBlobSize))
348 fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n",
349 idlc()->getOptions()->getProgramName().getStr(),
350 getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr());
351 return sal_False;
354 return sal_True;
357 AstUnionBranch::AstUnionBranch(AstUnionLabel* pLabel, AstType const * pType, const OString& name, AstScope* pScope)
358 : AstMember(NT_union_branch, pType, name, pScope)
359 , m_pLabel(pLabel)
363 AstUnionBranch::~AstUnionBranch()
365 delete m_pLabel;
368 AstUnionLabel::AstUnionLabel(UnionLabel labelKind, AstExpression* pExpr)
369 : m_label(labelKind)
370 , m_pLabelValue(pExpr)
372 if ( m_pLabelValue )
373 m_pLabelValue->evaluate(EK_const);
376 AstUnionLabel::~AstUnionLabel()
378 delete m_pLabelValue;
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */