1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
;
38 m_pDiscriminantType
= NULL
;
39 m_discExprType
= ET_none
;
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())
59 m_discExprType
= pBaseType
->getExprType();
62 m_discExprType
= ET_none
;
63 m_pDiscriminantType
= NULL
;
67 if (pDiscType
->getNodeType() == NT_enum
)
69 m_discExprType
= ET_any
;
70 m_pDiscriminantType
= pDiscType
;
73 m_discExprType
= ET_none
;
74 m_pDiscriminantType
= NULL
;
77 if ( !m_pDiscriminantType
)
78 idlc()->error()->error2(EIDL_DISC_TYPE
, this, pDiscType
);
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
);
97 return AstScope::addDeclaration(pDecl
);
100 AstUnionBranch
* AstUnion::lookupBranch(AstUnionBranch
* pBranch
)
102 AstUnionLabel
* pLabel
= NULL
;
105 pLabel
= pBranch
->getLabel();
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
);
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
)
129 if ( pDecl
->getNodeType() == NT_union_branch
)
131 pBranch
= (AstUnionBranch
*)pDecl
;
137 if ( pBranch
->getLabel() != NULL
&&
138 pBranch
->getLabel()->getLabelKind() == UL_default
)
141 idlc()->error()->error2(EIDL_MULTIPLE_BRANCH
, this, pBranch
);
150 AstUnionBranch
* AstUnion::lookupLabel(AstUnionBranch
* pBranch
)
152 AstUnionLabel
* pLabel
= pBranch
->getLabel();
154 if ( !pLabel
->getLabelValue() )
156 // pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False));
157 AstExprValue
* pLabelValue
= pLabel
->getLabelValue()->coerce(
158 m_discExprType
, sal_False
);
161 idlc()->error()->evalError(pLabel
->getLabelValue());
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
)
176 if ( pDecl
->getNodeType() == NT_union_branch
)
178 pB
= (AstUnionBranch
*)pDecl
;
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
);
197 AstUnionBranch
* AstUnion::lookupEnum(AstUnionBranch
* pBranch
)
199 AstDeclaration
const * pType
= resolveTypedefs(m_pDiscriminantType
);
200 if ( pType
->getNodeType() != NT_enum
)
203 AstUnionLabel
* pLabel
= pBranch
->getLabel();
204 AstExpression
* pExpr
= pLabel
->getLabelValue();
209 * Expecting a symbol label
211 if ( pExpr
->getCombOperator() != EC_symbol
)
213 idlc()->error()->enumValExpected(this);
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());
229 DeclList::const_iterator iter
= getIteratorBegin();
230 DeclList::const_iterator end
= getIteratorEnd();
231 AstUnionBranch
* pB
= NULL
;
234 while ( iter
!= end
)
237 if ( pDecl
->getNodeType() == NT_union_branch
)
239 pB
= (AstUnionBranch
*)pDecl
;
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
);
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());
269 sal_uInt16 nMember
= getNodeCount(NT_union_branch
);
272 typereg::Writer
aBlob(
273 TYPEREG_VERSION_0
, getDocumentation(), emptyStr
, RT_TYPE_UNION
,
274 false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8
), 1,
276 aBlob
.setSuperTypeName(
279 getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8
));
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
;
291 sal_uInt16 index
= 0;
296 while ( iter
!= end
)
299 if ( pDecl
->getNodeType() == NT_union_branch
)
301 pBranch
= (AstUnionBranch
*)pDecl
;
302 if (pBranch
== pDefault
)
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
;
316 index
++, pBranch
->getDocumentation(), emptyStr
, RT_ACCESS_READWRITE
,
318 pBranch
->getLocalName(), RTL_TEXTENCODING_UTF8
),
320 pBranch
->getType()->getRelativName(),
321 RTL_TEXTENCODING_UTF8
),
329 aConst
.m_type
= RT_TYPE_INT64
;
330 aConst
.m_value
.aHyper
= disc
+ 1;
332 0, pDefault
->getDocumentation(), emptyStr
, RT_ACCESS_DEFAULT
,
334 pDefault
->getLocalName(), RTL_TEXTENCODING_UTF8
),
336 pDefault
->getType()->getRelativName(),
337 RTL_TEXTENCODING_UTF8
),
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());
357 AstUnionBranch::AstUnionBranch(AstUnionLabel
* pLabel
, AstType
const * pType
, const OString
& name
, AstScope
* pScope
)
358 : AstMember(NT_union_branch
, pType
, name
, pScope
)
363 AstUnionBranch::~AstUnionBranch()
368 AstUnionLabel::AstUnionLabel(UnionLabel labelKind
, AstExpression
* pExpr
)
370 , m_pLabelValue(pExpr
)
373 m_pLabelValue
->evaluate(EK_const
);
376 AstUnionLabel::~AstUnionLabel()
378 delete m_pLabelValue
;
382 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */