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