diff options
Diffstat (limited to 'idlc/source')
37 files changed, 14597 insertions, 0 deletions
diff --git a/idlc/source/astarray.cxx b/idlc/source/astarray.cxx new file mode 100644 index 000000000000..0277b5a04e76 --- /dev/null +++ b/idlc/source/astarray.cxx @@ -0,0 +1,74 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astarray.hxx> + +using namespace ::rtl; + +AstArray::AstArray(const OString& name, AstType* pType, const ExprList& rDimExpr, AstScope* pScope) + : AstType(NT_array, name, pScope) + , m_pType(pType) + , m_dimension((sal_uInt32)(rDimExpr.size())) + , m_dimExpressions(rDimExpr) +{ + if ( m_pType ) + setName(makeName()); +} + +AstArray::AstArray(AstType* pType, const ExprList& rDimExpr, AstScope* pScope) + : AstType(NT_array, OString("arrary_"), pScope) + , m_pType(pType) + , m_dimension((sal_uInt32)(rDimExpr.size())) + , m_dimExpressions(rDimExpr) +{ + if ( m_pType ) + setName(makeName()); +} + +OString AstArray::makeName() +{ + if ( m_pType ) + { + OString name(m_pType->getScopedName()); + OString openBracket("["); + OString closeBracket("]"); + ExprList::iterator iter = m_dimExpressions.begin(); + ExprList::iterator end = m_dimExpressions.end(); + + while ( iter != end ) + { + name += openBracket; + name += (*iter)->toString(); + name += closeBracket; + ++iter; + } + return name; + } + return OString(); +} diff --git a/idlc/source/astconstant.cxx b/idlc/source/astconstant.cxx new file mode 100644 index 000000000000..2f920508bd75 --- /dev/null +++ b/idlc/source/astconstant.cxx @@ -0,0 +1,136 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astconstant.hxx> +#include <idlc/astscope.hxx> + +#include "registry/writer.hxx" + +using namespace ::rtl; + +AstConstant::AstConstant(const ExprType type, + const NodeType nodeType, + AstExpression* pExpr, + const ::rtl::OString& name, + AstScope* pScope) + : AstDeclaration(nodeType, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::AstConstant(const ExprType type, + AstExpression* pExpr, + const ::rtl::OString& name, + AstScope* pScope) + : AstDeclaration(NT_const, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::~AstConstant() +{ + +} + +sal_Bool AstConstant::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, bool published) +{ + RTConstValue aConst; + sal_Unicode* str = NULL; + + AstExprValue *exprVal = getConstValue()->getExprValue(); + switch (getConstValueType()) + { + case ET_short: + aConst.m_type = RT_TYPE_INT16; + aConst.m_value.aShort = exprVal->u.sval; + break; + case ET_ushort: + aConst.m_type = RT_TYPE_UINT16; + aConst.m_value.aUShort = exprVal->u.usval; + break; + case ET_long: + aConst.m_type = RT_TYPE_INT32; + aConst.m_value.aLong = exprVal->u.lval; + break; + case ET_ulong: + aConst.m_type = RT_TYPE_UINT32; + aConst.m_value.aULong = exprVal->u.ulval; + break; + case ET_hyper: + aConst.m_type = RT_TYPE_INT64; + aConst.m_value.aHyper = exprVal->u.hval; + break; + case ET_uhyper: + aConst.m_type = RT_TYPE_UINT64; + aConst.m_value.aUHyper = exprVal->u.uhval; + break; + case ET_float: + aConst.m_type = RT_TYPE_FLOAT; + aConst.m_value.aFloat = exprVal->u.fval; + break; + case ET_double: + aConst.m_type = RT_TYPE_DOUBLE; + aConst.m_value.aDouble = exprVal->u.dval; + break; + case ET_byte: + aConst.m_type = RT_TYPE_BYTE; + aConst.m_value.aByte = exprVal->u.byval; + break; + case ET_boolean: + aConst.m_type = RT_TYPE_BOOL; + aConst.m_value.aBool = exprVal->u.bval; + break; + default: + { + fprintf(stderr, "%s: exprtype to const type: cannot convert ExprType\n", + idlc()->getOptions()->getProgramName().getStr()); + return sal_False; + } + } + + OString name = getLocalName(); + + OUString type; + if ( getNodeType() != NT_enum_val ) + { + type = OStringToOUString(exprTypeToString(getConstValueType()), RTL_TEXTENCODING_UTF8); + } + + rBlob.setFieldData( + index, getDocumentation(), OUString(), + RT_ACCESS_CONST | (published ? RT_ACCESS_PUBLISHED : 0), + OStringToOUString(name, RTL_TEXTENCODING_UTF8), type, aConst); + if (str) + delete[] str; + + return sal_True; +} diff --git a/idlc/source/astdeclaration.cxx b/idlc/source/astdeclaration.cxx new file mode 100644 index 000000000000..16e153e696e1 --- /dev/null +++ b/idlc/source/astdeclaration.cxx @@ -0,0 +1,211 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astdeclaration.hxx> +#include <idlc/astscope.hxx> +#include <rtl/strbuf.hxx> + +using namespace ::rtl; + +static OString sGlobal("::"); + +static OString convertName(const OString& name) +{ + OStringBuffer nameBuffer(name.getLength()+1); + sal_Int32 nIndex = 0; + do + { + OString token( name.getToken( 0, ':', nIndex ) ); + if( token.getLength() ) + { + nameBuffer.append('/'); + nameBuffer.append( token ); + } + } while( nIndex != -1 ); + return nameBuffer.makeStringAndClear(); +} + +AstDeclaration::AstDeclaration(NodeType type, const OString& name, AstScope* pScope) + : m_localName(name) + , m_pScope(pScope) + , m_nodeType(type) + , m_bImported(sal_False) + , m_bIsAdded(sal_False) + , m_bInMainFile(sal_False) + , m_bPredefined(false) +{ + if ( m_pScope ) + { + AstDeclaration* pDecl = scopeAsDecl(m_pScope); + if (pDecl) + { + m_scopedName = pDecl->getScopedName(); + if (m_scopedName.getLength() > 0) + m_scopedName += sGlobal; + m_scopedName += m_localName; + } + } else + { + m_scopedName = m_localName; + } + m_fullName = convertName(m_scopedName); + + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + { + m_fileName = idlc()->getMainFileName(); + m_bInMainFile = sal_True; + } else + { + m_fileName = idlc()->getFileName(); + m_bImported = sal_True; + } + + if ( idlc()->isDocValid() ) + m_documentation = OStringToOUString(idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8); + + m_bPublished = idlc()->isPublished(); +} + + +AstDeclaration::~AstDeclaration() +{ + +} + +void AstDeclaration::setPredefined(bool bPredefined) +{ + m_bPredefined = bPredefined; + if ( m_bPredefined ) + { + m_fileName = OString(); + m_bInMainFile = sal_False; + } +} + +void AstDeclaration::setName(const ::rtl::OString& name) +{ + m_scopedName = name; + sal_Int32 nIndex = name.lastIndexOf( ':' ); + m_localName = name.copy( nIndex+1 ); + +// Huh ? There is always at least one token + +// sal_Int32 count = name.getTokenCount(':'); + +// if ( count > 0 ) +// { +// m_localName = name.getToken(count-1, ':'); +// m_scopedName = name; +// } else if ( m_pScope ) +// { +// m_localName = name; +// AstDeclaration* pDecl = scopeAsDecl(m_pScope); +// if (pDecl) +// { +// m_scopedName = pDecl->getScopedName(); +// if (m_scopedName.getLength() > 0) +// m_scopedName += sGlobal; +// m_scopedName += m_localName; +// } +// } else +// { +// m_localName = name; +// m_scopedName = name; +// } + m_fullName = convertName(m_scopedName); +} + +bool AstDeclaration::isType() const { + switch (m_nodeType) { + case NT_interface: + case NT_instantiated_struct: + case NT_union: + case NT_enum: + case NT_sequence: + case NT_array: + case NT_typedef: + case NT_predefined: + case NT_type_parameter: + return true; + + default: + OSL_ASSERT(m_nodeType != NT_struct); // see AstStruct::isType + return false; + } +} + +sal_Bool AstDeclaration::hasAncestor(AstDeclaration* pDecl) +{ + if (this == pDecl) + return sal_True; + if ( !m_pScope ) + return sal_False; + return scopeAsDecl(m_pScope)->hasAncestor(pDecl); +} + +sal_Bool AstDeclaration::dump(RegistryKey& rKey) +{ + AstScope* pScope = declAsScope(this); + sal_Bool bRet = sal_True; + + if ( pScope ) + { + DeclList::const_iterator iter = pScope->getIteratorBegin(); + DeclList::const_iterator end = pScope->getIteratorEnd(); + AstDeclaration* pDecl = NULL; + while ( iter != end && bRet) + { + pDecl = *iter; + if ( pDecl->isInMainfile() ) + { + switch ( pDecl->getNodeType() ) + { + case NT_module: + case NT_constants: + case NT_interface: + case NT_struct: + case NT_exception: + case NT_enum: + case NT_union: + case NT_typedef: + case NT_service: + case NT_singleton: + bRet = pDecl->dump(rKey); + break; + default: + break; + } + } + + ++iter; + } + } + return bRet; +} + diff --git a/idlc/source/astdump.cxx b/idlc/source/astdump.cxx new file mode 100644 index 000000000000..3934cfb67e19 --- /dev/null +++ b/idlc/source/astdump.cxx @@ -0,0 +1,454 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astmodule.hxx> +#include <idlc/asttypedef.hxx> +#include <idlc/astservice.hxx> +#include <idlc/astconstant.hxx> +#include <idlc/astattribute.hxx> +#include <idlc/astinterfacemember.hxx> +#ifndef _IDLC_ASTSERVICEEMEMBER_HXX_ +#include <idlc/astservicemember.hxx> +#endif +#include <idlc/astobserves.hxx> +#include <idlc/astneeds.hxx> +#include <idlc/astsequence.hxx> +#include "idlc/astoperation.hxx" + +#include "registry/version.h" +#include "registry/writer.hxx" + +using namespace ::rtl; + +sal_Bool AstModule::dump(RegistryKey& rKey) +{ + OUString emptyStr; + RegistryKey localKey; + if ( getNodeType() == NT_root ) + { + localKey = rKey; + }else + { + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + } + + sal_uInt16 nConst = getNodeCount(NT_const); + + if ( nConst > 0 ) + { + RTTypeClass typeClass = RT_TYPE_MODULE; + if ( getNodeType() == NT_constants ) + typeClass = RT_TYPE_CONSTANTS; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), emptyStr, typeClass, + m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + sal_uInt16 index = 0; + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_const && + pDecl->isInMainfile() ) + { + ((AstConstant*)pDecl)->dumpBlob( + aBlob, index++, + getNodeType() == NT_module && pDecl->isPublished()); + } + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, + (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + } else + { + RTTypeClass typeClass = RT_TYPE_MODULE; + if ( getNodeType() == NT_constants ) + typeClass = RT_TYPE_CONSTANTS; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), emptyStr, typeClass, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, 0, 0, + 0); + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if ( getNodeType() != NT_root ) + { + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, + (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + } + } + if ( getNodeType() == NT_root ) + { + localKey.releaseKey(); + } + return AstDeclaration::dump(rKey); +} + +sal_Bool AstTypeDef::dump(RegistryKey& rKey) +{ + OUString emptyStr; + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), emptyStr, RT_TYPE_TYPEDEF, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1, 0, 0, 0); + aBlob.setSuperTypeName( + 0, + OStringToOUString( + getBaseType()->getRelativName(), RTL_TEXTENCODING_UTF8)); + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + return sal_True; +} + +sal_Bool AstService::dump(RegistryKey& rKey) +{ + OUString emptyStr; + typereg_Version version = m_bPublished + ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0; + OString superName; + sal_uInt16 constructors = 0; + sal_uInt16 properties = 0; + sal_uInt16 references = 0; + {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_interface: + case NT_typedef: + version = TYPEREG_VERSION_1; + OSL_ASSERT(superName.getLength() == 0); + superName = (*i)->getRelativName(); + break; + + case NT_operation: + OSL_ASSERT(getNodeType() == NT_service); + ++constructors; + break; + + case NT_property: + OSL_ASSERT(getNodeType() == NT_service); + ++properties; + break; + + case NT_service_member: + if (getNodeType() == NT_singleton) { + OSL_ASSERT(superName.getLength() == 0); + superName = ((AstServiceMember *)(*i))-> + getRealService()->getRelativName(); + break; + } + case NT_interface_member: + case NT_observes: + case NT_needs: + OSL_ASSERT(getNodeType() == NT_service); + ++references; + break; + + default: + OSL_ASSERT(false); + break; + } + }} + OSL_ASSERT(constructors == 0 || !m_defaultConstructor); + if (m_defaultConstructor) { + constructors = 1; + } + RegistryKey localKey; + if (rKey.createKey( + rtl::OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8), + localKey)) { + fprintf( + stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), + rtl::OUStringToOString( + rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + typereg::Writer writer( + version, getDocumentation(), emptyStr, + getNodeType() == NT_singleton ? RT_TYPE_SINGLETON : RT_TYPE_SERVICE, + m_bPublished, + rtl::OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + superName.getLength() == 0 ? 0 : 1, properties, constructors, + references); + if (superName.getLength() != 0) { + writer.setSuperTypeName( + 0, rtl::OStringToOUString(superName, RTL_TEXTENCODING_UTF8)); + } + sal_uInt16 constructorIndex = 0; + sal_uInt16 propertyIndex = 0; + sal_uInt16 referenceIndex = 0; + {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_operation: +// static_cast< AstOperation * >(*i)->dumpBlob( + ((AstOperation *)(*i))->dumpBlob( + writer, constructorIndex++); + break; + + case NT_property: +// static_cast< AstAttribute * >(*i)->dumpBlob( + ((AstAttribute *)(*i))->dumpBlob( + writer, propertyIndex++, 0); + break; + + case NT_interface_member: + { +// AstInterfaceMember * decl = static_cast< AstInterfaceMember *>(*i); + AstInterfaceMember * decl = (AstInterfaceMember *)(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RT_REF_SUPPORTS, + (decl->isOptional() + ? RT_ACCESS_OPTIONAL : RT_ACCESS_INVALID), + rtl::OStringToOUString( + decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_service_member: + if (getNodeType() == NT_service) { +// AstServiceMember * decl = static_cast< AstServiceMember * >(*i); + AstServiceMember * decl = (AstServiceMember *)(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RT_REF_EXPORTS, + (decl->isOptional() + ? RT_ACCESS_OPTIONAL : RT_ACCESS_INVALID), + rtl::OStringToOUString( + decl->getRealService()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + break; + + case NT_observes: + { +// AstObserves * decl = static_cast< AstObserves * >(*i); + AstObserves * decl = (AstObserves *)(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RT_REF_OBSERVES, + RT_ACCESS_INVALID, + rtl::OStringToOUString( + decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_needs: + { +// AstNeeds * decl = static_cast< AstNeeds * >(*i); + AstNeeds * decl = (AstNeeds *)(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RT_REF_NEEDS, + RT_ACCESS_INVALID, + rtl::OStringToOUString( + decl->getRealService()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + default: + OSL_ASSERT( + (*i)->getNodeType() == NT_interface + || (*i)->getNodeType() == NT_typedef); + break; + } + }} + if (m_defaultConstructor) { + writer.setMethodData( + constructorIndex++, emptyStr, RT_MODE_TWOWAY, + emptyStr, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")), + 0, 0); + } + sal_uInt32 size; + void const * blob = writer.getBlob(&size); + if (localKey.setValue( + emptyStr, RG_VALUETYPE_BINARY, const_cast< void * >(blob), + size)) + { + fprintf( + stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), + rtl::OUStringToOString( + localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return false; + } + return true; +} + +sal_Bool AstAttribute::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, sal_uInt16 * methodIndex) +{ + RTFieldAccess accessMode = RT_ACCESS_INVALID; + + if (isReadonly()) + { + accessMode |= RT_ACCESS_READONLY; + } else + { + accessMode |= RT_ACCESS_READWRITE; + } + if (isOptional()) + { + accessMode |= RT_ACCESS_OPTIONAL; + } + if (isBound()) + { + accessMode |= RT_ACCESS_BOUND; + } + if (isMayBeVoid()) + { + accessMode |= RT_ACCESS_MAYBEVOID; + } + if (isConstrained()) + { + accessMode |= RT_ACCESS_CONSTRAINED; + } + if (isTransient()) + { + accessMode |= RT_ACCESS_TRANSIENT; + } + if (isMayBeAmbiguous()) + { + accessMode |= RT_ACCESS_MAYBEAMBIGUOUS; + } + if (isMayBeDefault()) + { + accessMode |= RT_ACCESS_MAYBEDEFAULT; + } + if (isRemoveable()) + { + accessMode |= RT_ACCESS_REMOVEABLE; + } + + OUString name(OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8)); + rBlob.setFieldData( + index, getDocumentation(), OUString(), accessMode, name, + OStringToOUString(getType()->getRelativName(), RTL_TEXTENCODING_UTF8), + RTConstValue()); + dumpExceptions( + rBlob, m_getDocumentation, m_getExceptions, RT_MODE_ATTRIBUTE_GET, + methodIndex); + dumpExceptions( + rBlob, m_setDocumentation, m_setExceptions, RT_MODE_ATTRIBUTE_SET, + methodIndex); + + return sal_True; +} + +void AstAttribute::dumpExceptions( + typereg::Writer & writer, rtl::OUString const & documentation, + DeclList const & exceptions, RTMethodMode flags, sal_uInt16 * methodIndex) +{ + if (!exceptions.empty()) { + OSL_ASSERT(methodIndex != 0); + sal_uInt16 idx = (*methodIndex)++; + // exceptions.size() <= SAL_MAX_UINT16 already checked in + // AstInterface::dump: + writer.setMethodData( + idx, documentation, flags, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")), 0, + static_cast< sal_uInt16 >(exceptions.size())); + sal_uInt16 exceptionIndex = 0; + for (DeclList::const_iterator i(exceptions.begin()); + i != exceptions.end(); ++i) + { + writer.setMethodExceptionTypeName( + idx, exceptionIndex++, + rtl::OStringToOUString( + (*i)->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + } +} + +const sal_Char* AstSequence::getRelativName() const +{ + if ( !m_pRelativName ) + { + m_pRelativName = new OString("[]"); + AstDeclaration const * pType = resolveTypedefs( m_pMemberType ); + *m_pRelativName += pType->getRelativName(); + } + + return m_pRelativName->getStr(); +} diff --git a/idlc/source/astenum.cxx b/idlc/source/astenum.cxx new file mode 100644 index 000000000000..365b166be568 --- /dev/null +++ b/idlc/source/astenum.cxx @@ -0,0 +1,125 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astenum.hxx> + +#include "registry/version.h" +#include "registry/writer.hxx" + +using namespace ::rtl; + +AstEnum::AstEnum(const ::rtl::OString& name, AstScope* pScope) + : AstType(NT_enum, name, pScope) + , AstScope(NT_enum) + , m_enumValueCount(0) +{ +} + +AstEnum::~AstEnum() +{ +} + +AstConstant* AstEnum::checkValue(AstExpression* pExpr) +{ + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstConstant* pConst = NULL; + AstDeclaration* pDecl = NULL; + + while ( iter != end) + { + pDecl = *iter; + pConst = (AstConstant*)pDecl; + + if (pConst->getConstValue()->compare(pExpr)) + return pConst; + + ++iter; + } + + if ( pExpr->getExprValue()->u.lval > m_enumValueCount ) + m_enumValueCount = pExpr->getExprValue()->u.lval + 1; + + return NULL; +} + +sal_Bool AstEnum::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + OUString emptyStr; + sal_uInt16 nConst = getNodeCount(NT_enum_val); + if ( nConst > 0 ) + { + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), emptyStr, RT_TYPE_ENUM, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + sal_uInt16 index = 0; + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_enum_val ) + ((AstConstant*)pDecl)->dumpBlob(aBlob, index++, false); + + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, + (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + } + + return sal_True; +} + +AstDeclaration* AstEnum::addDeclaration(AstDeclaration* pDecl) +{ + return AstScope::addDeclaration(pDecl); +} diff --git a/idlc/source/astexpression.cxx b/idlc/source/astexpression.cxx new file mode 100644 index 000000000000..a93c13ecf8ba --- /dev/null +++ b/idlc/source/astexpression.cxx @@ -0,0 +1,1266 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astexpression.hxx> +#include <idlc/astconstant.hxx> +#include <idlc/astscope.hxx> +#include <idlc/errorhandler.hxx> + +#include <limits.h> +#include <float.h> + +#undef MAXCHAR +#define MAXCHAR 127 +#undef MINCHAR +#define MINCHAR -128 + +using namespace ::rtl; + +AstExpression::AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2) + : m_combOperator(c) + , m_subExpr1(pExpr1) + , m_subExpr2(pExpr2) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + +} + +AstExpression::AstExpression(sal_Int32 l) + : m_combOperator(EC_none) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + + m_exprValue = new AstExprValue(); + m_exprValue->et = ET_long; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int32 l, ExprType et) + : m_combOperator(EC_none) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + + m_exprValue = new AstExprValue(); + m_exprValue->et = et; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int64 h) + : m_combOperator(EC_none) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + + m_exprValue = new AstExprValue(); + m_exprValue->et = ET_hyper; + m_exprValue->u.hval = h; +} + +AstExpression::AstExpression(sal_uInt64 uh) + : m_combOperator(EC_none) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + + m_exprValue = new AstExprValue(); + m_exprValue->et = ET_uhyper; + m_exprValue->u.uhval = uh; +} + +AstExpression::AstExpression(double d) + : m_combOperator(EC_none) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(NULL) +{ + fillDefinitionDetails(); + + m_exprValue = new AstExprValue(); + m_exprValue->et = ET_double; + m_exprValue->u.dval = d; +} + +AstExpression::AstExpression(::rtl::OString* scopedName) + : m_combOperator(EC_symbol) + , m_subExpr1(NULL) + , m_subExpr2(NULL) + , m_exprValue(NULL) + , m_pSymbolicName(scopedName) +{ + fillDefinitionDetails(); +} + +AstExpression::~AstExpression() +{ + if ( m_exprValue ) + delete m_exprValue; + if ( m_subExpr1 ) + delete m_subExpr1; + if ( m_subExpr2 ) + delete m_subExpr2; + if ( m_pSymbolicName ) + delete m_pSymbolicName; +} + +/* + * Perform the coercion from the given AstExprValue to the requested + * ExprType. Return an AstExprValue if successful, NULL if failed. + * must be done for hyper, uhyper + */ +static AstExprValue * +coerce_value(AstExprValue *ev, ExprType t) +{ + if (ev == NULL) + return NULL; + + switch (t) + { + case ET_short: + switch (ev->et) + { + case ET_short: + return ev; + case ET_ushort: + if (ev->u.usval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.usval; + ev->et = ET_short; + return ev; + case ET_long: + if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.lval; + ev->et = ET_short; + return ev; + case ET_ulong: + if (ev->u.ulval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.ulval; + ev->et = ET_short; + return ev; + case ET_hyper: + if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.hval; + ev->et = ET_short; + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.uhval; + ev->et = ET_short; + return ev; + case ET_boolean: + ev->u.sval = (sal_Int16)ev->u.bval; + ev->et = ET_short; + return ev; + case ET_float: + if (ev->u.fval < SAL_MIN_INT16 || ev->u.fval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.fval; + ev->et = ET_short; + return ev; + case ET_double: + if (ev->u.dval < SAL_MIN_INT16 || ev->u.dval > SAL_MAX_INT16) + return NULL; + ev->u.sval = (sal_Int16)ev->u.dval; + ev->et = ET_short; + return ev; + case ET_byte: + ev->u.sval = (sal_Int16)ev->u.byval; + ev->et = ET_short; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_ushort: + switch (ev->et) + { + case ET_short: + if (ev->u.sval < 0) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.sval; + ev->et = ET_ushort; + return ev; + case ET_ushort: + return ev; + case ET_long: + if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.lval; + ev->et = ET_ushort; + return ev; + case ET_ulong: + if (ev->u.ulval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.ulval; + ev->et = ET_ushort; + return ev; + case ET_hyper: + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.hval; + ev->et = ET_ushort; + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.uhval; + ev->et = ET_ushort; + return ev; + case ET_boolean: + ev->u.usval = (sal_uInt16)ev->u.bval; + ev->et = ET_short; + return ev; + case ET_float: + if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.fval; + ev->et = ET_short; + return ev; + case ET_double: + if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT16) + return NULL; + ev->u.usval = (sal_uInt16)ev->u.dval; + ev->et = ET_short; + return ev; + case ET_byte: + ev->u.usval = (sal_uInt16)ev->u.byval; + ev->et = ET_ushort; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_long: + switch (ev->et) + { + case ET_short: + ev->u.lval = (sal_Int32)ev->u.sval; + ev->et = ET_long; + return ev; + case ET_ushort: + ev->u.lval = (sal_Int32)ev->u.usval; + ev->et = ET_long; + return ev; + case ET_long: + return ev; + case ET_ulong: + if (ev->u.ulval > SAL_MAX_INT32) + return NULL; + ev->u.lval = (sal_Int32)ev->u.ulval; + ev->et = ET_long; + return ev; + case ET_hyper: + if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32) + return NULL; + ev->u.lval = (sal_Int32)ev->u.hval; + ev->et = ET_long; + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_INT32) + return NULL; + ev->u.lval = (sal_Int32)ev->u.uhval; + ev->et = ET_long; + return ev; + case ET_boolean: + ev->u.lval = (sal_Int32)ev->u.bval; + ev->et = ET_long; + return ev; + case ET_float: + if (ev->u.fval < SAL_MIN_INT32 || ev->u.fval > SAL_MAX_INT32) + return NULL; + ev->u.lval = (sal_Int32)ev->u.fval; + ev->et = ET_long; + return ev; + case ET_double: + if (ev->u.dval < SAL_MIN_INT32 || ev->u.dval > SAL_MAX_INT32) + return NULL; + ev->u.lval = (sal_Int32)ev->u.dval; + ev->et = ET_long; + return ev; + case ET_byte: + ev->u.lval = (sal_Int32) ev->u.byval; + ev->et = ET_long; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_ulong: + switch (ev->et) + { + case ET_short: + if (ev->u.sval < 0) + return NULL; + ev->u.ulval = (sal_uInt32)ev->u.sval; + ev->et = ET_ulong; + return ev; + case ET_ushort: + ev->u.ulval = (sal_uInt32)ev->u.usval; + ev->et = ET_ulong; + return ev; + case ET_long: + if (ev->u.lval < 0) + return NULL; + ev->u.ulval = (sal_uInt32)ev->u.lval; + ev->et = ET_ulong; + return ev; + case ET_ulong: + return ev; + case ET_hyper: + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32) + return NULL; + ev->u.lval = (sal_uInt32)ev->u.hval; + ev->et = ET_ulong; + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_UINT32) + return NULL; + ev->u.ulval = (sal_uInt32)ev->u.uhval; + ev->et = ET_ulong; + return ev; + case ET_boolean: + ev->u.ulval = (sal_uInt32)ev->u.bval; + ev->et = ET_ulong; + return ev; + case ET_float: + if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT32) + return NULL; + ev->u.ulval = (sal_uInt32)ev->u.fval; + ev->et = ET_ulong; + return ev; + case ET_double: + if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT32) + return NULL; + ev->u.ulval = (sal_uInt32)ev->u.dval; + ev->et = ET_ulong; + return ev; + case ET_byte: + ev->u.ulval = (sal_uInt32)ev->u.byval; + ev->et = ET_ulong; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_hyper: + switch (ev->et) + { + case ET_short: + ev->u.hval = (sal_Int64)ev->u.sval; + ev->et = ET_hyper; + return ev; + case ET_ushort: + ev->u.hval = (sal_Int64)ev->u.usval; + ev->et = ET_hyper; + return ev; + case ET_long: + ev->u.hval = (sal_Int64)ev->u.lval; + ev->et = ET_hyper; + return ev; + case ET_ulong: + ev->u.hval = (sal_Int64)ev->u.ulval; + ev->et = ET_hyper; + return ev; + case ET_hyper: + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_INT64) + return NULL; + ev->u.hval = (sal_Int64)ev->u.uhval; + ev->et = ET_long; + return ev; + case ET_boolean: + ev->u.hval = (sal_Int64)ev->u.bval; + ev->et = ET_hyper; + return ev; + case ET_float: + if (ev->u.fval < SAL_MIN_INT64 || ev->u.fval > SAL_MAX_INT64) + return NULL; + ev->u.hval = (sal_Int64)ev->u.fval; + ev->et = ET_hyper; + return ev; + case ET_double: + if (ev->u.dval < SAL_MIN_INT64 || ev->u.dval > SAL_MAX_INT64) + return NULL; + ev->u.hval = (sal_Int64)ev->u.dval; + ev->et = ET_hyper; + return ev; + case ET_byte: + ev->u.hval = (sal_Int64)ev->u.byval; + ev->et = ET_hyper; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_uhyper: + switch (ev->et) + { + case ET_short: + if (ev->u.sval < 0) + return NULL; + ev->u.uhval = (sal_uInt64)ev->u.sval; + ev->et = ET_uhyper; + return ev; + case ET_ushort: + ev->u.uhval = (sal_uInt64)ev->u.usval; + ev->et = ET_uhyper; + return ev; + case ET_long: + if (ev->u.lval < 0) + return NULL; + ev->u.uhval = (sal_uInt64)ev->u.lval; + ev->et = ET_uhyper; + return ev; + case ET_ulong: + ev->u.uhval = (sal_uInt64)ev->u.ulval; + ev->et = ET_uhyper; + return ev; + case ET_hyper: + if (ev->u.hval < 0) + return NULL; + ev->u.uhval = (sal_uInt64)ev->u.hval; + ev->et = ET_uhyper; + return ev; + case ET_uhyper: + return ev; + case ET_boolean: + ev->u.uhval = (sal_uInt64)ev->u.bval; + ev->et = ET_uhyper; + return ev; + case ET_float: + if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT64) + return NULL; + ev->u.uhval = (sal_uInt64)ev->u.fval; + ev->et = ET_uhyper; + return ev; + case ET_double: + if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT64) + return NULL; + ev->u.uhval = (sal_uInt64)ev->u.dval; + ev->et = ET_uhyper; + return ev; + case ET_byte: + ev->u.uhval = (sal_uInt64)ev->u.byval; + ev->et = ET_uhyper; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_boolean: + switch (ev->et) + { + case ET_short: + ev->u.bval = (ev->u.sval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_ushort: + ev->u.bval = (ev->u.usval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_long: + ev->u.bval = (ev->u.lval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_ulong: + ev->u.bval = (ev->u.ulval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_hyper: + ev->u.bval = (ev->u.hval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_uhyper: + ev->u.bval = (ev->u.uhval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_boolean: + return ev; + case ET_float: + ev->u.bval = (ev->u.fval == 0.0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_double: + ev->u.bval = (ev->u.dval == 0.0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + case ET_byte: + ev->u.bval = (ev->u.byval == 0) ? sal_False : sal_True; + ev->et = ET_boolean; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_float: + switch (ev->et) + { + case ET_short: + ev->u.fval = (float)ev->u.sval; + ev->et = ET_float; + return ev; + case ET_ushort: + ev->u.fval = (float)ev->u.usval; + ev->et = ET_float; + return ev; + case ET_long: + ev->u.fval = (float)ev->u.lval; + ev->et = ET_float; + return ev; + case ET_ulong: + ev->u.fval = (float)ev->u.ulval; + ev->et = ET_float; + return ev; + case ET_hyper: + ev->u.fval = (float)ev->u.hval; + ev->et = ET_float; + return ev; + case ET_uhyper: + if ((float)ev->u.ulval > FLT_MAX) + return NULL; + ev->u.fval = (float)ev->u.ulval; + ev->et = ET_float; + return ev; + case ET_boolean: + ev->u.fval = (ev->u.bval == sal_True) ? 1.0f : 0.0f; + ev->et = ET_float; + return ev; + case ET_float: + return ev; + case ET_double: + if ((float)ev->u.dval > FLT_MAX || (float)ev->u.dval < -FLT_MAX) + return NULL; + ev->u.fval = (float)ev->u.dval; + ev->et = ET_float; + return ev; + case ET_byte: + ev->u.fval = (float)ev->u.byval; + ev->et = ET_float; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_double: + switch (ev->et) + { + case ET_short: + ev->u.dval = (double)ev->u.sval; + ev->et = ET_double; + return ev; + case ET_ushort: + ev->u.dval = (double)ev->u.usval; + ev->et = ET_double; + return ev; + case ET_long: + ev->u.dval = (double)ev->u.lval; + ev->et = ET_double; + return ev; + case ET_ulong: + ev->u.dval = (double)ev->u.ulval; + ev->et = ET_double; + return ev; + case ET_hyper: + ev->u.dval = (double)ev->u.hval; + ev->et = ET_double; + return ev; + case ET_uhyper: + if ((double)ev->u.dval > FLT_MAX || (double)ev->u.dval < -FLT_MAX) + return NULL; + ev->u.dval = (double)ev->u.ulval; + ev->et = ET_double; + return ev; + case ET_boolean: + ev->u.dval = (ev->u.bval == sal_True) ? 1.0 : 0.0; + ev->et = ET_double; + return ev; + case ET_float: + ev->u.dval = (double)ev->u.fval; + ev->et = ET_double; + return ev; + case ET_double: + return ev; + case ET_byte: + ev->u.dval = (double)ev->u.byval; + ev->et = ET_double; + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + case ET_byte: + switch (ev->et) + { + case ET_short: + if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar)ev->u.sval; + ev->et = ET_byte; + return ev; + case ET_ushort: + if (ev->u.usval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar)ev->u.usval; + ev->et = ET_byte; + return ev; + case ET_long: + if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.lval; + ev->et = ET_byte; + return ev; + case ET_ulong: + if (ev->u.ulval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.ulval; + ev->et = ET_byte; + return ev; + case ET_hyper: + if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.hval; + ev->et = ET_byte; + return ev; + case ET_uhyper: + if (ev->u.uhval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.uhval; + ev->et = ET_byte; + return ev; + case ET_boolean: + ev->u.byval = (ev->u.bval == sal_False) ? 1 : 0; + ev->et = ET_byte; + return ev; + case ET_float: + if (ev->u.fval < SAL_MIN_INT8 || ev->u.fval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.fval; + ev->et = ET_byte; + return ev; + case ET_double: + if (ev->u.dval < SAL_MIN_INT8 || ev->u.dval > SAL_MAX_UINT8) + return NULL; + ev->u.byval = (sal_uChar) ev->u.dval; + ev->et = ET_byte; + return ev; + case ET_byte: + return ev; + default: + OSL_ASSERT(false); + return NULL; + } + default: + OSL_ASSERT(false); + return NULL; + } +} + +/* + * Evaluate the expression with the evaluation kind requested. Supported + * evaluation kinds are + * - EK_const: The expression must evaluate to a constant + * - EK_positive_int: The expression must further evaluate to a + * positive integer + */ +static AstExprValue * +eval_kind(AstExprValue *ev, EvalKind ek) +{ + if (ek == EK_const) + return ev; + if (ek == EK_positive_int) + return coerce_value(ev, ET_ulong); + + return NULL; +} + +AstExprValue* AstExpression::coerce(ExprType t, sal_Bool bAssign) +{ + AstExprValue *copy; + + /* + * Is it already of the right type? + */ + if (m_exprValue != NULL && m_exprValue->et == t) + return m_exprValue; + /* + * OK, must coerce + * + * First, evaluate it, then try to coerce result type + * If already evaluated, return the result + */ + m_exprValue = eval_internal(EK_const); + if (m_exprValue == NULL) + return NULL; + + /* + * Create a copy to contain coercion result + */ + copy = new AstExprValue; + + copy->et = m_exprValue->et; + switch (m_exprValue->et) + { + case ET_short: + copy->u.sval = m_exprValue->u.sval; + break; + case ET_ushort: + copy->u.usval = m_exprValue->u.usval; + break; + case ET_long: + copy->u.lval = m_exprValue->u.lval; + break; + case ET_ulong: + copy->u.ulval = m_exprValue->u.ulval; + break; + case ET_hyper: + copy->u.hval = m_exprValue->u.hval; + break; + case ET_uhyper: + copy->u.uhval = m_exprValue->u.uhval; + break; + case ET_boolean: + copy->u.bval = m_exprValue->u.bval; + break; + case ET_float: + copy->u.fval = m_exprValue->u.fval; + break; + case ET_double: + copy->u.dval = m_exprValue->u.dval; + break; + case ET_byte: + copy->u.byval = m_exprValue->u.byval; + break; + default: + OSL_ASSERT(false); + break; + } + + if (bAssign) + { + m_exprValue = coerce_value(copy, t); + return m_exprValue; + } + + return coerce_value(copy, t); +} + +void AstExpression::evaluate(EvalKind ek) +{ + m_exprValue = eval_internal(ek); + m_exprValue = eval_kind(m_exprValue, ek); +} + +sal_Bool AstExpression::operator==(AstExpression *pExpr) +{ + if (m_combOperator != pExpr->getCombOperator()) + return sal_False; + evaluate(EK_const); + pExpr->evaluate(EK_const); + if (m_exprValue == NULL || pExpr->getExprValue() == NULL) + return sal_False; + if (m_exprValue->et != pExpr->getExprValue()->et) + return sal_False; + switch (m_exprValue->et) + { + case ET_short: + return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False; + case ET_ushort: + return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False; + case ET_long: + return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; + case ET_ulong: + return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False; + case ET_hyper: + return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False; + case ET_uhyper: + return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False; + case ET_float: + return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False; + case ET_double: + return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False; + case ET_byte: + return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False; + case ET_boolean: + return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; + default: + OSL_ASSERT(false); + return sal_False; + } + + return sal_False; +} + +sal_Bool AstExpression::compare(AstExpression *pExpr) +{ + if (m_combOperator != pExpr->getCombOperator()) + return sal_False; + evaluate(EK_const); + pExpr->evaluate(EK_const); + if (m_exprValue == NULL || pExpr->getExprValue() == NULL) + return sal_False; + if (m_exprValue->et != pExpr->getExprValue()->et) + return sal_False; + switch (m_exprValue->et) + { + case ET_short: + return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False; + case ET_ushort: + return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False; + case ET_long: + return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; + case ET_ulong: + return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False; + case ET_hyper: + return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False; + case ET_uhyper: + return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False; + case ET_float: + return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False; + case ET_double: + return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False; + case ET_byte: + return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False; + case ET_boolean: + return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; + default: + OSL_ASSERT(false); + return sal_False; + } + + return sal_False; +} + +void AstExpression::fillDefinitionDetails() +{ + m_pScope = idlc()->scopes()->depth() > 0 ? idlc()->scopes()->top() : NULL; + m_lineNo = idlc()->getLineNumber(); + m_fileName = idlc()->getFileName(); +} + +AstExprValue* AstExpression::eval_internal(EvalKind ek) +{ + /* + * Already evaluated? + */ + if ( m_exprValue != NULL ) + return eval_kind(m_exprValue, ek); + /* + * OK, must evaluate operator + */ + switch (m_combOperator) + { + case EC_add: + case EC_minus: + case EC_mul: + case EC_div: + case EC_mod: + m_exprValue = eval_bin_op(ek); + return eval_kind(m_exprValue, ek); + case EC_or: + case EC_xor: + case EC_and: + case EC_left: + case EC_right: + m_exprValue = eval_bit_op(ek); + return eval_kind(m_exprValue, ek); + case EC_u_plus: + case EC_u_minus: + case EC_bit_neg: + m_exprValue = eval_un_op(ek); + return eval_kind(m_exprValue, ek); + case EC_symbol: + m_exprValue = eval_symbol(ek); + return eval_kind(m_exprValue, ek); + case EC_none: + return NULL; + } + + return NULL; +} + +AstExprValue* AstExpression::eval_bin_op(EvalKind ek) +{ + AstExprValue *retval = NULL; + ExprType eType = ET_double; + + if ( m_combOperator == EC_mod ) + eType = ET_hyper; + + if (ek != EK_const && ek != EK_positive_int) + return NULL; + if (m_subExpr1 == NULL || m_subExpr2 == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->coerce(eType)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek)); + if (m_subExpr2->getExprValue() == NULL) + return NULL; + m_subExpr2->setExprValue(m_subExpr2->coerce(eType)); + if (m_subExpr2->getExprValue() == NULL) + return NULL; + + retval = new AstExprValue(); + retval->et = eType; + + switch (m_combOperator) + { + case EC_mod: + if (m_subExpr2->getExprValue()->u.hval == 0) + return NULL; + retval->u.hval = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval; + break; + case EC_add: + retval->u.dval = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval; + break; + case EC_minus: + retval->u.dval = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval; + break; + case EC_mul: + retval->u.dval = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval; + break; + case EC_div: + if (m_subExpr2->getExprValue()->u.dval == 0.0) + return NULL; + retval->u.dval = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval; + break; + default: + return NULL; + } + + return retval; +} + +AstExprValue* AstExpression::eval_bit_op(EvalKind ek) +{ + AstExprValue *retval = NULL; + + if (ek != EK_const && ek != EK_positive_int) + return NULL; + if (m_subExpr1 == NULL || m_subExpr2 == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek)); + if (m_subExpr2->getExprValue() == NULL) + return NULL; + m_subExpr2->setExprValue(m_subExpr2->coerce(ET_long)); + if (m_subExpr2->getExprValue() == NULL) + return NULL; + + retval = new AstExprValue; + retval->et = ET_long; + + switch (m_combOperator) + { + case EC_or: + retval->u.lval = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval; + break; + case EC_xor: + retval->u.lval = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval; + break; + case EC_and: + retval->u.lval = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval; + break; + case EC_left: + retval->u.lval = m_subExpr1->getExprValue()->u.lval << m_subExpr2->getExprValue()->u.lval; + break; + case EC_right: + retval->u.lval = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval; + break; + default: + return NULL; + } + + return retval; +} + +AstExprValue* AstExpression::eval_un_op(EvalKind ek) +{ + AstExprValue *retval = NULL; + + if (m_exprValue != NULL) + return m_exprValue; + + if (ek != EK_const && ek != EK_positive_int) + return NULL; + if (m_subExpr1 == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + m_subExpr1->setExprValue(m_subExpr1->coerce(ET_double)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + + retval = new AstExprValue(); + retval->et = ET_double; + + switch (m_combOperator) + { + case EC_u_plus: + retval->u.lval = m_subExpr1->getExprValue()->u.lval; + break; + case EC_u_minus: + retval->u.lval = -(m_subExpr1->getExprValue()->u.lval); + break; + case EC_bit_neg: + m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long)); + if (m_subExpr1->getExprValue() == NULL) + return NULL; + retval->u.lval = ~m_subExpr1->getExprValue()->u.lval; + break; + default: + return NULL; + } + + return retval; +} + +AstExprValue* AstExpression::eval_symbol(EvalKind ek) +{ + AstScope *pScope = 0; + AstDeclaration *pDecl; + AstConstant *pConst; + + /* + * Is there a symbol stored? + */ + if (m_pSymbolicName == NULL) + { + idlc()->error()->evalError(this); + return NULL; + } + /* + * Get current scope for lookup + */ + if (idlc()->scopes()->depth() > 0) + pScope = idlc()->scopes()->topNonNull(); + if ( !pScope ) + { + idlc()->error()->lookupError(*m_pSymbolicName); + return NULL; + } + /* + * Do lookup + */ + pDecl = pScope->lookupByName(*m_pSymbolicName); + if (pDecl == NULL) + { + idlc()->error()->lookupError(*m_pSymbolicName); + return NULL; + } + /* + * Is it a constant? + */ + if (pDecl->getNodeType() != NT_const && + pDecl->getNodeType() != NT_enum_val) + { + idlc()->error()->constantExpected(pDecl, *m_pSymbolicName); + return NULL; + } + if (!idlc()->error()->checkPublished(pDecl)) + { + return NULL; + } + /* + * OK, now evaluate the constant we just got, to produce its value + */ + pConst = static_cast< AstConstant* >(pDecl); + if (pConst == NULL) + return NULL; + return pConst->getConstValue()->eval_internal(ek); +} + +OString AstExpression::toString() +{ + OString exprStr; + if ( m_combOperator == EC_symbol ) + return *m_pSymbolicName; + + if ( m_exprValue ) + { + switch (m_exprValue->et) + { + case ET_short: + return OString::valueOf((sal_Int32)m_exprValue->u.sval); + case ET_ushort: + return OString::valueOf((sal_Int32)m_exprValue->u.usval); + case ET_long: + return OString::valueOf(m_exprValue->u.lval); + case ET_ulong: + return OString::valueOf((sal_Int32)m_exprValue->u.ulval); + case ET_hyper: + return OString::valueOf(m_exprValue->u.hval); + case ET_uhyper: + return OString::valueOf((sal_Int64)m_exprValue->u.uhval); + case ET_float: + return OString::valueOf(m_exprValue->u.fval); + case ET_double: + return OString::valueOf(m_exprValue->u.dval); + case ET_byte: + return OString::valueOf((sal_Int32)m_exprValue->u.byval); + case ET_boolean: + if ( m_exprValue->u.lval == 0) + return OString("FALSE"); + else + return OString("TRUE"); + default: + OSL_ASSERT(false); + return OString(); + } + } + + switch (m_combOperator) + { + case EC_u_plus: + exprStr += OString("+"); + break; + case EC_u_minus: + exprStr += OString("-"); + break; + case EC_bit_neg: + exprStr += OString("~"); + break; + default: + break; + } + if ( m_subExpr1 ) + exprStr += m_subExpr1->toString(); + switch (m_combOperator) + { + case EC_add: + exprStr += OString(" + "); + break; + case EC_minus: + exprStr += OString(" - "); + break; + case EC_mul: + exprStr += OString(" * "); + break; + case EC_div: + exprStr += OString(" / "); + break; + case EC_mod: + exprStr += OString(" % "); + break; + case EC_or: + exprStr += OString(" | "); + break; + case EC_xor: + exprStr += OString(" ^ "); + break; + case EC_and: + exprStr += OString(" & "); + break; + case EC_left: + exprStr += OString(" << "); + break; + case EC_right: + exprStr += OString(" >> "); + break; + default: + break; + } + + if ( m_subExpr2 ) + exprStr += m_subExpr2->toString(); + + return exprStr; +} + +// Convert the type of an AST_Expression to a char * +const sal_Char* SAL_CALL exprTypeToString(ExprType t) +{ + switch (t) + { + case ET_short: + return "short"; + case ET_ushort: + return "unsigned short"; + case ET_long: + return "long"; + case ET_ulong: + return "unsigned long"; + case ET_hyper: + return "hyper"; + case ET_uhyper: + return "unsigned hyper"; + case ET_float: + return "float"; + case ET_double: + return "double"; + case ET_char: + return "char"; + case ET_byte: + return "byte"; + case ET_boolean: + return "boolean"; + case ET_string: + return "string"; + case ET_any: + return "any"; + case ET_type: + return "type"; + case ET_void: + return "void"; + case ET_none: + return "none"; + } + + return ("unkown"); +} diff --git a/idlc/source/astinterface.cxx b/idlc/source/astinterface.cxx new file mode 100644 index 000000000000..97bea094c53c --- /dev/null +++ b/idlc/source/astinterface.cxx @@ -0,0 +1,427 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astinterface.hxx> +#include <idlc/astattribute.hxx> +#include <idlc/astoperation.hxx> +#include "idlc/idlc.hxx" + +#include "registry/version.h" +#include "registry/writer.hxx" + +using namespace ::rtl; + +AstInterface::AstInterface(const ::rtl::OString& name, + AstInterface const * pInherits, + AstScope* pScope) + : AstType(NT_interface, name, pScope) + , AstScope(NT_interface) + , m_mandatoryInterfaces(0) + , m_bIsDefined(false) + , m_bForwarded(sal_False) + , m_bForwardedInSameFile(sal_False) + , m_bSingleInheritance(pInherits != 0) +{ + if (pInherits != 0) { + addInheritedInterface(pInherits, false, rtl::OUString()); + } +} + +AstInterface::~AstInterface() +{ +} + +AstInterface::DoubleDeclarations AstInterface::checkInheritedInterfaceClashes( + AstInterface const * ifc, bool optional) const +{ + DoubleDeclarations doubleDecls; + std::set< rtl::OString > seen; + checkInheritedInterfaceClashes( + doubleDecls, seen, ifc, true, optional, optional); + return doubleDecls; +} + +void AstInterface::addInheritedInterface( + AstType const * ifc, bool optional, rtl::OUString const & documentation) +{ + m_inheritedInterfaces.push_back( + InheritedInterface(ifc, optional, documentation)); + if (!optional) { + ++m_mandatoryInterfaces; + } + AstInterface const * resolved = resolveInterfaceTypedefs(ifc); + addVisibleInterface(resolved, true, optional); + if (optional) { + addOptionalVisibleMembers(resolved); + } +} + +AstInterface::DoubleMemberDeclarations AstInterface::checkMemberClashes( + AstDeclaration const * member) const +{ + DoubleMemberDeclarations doubleMembers; + checkMemberClashes(doubleMembers, member, true); + return doubleMembers; +} + +void AstInterface::addMember(AstDeclaration /*TODO: const*/ * member) { + addDeclaration(member); + m_visibleMembers.insert( + VisibleMembers::value_type( + member->getLocalName(), VisibleMember(member))); +} + +void AstInterface::forwardDefined(AstInterface const & def) +{ + setImported(def.isImported()); + setInMainfile(def.isInMainfile()); + setLineNumber(def.getLineNumber()); + setFileName(def.getFileName()); + setDocumentation(def.getDocumentation()); + m_inheritedInterfaces = def.m_inheritedInterfaces; + m_mandatoryInterfaces = def.m_mandatoryInterfaces; + m_bIsDefined = true; +} + +sal_Bool AstInterface::dump(RegistryKey& rKey) +{ + if ( !isDefined() ) + return sal_True; + + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + if (m_mandatoryInterfaces > SAL_MAX_UINT16 + || m_inheritedInterfaces.size() - m_mandatoryInterfaces + > SAL_MAX_UINT16) + { + fprintf( + stderr, "%s: interface %s has too many direct base interfaces\n", + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr()); + return false; + } + sal_uInt16 nBaseTypes = static_cast< sal_uInt16 >(m_mandatoryInterfaces); + sal_uInt16 nAttributes = 0; + sal_uInt16 nMethods = 0; + sal_uInt16 nReferences = static_cast< sal_uInt16 >( + m_inheritedInterfaces.size() - m_mandatoryInterfaces); + typereg_Version version + = (nBaseTypes <= 1 && nReferences == 0 && !m_bPublished + ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1); + {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_attribute: + { + if (!increment(&nAttributes, "attributes")) { + return false; + } +// AstAttribute * attr = static_cast< AstAttribute * >(*i); + AstAttribute * attr = (AstAttribute *)(*i); + if (attr->isBound()) { + version = TYPEREG_VERSION_1; + } + DeclList::size_type getCount = attr->getGetExceptionCount(); + if (getCount > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: raises clause of getter for attribute %s of" + " interface %s is too long\n"), + idlc()->getOptions()->getProgramName().getStr(), + (*i)->getLocalName().getStr(), + getScopedName().getStr()); + return false; + } + if (getCount > 0) { + version = TYPEREG_VERSION_1; + if (!increment(&nMethods, "attributes")) { + return false; + } + } + DeclList::size_type setCount = attr->getSetExceptionCount(); + if (setCount > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: raises clause of setter for attribute %s of" + " interface %s is too long\n"), + idlc()->getOptions()->getProgramName().getStr(), + (*i)->getLocalName().getStr(), + getScopedName().getStr()); + return false; + } + if (setCount > 0) { + version = TYPEREG_VERSION_1; + if (!increment(&nMethods, "attributes")) { + return false; + } + } + break; + } + + case NT_operation: + if (!increment(&nMethods, "methods")) { + return false; + } + break; + + default: + OSL_ASSERT(false); + break; + } + }} + + OUString emptyStr; + typereg::Writer aBlob( + version, getDocumentation(), emptyStr, RT_TYPE_INTERFACE, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), nBaseTypes, + nAttributes, nMethods, nReferences); + + sal_uInt16 superTypeIndex = 0; + sal_uInt16 referenceIndex = 0; + {for (InheritedInterfaces::iterator i = m_inheritedInterfaces.begin(); + i != m_inheritedInterfaces.end(); ++i) + { + if (i->isOptional()) { + aBlob.setReferenceData( + referenceIndex++, i->getDocumentation(), RT_REF_SUPPORTS, + RT_ACCESS_OPTIONAL, + OStringToOUString( + i->getInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } else { + aBlob.setSuperTypeName( + superTypeIndex++, + OStringToOUString( + i->getInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + }} + + sal_uInt16 attributeIndex = 0; + sal_uInt16 methodIndex = 0; + {for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + switch ((*i)->getNodeType()) { + case NT_attribute: +// static_cast< AstAttribute * >(*i)->dumpBlob( + + ((AstAttribute *)(*i))->dumpBlob( + aBlob, attributeIndex++, &methodIndex); + break; + + case NT_operation: +// static_cast< AstOperation * >(*i)->dumpBlob(aBlob, methodIndex++); + ((AstOperation *)(*i))->dumpBlob(aBlob, methodIndex++); + break; + + default: + OSL_ASSERT(false); + break; + } + }} + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + return true; +} + +void AstInterface::checkInheritedInterfaceClashes( + DoubleDeclarations & doubleDeclarations, + std::set< rtl::OString > & seenInterfaces, AstInterface const * ifc, + bool direct, bool optional, bool mainOptional) const +{ + if (direct || optional + || seenInterfaces.insert(ifc->getScopedName()).second) + { + VisibleInterfaces::const_iterator visible( + m_visibleInterfaces.find(ifc->getScopedName())); + if (visible != m_visibleInterfaces.end()) { + switch (visible->second) { + case INTERFACE_INDIRECT_OPTIONAL: + if (direct && optional) { + doubleDeclarations.interfaces.push_back(ifc); + return; + } + break; + + case INTERFACE_DIRECT_OPTIONAL: + if (direct || !mainOptional) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + + case INTERFACE_INDIRECT_MANDATORY: + if (direct) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + + case INTERFACE_DIRECT_MANDATORY: + if (direct || (!optional && !mainOptional)) { + doubleDeclarations.interfaces.push_back(ifc); + } + return; + } + } + if (direct || !optional) { + {for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + checkMemberClashes( + doubleDeclarations.members, *i, !mainOptional); + }} + {for (InheritedInterfaces::const_iterator i( + ifc->m_inheritedInterfaces.begin()); + i != ifc->m_inheritedInterfaces.end(); ++i) + { + checkInheritedInterfaceClashes( + doubleDeclarations, seenInterfaces, i->getResolved(), + false, i->isOptional(), mainOptional); + }} + } + } +} + +void AstInterface::checkMemberClashes( + DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member, + bool checkOptional) const +{ + VisibleMembers::const_iterator i( + m_visibleMembers.find(member->getLocalName())); + if (i != m_visibleMembers.end()) { + if (i->second.mandatory != 0) { + if (i->second.mandatory->getScopedName() != member->getScopedName()) + { + DoubleMemberDeclaration d; + d.first = i->second.mandatory; + d.second = member; + doubleMembers.push_back(d); + } + } else if (checkOptional) { + for (VisibleMember::Optionals::const_iterator j( + i->second.optionals.begin()); + j != i->second.optionals.end(); ++j) + { + if (j->second->getScopedName() != member->getScopedName()) { + DoubleMemberDeclaration d; + d.first = j->second; + d.second = member; + doubleMembers.push_back(d); + } + } + } + } +} + +void AstInterface::addVisibleInterface( + AstInterface const * ifc, bool direct, bool optional) +{ + InterfaceKind kind = optional + ? direct ? INTERFACE_DIRECT_OPTIONAL : INTERFACE_INDIRECT_OPTIONAL + : direct ? INTERFACE_DIRECT_MANDATORY : INTERFACE_INDIRECT_MANDATORY; + std::pair< VisibleInterfaces::iterator, bool > result( + m_visibleInterfaces.insert( + VisibleInterfaces::value_type(ifc->getScopedName(), kind))); + bool seen = !result.second + && result.first->second >= INTERFACE_INDIRECT_MANDATORY; + if (!result.second && kind > result.first->second) { + result.first->second = kind; + } + if (!optional && !seen) { + {for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + m_visibleMembers.insert( + VisibleMembers::value_type( + (*i)->getLocalName(), VisibleMember(*i))); + }} + {for (InheritedInterfaces::const_iterator i( + ifc->m_inheritedInterfaces.begin()); + i != ifc->m_inheritedInterfaces.end(); ++i) + { + addVisibleInterface(i->getResolved(), false, i->isOptional()); + }} + } +} + +void AstInterface::addOptionalVisibleMembers(AstInterface const * ifc) { + {for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + VisibleMembers::iterator visible( + m_visibleMembers.find((*i)->getLocalName())); + if (visible == m_visibleMembers.end()) { + visible = m_visibleMembers.insert( + VisibleMembers::value_type( + (*i)->getLocalName(), VisibleMember())).first; + } + if (visible->second.mandatory == 0) { + visible->second.optionals.insert( + VisibleMember::Optionals::value_type(ifc->getScopedName(), *i)); + } + }} + {for (InheritedInterfaces::const_iterator i( + ifc->m_inheritedInterfaces.begin()); + i != ifc->m_inheritedInterfaces.end(); ++i) + { + if (!i->isOptional()) { + addOptionalVisibleMembers(i->getResolved()); + } + }} +} + +bool AstInterface::increment(sal_uInt16 * counter, char const * sort) const { + if (*counter == SAL_MAX_UINT16) { + fprintf( + stderr, "%s: interface %s has too many direct %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr(), sort); + return false; + } + ++*counter; + return true; +} diff --git a/idlc/source/astoperation.cxx b/idlc/source/astoperation.cxx new file mode 100644 index 000000000000..5fff08ee7404 --- /dev/null +++ b/idlc/source/astoperation.cxx @@ -0,0 +1,153 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astoperation.hxx> +#include <idlc/asttype.hxx> +#include <idlc/astbasetype.hxx> +#include <idlc/astparameter.hxx> +#include <idlc/errorhandler.hxx> + +#include "registry/writer.hxx" + +using namespace ::rtl; + +void AstOperation::setExceptions(DeclList const * pExceptions) +{ + if (pExceptions != 0) { + if (isOneway()) { + idlc()->error()->error1(EIDL_ONEWAY_RAISE_CONFLICT, this); + } + m_exceptions = *pExceptions; + } +} + +bool AstOperation::isVariadic() const { + DeclList::const_iterator i(getIteratorEnd()); + return i != getIteratorBegin() + && static_cast< AstParameter const * >(*(--i))->isRest(); +} + +sal_Bool AstOperation::dumpBlob(typereg::Writer & rBlob, sal_uInt16 index) +{ + sal_uInt16 nParam = getNodeCount(NT_parameter); + sal_uInt16 nExcep = nExceptions(); + RTMethodMode methodMode = RT_MODE_TWOWAY; + + if ( isOneway() ) + methodMode = RT_MODE_ONEWAY; + + rtl::OUString returnTypeName; + if (m_pReturnType == 0) { + returnTypeName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("void")); + } else { + returnTypeName = rtl::OStringToOUString( + m_pReturnType->getRelativName(), RTL_TEXTENCODING_UTF8); + } + rBlob.setMethodData( + index, getDocumentation(), methodMode, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + returnTypeName, nParam, nExcep); + + if ( nParam ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + RTParamMode paramMode; + sal_uInt16 paramIndex = 0; + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_parameter ) + { + AstParameter* pParam = (AstParameter*)pDecl; + switch (pParam->getDirection()) + { + case DIR_IN : + paramMode = RT_PARAM_IN; + break; + case DIR_OUT : + paramMode = RT_PARAM_OUT; + break; + case DIR_INOUT : + paramMode = RT_PARAM_INOUT; + break; + default: + paramMode = RT_PARAM_INVALID; + break; + } + if (pParam->isRest()) { + paramMode = static_cast< RTParamMode >( + paramMode | RT_PARAM_REST); + } + + rBlob.setMethodParameterData( + index, paramIndex++, paramMode, + OStringToOUString( + pDecl->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString( + pParam->getType()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + ++iter; + } + } + + if ( nExcep ) + { + DeclList::iterator iter = m_exceptions.begin(); + DeclList::iterator end = m_exceptions.end(); + sal_uInt16 exceptIndex = 0; + while ( iter != end ) + { + rBlob.setMethodExceptionTypeName( + index, exceptIndex++, + OStringToOUString( + (*iter)->getRelativName(), RTL_TEXTENCODING_UTF8)); + ++iter; + } + } + + return sal_True; +} + +AstDeclaration* AstOperation::addDeclaration(AstDeclaration* pDecl) +{ + if ( pDecl->getNodeType() == NT_parameter ) + { + AstParameter* pParam = (AstParameter*)pDecl; + if ( isOneway() && + (pParam->getDirection() == DIR_OUT || pParam->getDirection() == DIR_INOUT) ) + { + idlc()->error()->error2(EIDL_ONEWAY_CONFLICT, pDecl, this); + return NULL; + } + } + return AstScope::addDeclaration(pDecl); +} diff --git a/idlc/source/astscope.cxx b/idlc/source/astscope.cxx new file mode 100644 index 000000000000..4d1e182320e0 --- /dev/null +++ b/idlc/source/astscope.cxx @@ -0,0 +1,356 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astscope.hxx> +#include <idlc/astbasetype.hxx> +#ifndef _IDLC_ASTINERFACE_HXX_ +#include <idlc/astinterface.hxx> +#endif +#include <idlc/errorhandler.hxx> + + +using namespace ::rtl; + +sal_Bool isGlobal(const OString& scopedName) +{ + if ((scopedName.getLength() == 0) || (scopedName.indexOf(':') == 0)) + { + return sal_True; + } + return sal_False; +} + +AstScope::AstScope(NodeType nodeType) + : m_nodeType(nodeType) +{ + +} + +AstScope::~AstScope() +{ + +} + +AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl) +{ + AstDeclaration* pDeclaration = NULL; + + if ((pDeclaration = lookupForAdd(pDecl)) != NULL) + { + if (pDecl->getNodeType() == NT_union_branch ) + { + m_declarations.push_back(pDecl); + return pDecl; + } + if ( pDecl->hasAncestor(pDeclaration) ) + { + idlc()->error()->error2(EIDL_REDEF_SCOPE, pDecl, pDeclaration); + return NULL; + } + if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) && + (pDecl->getNodeType() == NT_sequence + || pDecl->getNodeType() == NT_array + || pDecl->getNodeType() == NT_instantiated_struct) ) + { + return pDeclaration; + } + if ( (pDeclaration->getNodeType() == NT_interface) + && (pDecl->getNodeType() == NT_interface) + && !((AstInterface*)pDeclaration)->isDefined() ) + { + m_declarations.push_back(pDecl); + return pDecl; + } + if ( (NT_service == m_nodeType) && + ( ((pDecl->getNodeType() == NT_interface_member) + && (pDeclaration->getNodeType() == NT_interface)) || + ((pDecl->getNodeType() == NT_service_member) + && (pDeclaration->getNodeType() == NT_service)) ) + ) + { + m_declarations.push_back(pDecl); + return pDecl; + } + + idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(this), pDecl); + return NULL; + } + + m_declarations.push_back(pDecl); + return pDecl; +} + +sal_uInt16 AstScope::getNodeCount(NodeType nodeType) +{ + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + sal_uInt16 count = 0; + + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == nodeType ) + count++; + ++iter; + } + return count; +} + +AstDeclaration* AstScope::lookupByName(const OString& scopedName) +{ + AstDeclaration* pDecl = NULL; + AstScope* pScope = NULL; + if (scopedName.getLength() == 0) + return NULL; + + // If name starts with "::" start look up in global scope + if ( isGlobal(scopedName) ) + { + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return NULL; + + pScope = pDecl->getScope(); + // If this is the global scope ... + if ( !pScope ) + { + // look up the scopedName part after "::" + OString subName = scopedName.copy(2); + pDecl = lookupByName(subName); + return pDecl; + //return pScope->lookupByName(); + } + // OK, not global scope yet, so simply iterate with parent scope + pDecl = pScope->lookupByName(scopedName); + return pDecl; + } + + // The name does not start with "::" + // Look up in the local scope and start with the first scope + sal_Int32 nIndex = scopedName.indexOf(':'); + OString firstScope = nIndex > 0 ? scopedName.copy(0, nIndex) : scopedName; + sal_Bool bFindFirstScope = sal_True; + pDecl = lookupByNameLocal(firstScope); + if ( !pDecl ) + { + bFindFirstScope = sal_False; + + // OK, not found. Go down parent scope chain + pDecl = scopeAsDecl(this); + if ( pDecl ) + { + pScope = pDecl->getScope(); + if ( pScope ) + pDecl = pScope->lookupByName(scopedName); + else + pDecl = NULL; + + // Special case for scope which is an interface. We + // have to look in the inherited interfaces as well. + if ( !pDecl ) + { + if (m_nodeType == NT_interface) + pDecl = lookupInInherited(scopedName); + } + } + } + + if ( bFindFirstScope && (firstScope != scopedName) ) + { + sal_Int32 i = 0; + sal_Int32 nOffset = 2; + do + { + pScope = declAsScope(pDecl); + if( pScope ) + { + pDecl = pScope->lookupByNameLocal(scopedName.getToken(nOffset, ':', i )); + nOffset = 1; + } + if( !pDecl ) + break; + } while( i != -1 ); + + if ( !pDecl ) + { + // last try if is not the global scope and the scopeName isn't specify global too + pDecl = scopeAsDecl(this); + if ( pDecl && (pDecl->getLocalName() != "") ) + { + pScope = pDecl->getScope(); + if ( pScope ) + pDecl = pScope->lookupByName(scopedName); + } else + { + pDecl = NULL; + } + } + + } + + return pDecl; +} + +AstDeclaration* AstScope::lookupByNameLocal(const OString& name) const +{ + DeclList::const_iterator iter(m_declarations.begin()); + DeclList::const_iterator end(m_declarations.end()); + AstDeclaration* pDecl = NULL; + + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getLocalName() == name ) + return pDecl; + ++iter; + } + return NULL; +} + +AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const +{ + AstInterface* pInterface = (AstInterface*)this; + + if ( !pInterface ) + return NULL; + + // Can't look in an interface which was not yet defined + if ( !pInterface->getScope() ) + { + idlc()->error()->forwardLookupError(pInterface, scopedName); + } + + // OK, loop through inherited interfaces. Stop when you find it + AstInterface::InheritedInterfaces::const_iterator iter( + pInterface->getAllInheritedInterfaces().begin()); + AstInterface::InheritedInterfaces::const_iterator end( + pInterface->getAllInheritedInterfaces().end()); + while ( iter != end ) + { + AstInterface const * resolved = iter->getResolved(); + AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName); + if ( pDecl ) + return pDecl; + pDecl = resolved->lookupInInherited(scopedName); + if ( pDecl ) + return pDecl; + ++iter; + } + // Not found + return NULL; +} + +AstDeclaration* AstScope::lookupPrimitiveType(ExprType type) +{ + AstDeclaration* pDecl = NULL; + AstScope* pScope = NULL; + AstBaseType* pBaseType = NULL; + OString typeName; + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return NULL; + pScope = pDecl->getScope(); + if ( pScope) + return pScope->lookupPrimitiveType(type); + + switch (type) + { + case ET_none: + OSL_ASSERT(false); + break; + case ET_short: + typeName = OString("short"); + break; + case ET_ushort: + typeName = OString("unsigned short"); + break; + case ET_long: + typeName = OString("long"); + break; + case ET_ulong: + typeName = OString("unsigned long"); + break; + case ET_hyper: + typeName = OString("hyper"); + break; + case ET_uhyper: + typeName = OString("unsigned hyper"); + break; + case ET_float: + typeName = OString("float"); + break; + case ET_double: + typeName = OString("double"); + break; + case ET_char: + typeName = OString("char"); + break; + case ET_byte: + typeName = OString("byte"); + break; + case ET_boolean: + typeName = OString("boolean"); + break; + case ET_any: + typeName = OString("any"); + break; + case ET_void: + typeName = OString("void"); + break; + case ET_type: + typeName = OString("type"); + break; + case ET_string: + typeName = OString("string"); + break; + } + + pDecl = lookupByNameLocal(typeName); + + if ( pDecl && (pDecl->getNodeType() == NT_predefined) ) + { + pBaseType = (AstBaseType*)pDecl; + + if ( pBaseType->getExprType() == type ) + return pDecl; + } + + return NULL; +} + +AstDeclaration* AstScope::lookupForAdd(AstDeclaration* pDecl) +{ + if ( !pDecl ) + return NULL; + + AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName()); + + return pRetDecl; +} diff --git a/idlc/source/astservice.cxx b/idlc/source/astservice.cxx new file mode 100644 index 000000000000..11f638cc0f66 --- /dev/null +++ b/idlc/source/astservice.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" + +#include "sal/config.h" + +#include "idlc/astmember.hxx" +#include "idlc/astoperation.hxx" +#include "idlc/astservice.hxx" +#include "idlc/asttype.hxx" + +bool AstService::checkLastConstructor() const { + AstOperation const * last = static_cast< AstOperation const * >(getLast()); + for (DeclList::const_iterator i(getIteratorBegin()); i != getIteratorEnd(); + ++i) + { + if (*i != last && (*i)->getNodeType() == NT_operation) { + AstOperation const * ctor = static_cast< AstOperation * >(*i); + if (ctor->isVariadic() && last->isVariadic()) { + return true; + } + sal_uInt32 n = ctor->nMembers(); + if (n == last->nMembers()) { + for (DeclList::const_iterator i1(ctor->getIteratorBegin()), + i2(last->getIteratorBegin()); + i1 != ctor->getIteratorEnd(); ++i1, ++i2) + { + sal_Int32 r1; + AstDeclaration const * t1 = deconstructAndResolveTypedefs( + static_cast< AstMember * >(*i1)->getType(), &r1); + sal_Int32 r2; + AstDeclaration const * t2 = deconstructAndResolveTypedefs( + static_cast< AstMember * >(*i2)->getType(), &r2); + if (r1 != r2 || t1->getScopedName() != t2->getScopedName()) + { + return false; + } + } + return true; + } + } + } + return false; +} diff --git a/idlc/source/aststack.cxx b/idlc/source/aststack.cxx new file mode 100644 index 000000000000..9697727ac861 --- /dev/null +++ b/idlc/source/aststack.cxx @@ -0,0 +1,137 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <rtl/alloc.h> +#include <idlc/aststack.hxx> +#include <idlc/astscope.hxx> + +#define STACKSIZE_INCREMENT 64 + +AstStack::AstStack() + : m_stack((AstScope**)rtl_allocateZeroMemory(sizeof(AstScope*) * STACKSIZE_INCREMENT)) + , m_size(STACKSIZE_INCREMENT) + , m_top(0) +{ +} + +AstStack::~AstStack() +{ + for(sal_uInt32 i=0; i < m_top; i++) + { + if (m_stack[i]) + delete(m_stack[i]); + } + + rtl_freeMemory(m_stack); +} + +sal_uInt32 AstStack::depth() +{ + return m_top; +} + +AstScope* AstStack::top() +{ + if (m_top < 1) + return NULL; + return m_stack[m_top - 1]; +} + +AstScope* AstStack::bottom() +{ + if (m_top == 0) + return NULL; + return m_stack[0]; +} + +AstScope* AstStack::nextToTop() +{ + AstScope *tmp, *retval; + + if (depth() < 2) + return NULL; + + tmp = top(); // Save top + (void) pop(); // Pop it + retval = top(); // Get next one down + (void) push(tmp); // Push top back + return retval; // Return next one down +} + +AstScope* AstStack::topNonNull() +{ + for (sal_uInt32 i = m_top; i > 0; i--) + { + if ( m_stack[i - 1] ) + return m_stack[i - 1]; + } + return NULL; +} + +AstStack* AstStack::push(AstScope* pScope) +{ + AstScope **tmp; +// AstDeclaration *pDecl = ScopeAsDecl(pScope); + sal_uInt32 newSize; + sal_uInt32 i; + + // Make sure there's space for one more + if (m_size == m_top) + { + newSize = m_size; + newSize += STACKSIZE_INCREMENT; + tmp = (AstScope**)rtl_allocateZeroMemory(sizeof(AstScope*) * newSize); + + for(i=0; i < m_size; i++) + tmp[i] = m_stack[i]; + + rtl_freeMemory(m_stack); + m_stack = tmp; + } + + // Insert new scope + m_stack[m_top++] = pScope; + + return this; +} + +void AstStack::pop() +{ + AstScope *pScope; + + if (m_top < 1) + return; + pScope = m_stack[--m_top]; +} + +void AstStack::clear() +{ + m_top = 0; +} + diff --git a/idlc/source/aststruct.cxx b/idlc/source/aststruct.cxx new file mode 100644 index 000000000000..913ebaed42c4 --- /dev/null +++ b/idlc/source/aststruct.cxx @@ -0,0 +1,191 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/aststruct.hxx> +#ifndef _IDLC_ASTMember_HXX_ +#include <idlc/astmember.hxx> +#endif + +#include "registry/version.h" +#include "registry/writer.hxx" + +using namespace ::rtl; + +AstStruct::AstStruct( + const OString& name, std::vector< rtl::OString > const & typeParameters, + AstStruct* pBaseType, AstScope* pScope) + : AstType(NT_struct, name, pScope) + , AstScope(NT_struct) + , m_pBaseType(pBaseType) +{ + for (std::vector< rtl::OString >::const_iterator i(typeParameters.begin()); + i != typeParameters.end(); ++i) + { + m_typeParameters.push_back( + new AstDeclaration(NT_type_parameter, *i, 0)); + } +} + +AstStruct::AstStruct(const NodeType type, + const OString& name, + AstStruct* pBaseType, + AstScope* pScope) + : AstType(type, name, pScope) + , AstScope(type) + , m_pBaseType(pBaseType) +{ +} + +AstStruct::~AstStruct() +{ + for (DeclList::iterator i(m_typeParameters.begin()); + i != m_typeParameters.end(); ++i) + { + delete *i; + } +} + +AstDeclaration const * AstStruct::findTypeParameter(rtl::OString const & name) + const +{ + for (DeclList::const_iterator i(m_typeParameters.begin()); + i != m_typeParameters.end(); ++i) + { + if ((*i)->getLocalName() == name) { + return *i; + } + } + return 0; +} + +bool AstStruct::isType() const { + return getNodeType() == NT_struct + ? getTypeParameterCount() == 0 : AstDeclaration::isType(); +} + +sal_Bool AstStruct::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + if (m_typeParameters.size() > SAL_MAX_UINT16) { + fprintf( + stderr, + ("%s: polymorphic struct type template %s has too many type" + " parameters\n"), + idlc()->getOptions()->getProgramName().getStr(), + getScopedName().getStr()); + return false; + } + + sal_uInt16 nMember = getNodeCount(NT_member); + + RTTypeClass typeClass = RT_TYPE_STRUCT; + if ( getNodeType() == NT_exception ) + typeClass = RT_TYPE_EXCEPTION; + + OUString emptyStr; + typereg::Writer aBlob( + (m_typeParameters.empty() && !m_bPublished + ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1), + getDocumentation(), emptyStr, typeClass, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + m_pBaseType == 0 ? 0 : 1, nMember, 0, + static_cast< sal_uInt16 >(m_typeParameters.size())); + if (m_pBaseType != 0) { + aBlob.setSuperTypeName( + 0, + OStringToOUString( + m_pBaseType->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + + if ( nMember > 0 ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + AstMember* pMember = NULL; + OUString docu; + sal_uInt16 index = 0; + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_member ) + { + pMember = (AstMember*)pDecl; + RTFieldAccess flags = RT_ACCESS_READWRITE; + rtl::OString typeName; + if (pMember->getType()->getNodeType() == NT_type_parameter) { + flags |= RT_ACCESS_PARAMETERIZED_TYPE; + typeName = pMember->getType()->getLocalName(); + } else { + typeName = pMember->getType()->getRelativName(); + } + aBlob.setFieldData( + index++, pMember->getDocumentation(), emptyStr, flags, + OStringToOUString( + pMember->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString(typeName, RTL_TEXTENCODING_UTF8), + RTConstValue()); + } + ++iter; + } + } + + sal_uInt16 index = 0; + for (DeclList::iterator i(m_typeParameters.begin()); + i != m_typeParameters.end(); ++i) + { + aBlob.setReferenceData( + index++, emptyStr, RT_REF_TYPE_PARAMETER, RT_ACCESS_INVALID, + OStringToOUString( + (*i)->getLocalName(), RTL_TEXTENCODING_UTF8)); + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(emptyStr, RG_VALUETYPE_BINARY, + (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + return sal_True; +} + diff --git a/idlc/source/aststructinstance.cxx b/idlc/source/aststructinstance.cxx new file mode 100644 index 000000000000..457c48ad00a7 --- /dev/null +++ b/idlc/source/aststructinstance.cxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" + +#include "idlc/aststructinstance.hxx" + +#include "idlc/asttype.hxx" +#include "idlc/idlctypes.hxx" + +#include "rtl/strbuf.hxx" +#include "rtl/string.hxx" + +namespace { + +rtl::OString createName( + AstType const * typeTemplate, DeclList const * typeArguments) +{ + rtl::OStringBuffer buf(typeTemplate->getScopedName()); + if (typeArguments != 0) { + buf.append('<'); + for (DeclList::const_iterator i(typeArguments->begin()); + i != typeArguments->end(); ++i) + { + if (i != typeArguments->begin()) { + buf.append(','); + } + if (*i != 0) { + buf.append((*i)->getScopedName()); + } + } + buf.append('>'); + } + return buf.makeStringAndClear(); +} + +} + +AstStructInstance::AstStructInstance( + AstType const * typeTemplate, DeclList const * typeArguments, + AstScope * scope): + AstType( + NT_instantiated_struct, createName(typeTemplate, typeArguments), scope), + m_typeTemplate(typeTemplate), m_typeArguments(*typeArguments) +{} diff --git a/idlc/source/astunion.cxx b/idlc/source/astunion.cxx new file mode 100644 index 000000000000..f4b1ede57bd4 --- /dev/null +++ b/idlc/source/astunion.cxx @@ -0,0 +1,401 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/astunion.hxx> +#include <idlc/astbasetype.hxx> +#include <idlc/errorhandler.hxx> + +#include "registry/version.h" +#include "registry/writer.hxx" + +using namespace ::rtl; + +AstUnion::AstUnion(const ::rtl::OString& name, AstType* pDiscType, AstScope* pScope) + : AstStruct(NT_union, name, NULL, pScope) + , m_pDiscriminantType(pDiscType) + , m_discExprType(ET_long) +{ + AstBaseType* pBaseType; + + if ( !pDiscType ) + { + m_pDiscriminantType = NULL; + m_discExprType = ET_none; + return; + } + /* + * If the discriminator type is a predefined type + * then install the equivalent coercion target type in + * the pd_udisc_type field. + */ + if ( pDiscType->getNodeType() == NT_predefined ) + { + pBaseType = (AstBaseType*)pDiscType; + if ( !pBaseType ) + { + m_pDiscriminantType = NULL; + m_discExprType = ET_none; + return; + } + m_pDiscriminantType = pDiscType; + switch (pBaseType->getExprType()) + { + case ET_long: + case ET_ulong: + case ET_short: + case ET_ushort: + case ET_char: + case ET_boolean: + m_discExprType = pBaseType->getExprType(); + break; + default: + m_discExprType = ET_none; + m_pDiscriminantType = NULL; + break; + } + } else + if (pDiscType->getNodeType() == NT_enum) + { + m_discExprType = ET_any; + m_pDiscriminantType = pDiscType; + } else + { + m_discExprType = ET_none; + m_pDiscriminantType = NULL; + } + + if ( !m_pDiscriminantType ) + idlc()->error()->error2(EIDL_DISC_TYPE, this, pDiscType); +} + +AstUnion::~AstUnion() +{ +} + +AstDeclaration* AstUnion::addDeclaration(AstDeclaration* pDecl) +{ + if ( pDecl->getNodeType() == NT_union_branch ) + { + AstUnionBranch* pBranch = (AstUnionBranch*)pDecl; + if ( lookupBranch(pBranch) ) + { + idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pDecl); + return NULL; + } + } + + return AstScope::addDeclaration(pDecl); +} + +AstUnionBranch* AstUnion::lookupBranch(AstUnionBranch* pBranch) +{ + AstUnionLabel* pLabel = NULL; + + if ( pBranch ) + pLabel = pBranch->getLabel(); + + if ( pLabel ) + { + if (pLabel->getLabelKind() == UL_default) + return lookupDefault(); + if (m_discExprType == ET_any) + /* CONVENTION: indicates enum discr */ + return lookupEnum(pBranch); + return lookupLabel(pBranch); + } + return NULL; +} + +AstUnionBranch* AstUnion::lookupDefault(sal_Bool bReportError) +{ + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstUnionBranch *pBranch = NULL; + AstDeclaration *pDecl = NULL; + + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_union_branch ) + { + pBranch = (AstUnionBranch*)pDecl; + if (pBranch == NULL) + { + ++iter; + continue; + } + if ( pBranch->getLabel() != NULL && + pBranch->getLabel()->getLabelKind() == UL_default) + { + if ( bReportError ) + idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); + return pBranch; + } + } + ++iter; + } + return NULL; +} + +AstUnionBranch* AstUnion::lookupLabel(AstUnionBranch* pBranch) +{ + AstUnionLabel* pLabel = pBranch->getLabel(); + + if ( !pLabel->getLabelValue() ) + return pBranch; +// pLabel->getLabelValue()->setExprValue(pLabel->getLabelValue()->coerce(m_discExprType, sal_False)); + AstExprValue* pLabelValue = pLabel->getLabelValue()->coerce( + m_discExprType, sal_False); + if ( !pLabelValue ) + { + idlc()->error()->evalError(pLabel->getLabelValue()); + return pBranch; + } else + { + pLabel->getLabelValue()->setExprValue(pLabelValue); + } + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstUnionBranch* pB = NULL; + AstDeclaration* pDecl = NULL; + + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_union_branch ) + { + pB = (AstUnionBranch*)pDecl; + if ( !pB ) + { + ++iter; + continue; + } + if ( pB->getLabel() != NULL && + pB->getLabel()->getLabelKind() == UL_label && + pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) ) + { + idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); + return pBranch; + } + } + ++iter; + } + return NULL; +} + +AstUnionBranch* AstUnion::lookupEnum(AstUnionBranch* pBranch) +{ + AstDeclaration const * pType = resolveTypedefs(m_pDiscriminantType); + if ( pType->getNodeType() != NT_enum ) + return NULL; + + AstUnionLabel* pLabel = pBranch->getLabel(); + AstExpression* pExpr = pLabel->getLabelValue(); + if ( !pExpr ) + return pBranch; + + /* + * Expecting a symbol label + */ + if ( pExpr->getCombOperator() != EC_symbol) + { + idlc()->error()->enumValExpected(this); + return pBranch; + } + + /* + * See if the symbol defines a constant in the discriminator enum + */ + AstEnum* pEnum = (AstEnum*)pType; + AstDeclaration* pDecl = pEnum->lookupByName(*pExpr->getSymbolicName()); + if ( pDecl == NULL || pDecl->getScope() != pEnum) + { + idlc()->error()->enumValLookupFailure(this, pEnum, *pExpr->getSymbolicName()); + return pBranch; + } + + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstUnionBranch* pB = NULL; + pDecl = NULL; + + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_union_branch ) + { + pB = (AstUnionBranch*)pDecl; + if ( !pB ) + { + ++iter; + continue; + } + if ( pB->getLabel() != NULL && + pB->getLabel()->getLabelKind() == UL_label && + pB->getLabel()->getLabelValue()->compare(pLabel->getLabelValue()) ) + { + idlc()->error()->error2(EIDL_MULTIPLE_BRANCH, this, pBranch); + return pBranch; + } + } + ++iter; + } + return NULL; +} + +sal_Bool AstUnion::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey)) + { + fprintf(stderr, "%s: warning, could not create key '%s' in '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(rKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + sal_uInt16 nMember = getNodeCount(NT_union_branch); + + OUString emptyStr; + typereg::Writer aBlob( + TYPEREG_VERSION_0, getDocumentation(), emptyStr, RT_TYPE_UNION, + false, OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 1, + nMember, 0, 0); + aBlob.setSuperTypeName( + 0, + OStringToOUString( + getDiscrimantType()->getScopedName(), RTL_TEXTENCODING_UTF8)); + + if ( nMember > 0 ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstDeclaration* pDecl = NULL; + AstUnionBranch* pBranch = NULL; + AstUnionBranch* pDefault = lookupDefault(sal_False); + AstUnionLabel* pLabel = NULL; + AstExprValue* pExprValue = NULL; + RTConstValue aConst; + RTFieldAccess access = RT_ACCESS_READWRITE; + OUString docu; + sal_uInt16 index = 0; + if ( pDefault ) + index = 1; + + sal_Int64 disc = 0; + while ( iter != end ) + { + pDecl = *iter; + if ( pDecl->getNodeType() == NT_union_branch ) + { + pBranch = (AstUnionBranch*)pDecl; + if (pBranch == pDefault) + { + ++iter; + continue; + } + + pLabel = pBranch->getLabel(); + pExprValue = pLabel->getLabelValue()->coerce(ET_hyper, sal_False); + aConst.m_type = RT_TYPE_INT64; + aConst.m_value.aHyper = pExprValue->u.hval; + if ( aConst.m_value.aHyper > disc ) + disc = aConst.m_value.aHyper; + + aBlob.setFieldData( + index++, pBranch->getDocumentation(), emptyStr, RT_ACCESS_READWRITE, + OStringToOUString( + pBranch->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString( + pBranch->getType()->getRelativName(), + RTL_TEXTENCODING_UTF8), + aConst); + } + ++iter; + } + + if ( pDefault ) + { + access = RT_ACCESS_DEFAULT; + aConst.m_type = RT_TYPE_INT64; + aConst.m_value.aHyper = disc + 1; + aBlob.setFieldData( + 0, pDefault->getDocumentation(), emptyStr, RT_ACCESS_DEFAULT, + OStringToOUString( + pDefault->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString( + pDefault->getType()->getRelativName(), + RTL_TEXTENCODING_UTF8), + aConst); + } + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue(OUString(), RG_VALUETYPE_BINARY, + (RegValue)pBlob, aBlobSize)) + { + fprintf(stderr, "%s: warning, could not set value of key \"%s\" in %s\n", + idlc()->getOptions()->getProgramName().getStr(), + getFullName().getStr(), OUStringToOString(localKey.getRegistryName(), RTL_TEXTENCODING_UTF8).getStr()); + return sal_False; + } + + return sal_True; +} + +AstUnionBranch::AstUnionBranch(AstUnionLabel* pLabel, AstType const * pType, const ::rtl::OString& name, AstScope* pScope) + : AstMember(NT_union_branch, pType, name, pScope) + , m_pLabel(pLabel) +{ +} + +AstUnionBranch::~AstUnionBranch() +{ + if ( m_pLabel ) + delete m_pLabel; +} + +AstUnionLabel::AstUnionLabel(UnionLabel labelKind, AstExpression* pExpr) + : m_label(labelKind) + , m_pLabelValue(pExpr) +{ + if ( m_pLabelValue ) + m_pLabelValue->evaluate(EK_const); +} + +AstUnionLabel::~AstUnionLabel() +{ + if ( m_pLabelValue ) + delete m_pLabelValue; +} + diff --git a/idlc/source/attributeexceptions.hxx b/idlc/source/attributeexceptions.hxx new file mode 100644 index 000000000000..2981c09220f6 --- /dev/null +++ b/idlc/source/attributeexceptions.hxx @@ -0,0 +1,42 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef INCLUDED_idlc_source_attributeexceptions_hxx +#define INCLUDED_idlc_source_attributeexceptions_hxx + +#include "rtl/ustring.hxx" + +struct AttributeExceptions { + struct Part { + rtl::OUString const * documentation; + DeclList const * exceptions; + }; + Part get; + Part set; +}; + +#endif diff --git a/idlc/source/errorhandler.cxx b/idlc/source/errorhandler.cxx new file mode 100644 index 000000000000..4ab4844eeca7 --- /dev/null +++ b/idlc/source/errorhandler.cxx @@ -0,0 +1,695 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/errorhandler.hxx> +#include <idlc/astinterface.hxx> + +using namespace ::rtl; + +static const sal_Char* errorCodeToMessage(ErrorCode eCode) +{ + switch (eCode) + { + case EIDL_NONE: + return "all is fine "; + case EIDL_SYNTAX_ERROR: + return ""; + case EIDL_REDEF: + return "illegal redefinition "; + case EIDL_REDEF_SCOPE: + return "illegal redefinition in scope "; + case EIDL_DEF_USE: + return "redefinition after use, "; + case EIDL_MULTIPLE_BRANCH: + return "union with duplicate branch label "; + case EIDL_COERCION_FAILURE: + return "coercion failure "; + case EIDL_SCOPE_CONFLICT: + return "definition scope is different than fwd declare scope, "; + case EIDL_ONEWAY_CONFLICT: + return "oneway operation with OUT|INOUT parameters or raises exceptions, "; + case EIDL_DISC_TYPE: + return "union with illegal discriminator type, "; + case EIDL_LABEL_TYPE: + return "label type incompatible with union discriminator type, "; + case EIDL_ILLEGAL_ADD: + return "illegal add operation, "; + case EIDL_ILLEGAL_USE: + return "illegal type used in expression, "; + case EIDL_ILLEGAL_RAISES: + return "non-exception type in raises(..) clause, "; + case EIDL_CANT_INHERIT: + return "cannot inherit "; + case EIDL_LOOKUP_ERROR: + return "error in lookup of symbol: "; + case EIDL_INHERIT_FWD_ERROR: + return ""; + case EIDL_CONSTANT_EXPECTED: + return "constant expected: "; + case EIDL_NAME_CASE_ERROR: + return "identifier used with two differing spellings: "; + case EIDL_ENUM_VAL_EXPECTED: + return "enumerator expected: "; + case EIDL_ENUM_VAL_NOT_FOUND: + return "enumerator by this name not defined: "; + case EIDL_EVAL_ERROR: + return "expression evaluation error: "; + case EIDL_AMBIGUOUS: + return "ambiguous definition: "; + case EIDL_DECL_NOT_DEFINED: + return "forward declared but never defined: "; + case EIDL_FWD_DECL_LOOKUP: + return ""; + case EIDL_RECURSIVE_TYPE: + return "illegal recursive use of type: "; + case EIDL_NONVOID_ONEWAY: + return "non-void return type in oneway operation: "; + case EIDL_NOT_A_TYPE: + return "specified symbol is not a type: "; + case EIDL_TYPE_NOT_VALID: + return "specified type is not valid in this context: "; + case EIDL_INTERFACEMEMBER_LOOKUP: + return "error in lookup of symbol, expected interface is not defined and no forward exists: "; + case EIDL_SERVICEMEMBER_LOOKUP: + return "error in lookup of symbol, expected service is not defined: "; + case EIDL_TYPE_IDENT_CONFLICT: + return "type and parameter/member name are equal: "; + case EIDL_ONEWAY_RAISE_CONFLICT: + return "oneway operation cannot raises exceptions: "; + case EIDL_WRONGATTRIBUTEFLAG: + return "the used flag is not valid in this context: "; + case EIDL_DEFINED_ATTRIBUTEFLAG: + return "flag is already set: "; + case EIDL_WRONGATTRIBUTEKEYWORD: + return "keyword not allowed: "; + case EIDL_MISSINGATTRIBUTEKEYWORD: + return "missing keyword: "; + case EIDL_BAD_ATTRIBUTE_FLAGS: + return + "the 'attribute' flag is mandatory, and only the 'bound' and" + " 'readonly' optional flags are accepted: "; + case EIDL_OPTIONALEXPECTED: + return "only the 'optional' flag is accepted: "; + case EIDL_MIXED_INHERITANCE: + return "interface inheritance declarations cannot appear in both an" + " interface's header and its body"; + case EIDL_DOUBLE_INHERITANCE: + return + "interface is (directly or indirectly) inherited more than once: "; + case EIDL_DOUBLE_MEMBER: + return + "member is (directly or indirectly) declared more than once: "; + case EIDL_CONSTRUCTOR_PARAMETER_NOT_IN: + return + "a service constructor parameter may not be an out or inout" + " parameter"; + case EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST: + return + "no parameters may precede a rest parameter in a service" + " constructor"; + case EIDL_REST_PARAMETER_NOT_LAST: + return "no parameters may follow a rest parameter"; + case EIDL_REST_PARAMETER_NOT_ANY: + return "a rest parameter must be of type any"; + case EIDL_METHOD_HAS_REST_PARAMETER: + return "a rest parameter may not be used on an interface method"; + case EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS: + return "a readonly attribute may not have a setter raises clause"; + case EIDL_UNSIGNED_TYPE_ARGUMENT: + return "an unsigned type cannot be used as a type argument"; + case EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS: + return + "the number of given type arguments does not match the expected" + " number of type parameters"; + case EIDL_INSTANTIATED_STRUCT_TYPE_TYPEDEF: + return + "an instantiated polymorphic struct type cannot be used in a" + " typedef"; + case EIDL_IDENTICAL_TYPE_PARAMETERS: + return "two type parameters have the same name"; + case EIDL_STRUCT_TYPE_TEMPLATE_WITH_BASE: + return "a polymorphic struct type template may not have a base type"; + case EIDL_PUBLISHED_FORWARD: + return + "a published forward declaration of an interface type cannot be" + " followed by an unpublished declaration of that type"; + case EIDL_PUBLISHED_USES_UNPUBLISHED: + return + "an unpublished entity cannot be used in the declaration of a" + " published entity: "; + case EIDL_SIMILAR_CONSTRUCTORS: + return "two constructors have identical lists of parameter types"; + } + return "unknown errror"; +} + +static const sal_Char* warningCodeToMessage(WarningCode wCode) +{ + switch (wCode) + { + case WIDL_EXPID_CONFLICT: + return "exception id conflict: "; + case WIDL_REQID_CONFLICT: + return "request id conflict: "; + case WIDL_INHERIT_IDCONFLICT: + return "request id conflict in inheritance tree: "; + case WIDL_TYPE_IDENT_CONFLICT: + return "type and parameter|member name are equal: "; + case WIDL_WRONG_NAMING_CONV: + return "type or identifier doesn't fulfill the UNO naming convention: "; + } + return "unkown warning"; +} + +static const sal_Char* parseStateToMessage(ParseState state) +{ + switch (state) + { + case PS_NoState: + return "Statement can not be parsed"; + case PS_TypeDeclSeen: + return "Malformed type declaration"; + case PS_ConstantDeclSeen: + return "Malformed const declaration"; + case PS_ExceptionDeclSeen: + return "Malformed exception declaration"; + case PS_InterfaceDeclSeen: + return "Malformed interface declaration"; + case PS_ServiceDeclSeen: + return "Malformed servicve declaration"; + case PS_ModuleDeclSeen: + return "Malformed module declaration"; + case PS_AttributeDeclSeen: + return "Malformed attribute declaration"; + case PS_PropertyDeclSeen: + return "Malformed property declaration"; + case PS_OperationDeclSeen: + return "Malformed operation declaration"; + case PS_InterfaceInheritanceDeclSeen: + return "Malformed interface inheritance declaration"; + case PS_ConstantsDeclSeen: + return "Malformed constants declaration"; + case PS_ServiceSeen: + return "Missing service identifier following SERVICE keyword"; + case PS_ServiceIDSeen: + return "Missing '{' or illegal syntax following service identifier"; + case PS_ServiceSqSeen: + return "Illegal syntax following service '{' opener"; + case PS_ServiceBodySeen: + return "Illegal syntax following service '}' closer"; + case PS_ServiceMemberSeen: + return "Illegal syntax following service member declaration"; + case PS_ServiceIFHeadSeen: + return "Illegal syntax following header of an interface member"; + case PS_ServiceSHeadSeen: + return "Illegal syntax following header of an service member"; + case PS_ModuleSeen: + return "Missing module identifier following MODULE keyword"; + case PS_ModuleIDSeen: + return "Missing '{' or illegal syntax following module identifier"; + case PS_ModuleSqSeen: + return "Illegal syntax following module '{' opener"; + case PS_ModuleQsSeen: + return "Illegal syntax following module '}' closer"; + case PS_ModuleBodySeen: + return "Illegal syntax following module export(s)"; + case PS_ConstantsSeen: + return "Missing constants identifier following CONSTANTS keyword"; + case PS_ConstantsIDSeen: + return "Missing '{' or illegal syntax following constants identifier"; + case PS_ConstantsSqSeen: + return "Illegal syntax following module '{' opener"; + case PS_ConstantsQsSeen: + return "Illegal syntax following module '}' closer"; + case PS_ConstantsBodySeen: + return "Illegal syntax following constants export(s)"; + case PS_InterfaceSeen: + return "Missing interface identifier following INTERFACE keyword"; + case PS_InterfaceIDSeen: + return "Illegal syntax following interface identifier"; + case PS_InterfaceHeadSeen: + return "Illegal syntax following interface head"; + case PS_InheritSpecSeen: + return "Missing '{' or illegal syntax following inheritance spec"; + case PS_ForwardDeclSeen: + return "Missing ';' following forward interface declaration"; + case PS_InterfaceSqSeen: + return "Illegal syntax following interface '{' opener"; + case PS_InterfaceQsSeen: + return "Illegal syntax following interface '}' closer"; + case PS_InterfaceBodySeen: + return "Illegal syntax following interface export(s)"; + case PS_InheritColonSeen: + return "Illegal syntax following ':' starting inheritance list"; + case PS_SNListCommaSeen: + return "Found illegal scoped name in scoped name list"; + case PS_ScopedNameSeen: + return "Missing ',' following scoped name in scoped name list"; + case PS_SN_IDSeen: + return "Illegal component in scoped name"; + case PS_ScopeDelimSeen: + return "Illegal component in scoped name following '::'"; + case PS_ConstSeen: + return "Missing type or illegal syntax following CONST keyword"; + case PS_ConstTypeSeen: + return "Missing identifier or illegal syntax following const type"; + case PS_ConstIDSeen: + return "Missing '=' or illegal syntax after const identifier"; + case PS_ConstAssignSeen: + return "Missing value expr or illegal syntax following '='"; + case PS_ConstExprSeen: + return "Missing ';' or illegal syntax following value expr in const"; + case PS_TypedefSeen: + return "Missing type or illegal syntax following TYPEDEF keyword"; + case PS_TypeSpecSeen: + return "Missing declarators or illegal syntax following type spec"; + case PS_DeclaratorsSeen: + return "Illegal syntax following declarators in TYPEDEF declaration"; + case PS_StructSeen: + return "Missing struct identifier following STRUCT keyword"; + case PS_StructHeaderSeen: + return "Missing '{' or illegal syntax following struct inheritance spec"; + case PS_StructIDSeen: + return "Missing '{' or illegal syntax following struct identifier"; + case PS_StructSqSeen: + return "Illegal syntax following struct '{' opener"; + case PS_StructQsSeen: + return "Illegal syntax following struct '}' closer"; + case PS_StructBodySeen: + return "Illegal syntax following struct member(s)"; + case PS_MemberTypeSeen: + return "Illegal syntax or missing identifier following member type"; + case PS_MemberDeclsSeen: + return "Illegal syntax following member declarator(s)"; + case PS_MemberDeclsCompleted: + return "Missing ',' between member decls of same type(?)"; + case PS_UnionSeen: + return "Missing identifier following UNION keyword"; + case PS_UnionIDSeen: + return "Illegal syntax following union identifier"; + case PS_SwitchSeen: + return "Illegal syntax following SWITCH keyword"; + case PS_SwitchOpenParSeen: + return "Illegal syntax following '(' in switch in union"; + case PS_SwitchTypeSeen: + return "Illegal syntax following type decl in switch in union"; + case PS_SwitchCloseParSeen: + return "Missing union '{' opener"; + case PS_UnionSqSeen: + return "Illegal syntax following union '{' opener"; + case PS_UnionQsSeen: + return "Illegal syntax following union '}' closer"; + case PS_DefaultSeen: + return "Illegal syntax or missing ':' following DEFAULT keyword"; + case PS_UnionLabelSeen: + return "Illegal syntax following branch label in union"; + case PS_LabelColonSeen: + return "Illegal syntax following ':' in branch label in union"; + case PS_LabelExprSeen: + return "Illegal syntax following label expression in union"; + case PS_UnionElemSeen: + case PS_UnionElemCompleted: + return "Illegal syntax following union element"; + case PS_CaseSeen: + return "Illegal syntax following CASE keyword in union"; + case PS_UnionElemTypeSeen: + return "Illegal syntax following type decl in union element"; + case PS_UnionElemDeclSeen: + return "Illegal syntax following declarator in union element"; + case PS_UnionBodySeen: + return "Illegal syntax following union body statement(s)"; + case PS_EnumSeen: + return "Illegal syntax or missing identifier following ENUM keyword"; + case PS_EnumIDSeen: + return "Illegal syntax or missing '{' following enum identifier"; + case PS_EnumSqSeen: + return "Illegal syntax following enum '{' opener"; + case PS_EnumQsSeen: + return "Illegal syntax following enum '}' closer"; + case PS_EnumBodySeen: + return "Illegal syntax following enum enumerator(s)"; + case PS_EnumCommaSeen: + return "Illegal syntax or missing identifier following ',' in enum"; + case PS_SequenceSeen: + return "Illegal syntax or missing '<' following SEQUENCE keyword"; + case PS_SequenceSqSeen: + return "Illegal syntax or missing type following '<' in sequence"; + case PS_SequenceQsSeen: + return "Illegal syntax following '>' in sequence"; + case PS_SequenceTypeSeen: + return "Illegal syntax following sequence type declaration"; + case PS_ArrayIDSeen: + return "Illegal syntax or missing dimensions after array identifier"; + case PS_ArrayCompleted: + return "Illegal syntax after array declaration"; + case PS_DimSqSeen: + return "Illegal syntax or missing size expr after '[' in array declaration"; + case PS_DimQsSeen: + return "Illegal syntax after ']' in array declaration"; + case PS_DimExprSeen: + return "Illegal syntax or missing ']' after size expr in array declaration"; + case PS_FlagHeaderSeen: + return "Illegal syntax after flags"; + case PS_AttrSeen: + return "Illegal syntax after ATTRIBUTE keyword"; + case PS_AttrTypeSeen: + return "Illegal syntax after type in attribute declaration"; + case PS_AttrCompleted: + return "Illegal syntax after attribute declaration"; + case PS_ReadOnlySeen: + return "Illegal syntax after READONLY keyword"; + case PS_OptionalSeen: + return "Illegal syntax after OPTIONAL keyword"; + case PS_MayBeVoidSeen: + return "Illegal syntax after MAYBEVOID keyword"; + case PS_BoundSeen: + return "Illegal syntax after BOUND keyword"; + case PS_ConstrainedSeen: + return "Illegal syntax after CONSTRAINED keyword"; + case PS_TransientSeen: + return "Illegal syntax after TRANSIENT keyword"; + case PS_MayBeAmbigiousSeen: + return "Illegal syntax after MAYBEAMBIGIOUS keyword"; + case PS_MayBeDefaultSeen: + return "Illegal syntax after MAYBEDEFAULT keyword"; + case PS_RemoveableSeen: + return "Illegal syntax after REMOVEABLE keyword"; + case PS_PropertySeen: + return "Illegal syntax after PROPERTY keyword"; + case PS_PropertyTypeSeen: + return "Illegal syntax after type in property declaration"; + case PS_PropertyCompleted: + return "Illegal syntax after property declaration"; + case PS_ExceptSeen: + return "Illegal syntax or missing identifier after EXCEPTION keyword"; + case PS_ExceptHeaderSeen: + return "Missing '{' or illegal syntax following exception inheritance spec"; + case PS_ExceptIDSeen: + return "Illegal syntax or missing '{' after exception identifier"; + case PS_ExceptSqSeen: + return "Illegal syntax after exception '{' opener"; + case PS_ExceptQsSeen: + return "Illegal syntax after exception '}' closer"; + case PS_ExceptBodySeen: + return "Illegal syntax after exception member(s)"; + case PS_OpHeadSeen: + return "Illegasl syntax after operation header"; + case PS_OpTypeSeen: + return "Illegal syntax or missing identifier after operation type"; + case PS_OpIDSeen: + return "Illegal syntax or missing '(' after operation identifier"; + case PS_OpParsCompleted: + return "Illegal syntax after operation parameter list"; + case PS_OpCompleted: + return "Illegal syntax after operation declaration"; + case PS_OpSqSeen: + return "Illegal syntax after operation parameter list '(' opener"; + case PS_OpQsSeen: + return "Illegal syntax after operation parameter list ')' closer"; + case PS_OpParCommaSeen: + return "Illegal syntax or missing direction in parameter declaration"; + case PS_OpParDirSeen: + return "Illegal syntax or missing type in parameter declaration"; + case PS_OpParTypeSeen: + return "Illegal syntax or missing declarator in parameter declaration"; + case PS_OpParDeclSeen: + return "Illegal syntax following parameter declarator"; + case PS_OpOnewaySeen: + return "Illegal syntax after ONEWAY keyword"; + case PS_RaiseSeen: + return "Illegal syntax or missing '(' after RAISES keyword"; + case PS_RaiseSqSeen: + return "Illegal syntax after RAISES '(' opener"; + case PS_RaiseQsSeen: + return "Illegal syntax after RAISES ')' closer"; + case PS_DeclsCommaSeen: + return "Illegal syntax after ',' in declarators list"; + case PS_DeclsDeclSeen: + return "Illegal syntax after declarator in declarators list"; + default: + return "no wider described syntax error"; + } +} + +static OString flagToString(sal_uInt32 flag) +{ + OString flagStr; + if ( (flag & AF_READONLY) == AF_READONLY ) + flagStr += "'readonly'"; + if ( (flag & AF_OPTIONAL) == AF_OPTIONAL ) + flagStr += "'optional'"; + if ( (flag & AF_MAYBEVOID) == AF_MAYBEVOID ) + flagStr += "'maybevoid'"; + if ( (flag & AF_BOUND) == AF_BOUND ) + flagStr += "'bound'"; + if ( (flag & AF_CONSTRAINED) == AF_CONSTRAINED ) + flagStr += "'constrained'"; + if ( (flag & AF_TRANSIENT) == AF_TRANSIENT ) + flagStr += "'transient'"; + if ( (flag & AF_MAYBEAMBIGUOUS) == AF_MAYBEAMBIGUOUS ) + flagStr += "'maybeambiguous'"; + if ( (flag & AF_MAYBEDEFAULT) == AF_MAYBEDEFAULT ) + flagStr += "'maybedefault'"; + if ( (flag & AF_REMOVEABLE) == AF_REMOVEABLE ) + flagStr += "'removeable'"; + if ( (flag & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + flagStr += "'attribute'"; + if ( (flag & AF_PROPERTY) == AF_PROPERTY ) + flagStr += "'property'"; + if ( !flagStr.getLength() ) + flagStr += "'unknown'"; + + return flagStr; +} + +static void errorHeader(ErrorCode eCode, sal_Int32 lineNumber) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s(%lu) : %s", file.getStr(), + sal::static_int_cast< unsigned long >(lineNumber), + errorCodeToMessage(eCode)); +} + +static void errorHeader(ErrorCode eCode) +{ + errorHeader(eCode, idlc()->getLineNumber()); +} + +static void warningHeader(WarningCode wCode) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s(%lu) : WARNING, %s", file.getStr(), + sal::static_int_cast< unsigned long >(idlc()->getLineNumber()), + warningCodeToMessage(wCode)); +} + +void ErrorHandler::error0(ErrorCode e) +{ + errorHeader(e); + fprintf(stderr, "\n"); + idlc()->incErrorCount(); +} + +void ErrorHandler::error1(ErrorCode e, AstDeclaration const * d) +{ + errorHeader(e); + fprintf(stderr, "'%s'\n", d->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::error2( + ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2) +{ + errorHeader(e); + fprintf(stderr, "'%s', '%s'\n", d1->getScopedName().getStr(), + d2->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::error3(ErrorCode e, AstDeclaration* d1, AstDeclaration* d2, AstDeclaration* d3) +{ + errorHeader(e); + fprintf(stderr, "'%s', '%s', '%s'\n", d1->getScopedName().getStr(), + d2->getScopedName().getStr(), d3->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::warning0(WarningCode w, const sal_Char* warningmsg) +{ + if ( idlc()->getOptions()->isValid("-w") || idlc()->getOptions()->isValid("-we") ) { + warningHeader(w); + fprintf(stderr, "%s\n", warningmsg); + } + + if ( idlc()->getOptions()->isValid("-we") ) + idlc()->incErrorCount(); + else + idlc()->incWarningCount(); +} + +void ErrorHandler::syntaxError(ParseState ps, sal_Int32 lineNumber, const sal_Char* errmsg) +{ + errorHeader(EIDL_SYNTAX_ERROR, lineNumber); + fprintf(stderr, "%s: %s\n", parseStateToMessage(ps), errmsg); + idlc()->incErrorCount(); +} + +void ErrorHandler::coercionError(AstExpression *pExpr, ExprType et) +{ + errorHeader(EIDL_COERCION_FAILURE); + fprintf(stderr, "'%s' to '%s'\n", pExpr->toString().getStr(), + exprTypeToString(et)); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(const ::rtl::OString& n) +{ + errorHeader(EIDL_LOOKUP_ERROR); + fprintf(stderr, "'%s'\n", n.getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(ErrorCode e, const ::rtl::OString& n, AstDeclaration* pScope) +{ + errorHeader(e); + fprintf(stderr, "'%s' in '%s'\n", n.getStr(), pScope->getFullName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::flagError(ErrorCode e, sal_uInt32 flag) +{ + errorHeader(e); + fprintf(stderr, "'%s'\n", flagToString(flag).getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::noTypeError(AstDeclaration const * pDecl) +{ + errorHeader(EIDL_NOT_A_TYPE); + fprintf(stderr, "'%s'\n", pDecl->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +namespace { + +char const * nodeTypeName(NodeType nodeType) { + switch (nodeType) { + case NT_interface: + return "interface"; + + case NT_exception: + return "exception"; + + case NT_struct: + return "struct"; + + default: + return ""; + } +} + +} + +void ErrorHandler::inheritanceError(NodeType nodeType, const OString* name, AstDeclaration* pDecl) +{ + if ( nodeType == NT_interface && + (pDecl->getNodeType() == NT_interface) && + !((AstInterface*)pDecl)->isDefined() ) + { + errorHeader(EIDL_INHERIT_FWD_ERROR); + fprintf(stderr, "interface '%s' cannot inherit from forward declared interface '%s'\n", + name->getStr(), pDecl->getScopedName().getStr()); + } else + { + errorHeader(EIDL_CANT_INHERIT); + fprintf(stderr, "%s '%s' from '%s'\n", + nodeTypeName(nodeType), name->getStr(), + pDecl->getScopedName().getStr()); + } + idlc()->incErrorCount(); +} + +void ErrorHandler::forwardLookupError(AstDeclaration* pForward, + const ::rtl::OString& name) +{ + errorHeader(EIDL_FWD_DECL_LOOKUP); + fprintf(stderr, "trying to look up '%s' in undefined forward declared interface '%s'\n", + pForward->getScopedName().getStr(), name.getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::constantExpected(AstDeclaration* pDecl, + const ::rtl::OString& name) +{ + errorHeader(EIDL_CONSTANT_EXPECTED); + fprintf(stderr, "'%s' is bound to '%s'\n", name.getStr(), pDecl->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::evalError(AstExpression* pExpr) +{ + errorHeader(EIDL_EVAL_ERROR); + fprintf(stderr, "'%s'\n", pExpr->toString().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::enumValExpected(AstUnion* pUnion) +{ + errorHeader(EIDL_ENUM_VAL_EXPECTED); + fprintf(stderr, " union %s\n", pUnion->getLocalName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::enumValLookupFailure(AstUnion* pUnion, AstEnum* pEnum, const ::rtl::OString& name) +{ + errorHeader(EIDL_ENUM_VAL_NOT_FOUND); + fprintf(stderr, " union %s, enum %s, enumerator %s\n", + pUnion->getLocalName().getStr(), + pEnum->getLocalName().getStr(), name.getStr()); + idlc()->incErrorCount(); +} + +bool ErrorHandler::checkPublished(AstDeclaration const * decl, bool bOptional) { + if (idlc()->isPublished() && !decl->isPublished() && !bOptional) { + error1(EIDL_PUBLISHED_USES_UNPUBLISHED, decl); + return false; + } else { + return true; + } +} diff --git a/idlc/source/fehelper.cxx b/idlc/source/fehelper.cxx new file mode 100644 index 000000000000..cd96c4c2a20a --- /dev/null +++ b/idlc/source/fehelper.cxx @@ -0,0 +1,144 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/fehelper.hxx> +#include <idlc/errorhandler.hxx> +#include <idlc/astarray.hxx> +#include "idlc/idlc.hxx" + +using namespace ::rtl; + +FeDeclarator::FeDeclarator(const OString& name, DeclaratorType declType, AstDeclaration* pComplPart) + : m_pComplexPart(pComplPart) + , m_name(name) + , m_declType(declType) +{ +} + +FeDeclarator::~FeDeclarator() +{ +} + +sal_Bool FeDeclarator::checkType(AstDeclaration const * type) +{ + OString tmp(m_name); + sal_Int32 count = m_name.lastIndexOf( ':' ); + if( count != -1 ) + tmp = m_name.copy( count+1 ); + + if (tmp == type->getLocalName()) + return sal_False; + else + return sal_True; +} + +AstType const * FeDeclarator::compose(AstDeclaration const * pDecl) +{ + AstArray* pArray; + AstType* pType; + + if ( pDecl == 0 ) + { + return NULL; + } + if ( !pDecl->isType() ) + { + idlc()->error()->noTypeError(pDecl); + return NULL; + } + pType = (AstType*)pDecl; + if (m_declType == FD_simple || m_pComplexPart == NULL) + return pType; + + if (m_pComplexPart->getNodeType() == NT_array) + { + pArray = (AstArray*)m_pComplexPart; + pArray->setType(pType); + + // insert array type in global scope + AstScope* pScope = idlc()->scopes()->bottom(); + if ( pScope ) + { + AstDeclaration* pDecl2 = pScope->addDeclaration(pArray); + if ( (AstDeclaration*)pArray != pDecl2 ) + { + delete m_pComplexPart; + m_pComplexPart = pDecl2; + } + } + return pArray; + } + + return NULL; // return through this statement should not happen +} + +FeInheritanceHeader::FeInheritanceHeader( + NodeType nodeType, ::rtl::OString* pName, ::rtl::OString* pInherits, + std::vector< rtl::OString > * typeParameters) + : m_nodeType(nodeType) + , m_pName(pName) + , m_pInherits(NULL) +{ + if (typeParameters != 0) { + m_typeParameters = *typeParameters; + } + initializeInherits(pInherits); +} + +void FeInheritanceHeader::initializeInherits(::rtl::OString* pInherits) +{ + if ( pInherits ) + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = pScope->lookupByName(*pInherits); + if ( pDecl ) + { + AstDeclaration const * resolved = resolveTypedefs(pDecl); + if ( resolved->getNodeType() == getNodeType() + && (resolved->getNodeType() != NT_interface + || static_cast< AstInterface const * >( + resolved)->isDefined()) ) + { + if ( idlc()->error()->checkPublished( pDecl ) ) + { + m_pInherits = pDecl; + } + } + else + { + idlc()->error()->inheritanceError( + getNodeType(), getName(), pDecl); + } + } + else + { + idlc()->error()->lookupError(*pInherits); + } + } +} diff --git a/idlc/source/idlc.cxx b/idlc/source/idlc.cxx new file mode 100644 index 000000000000..1477739cd531 --- /dev/null +++ b/idlc/source/idlc.cxx @@ -0,0 +1,341 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/idlc.hxx> +#include <idlc/errorhandler.hxx> +#include <idlc/astscope.hxx> +#include <idlc/astmodule.hxx> +#include <idlc/astservice.hxx> +#include <idlc/astconstants.hxx> +#include <idlc/astexception.hxx> +#include <idlc/astunion.hxx> +#include <idlc/astenum.hxx> +#include <idlc/astinterface.hxx> +#include <idlc/astoperation.hxx> +#include <idlc/astbasetype.hxx> +#include "idlc/astdeclaration.hxx" +#include "idlc/astparameter.hxx" +#include "idlc/astsequence.hxx" +#include "idlc/asttype.hxx" +#include "idlc/asttypedef.hxx" + +#include "osl/diagnose.h" + +using namespace ::rtl; + +AstDeclaration* SAL_CALL scopeAsDecl(AstScope* pScope) +{ + if (pScope == NULL) return NULL; + + switch( pScope->getScopeNodeType() ) + { + case NT_service: + case NT_singleton: + return (AstService*)(pScope); + case NT_module: + case NT_root: + return (AstModule*)(pScope); + case NT_constants: + return (AstConstants*)(pScope); + case NT_interface: + return (AstInterface*)(pScope); + case NT_operation: + return (AstOperation*)(pScope); + case NT_exception: + return (AstException*)(pScope); + case NT_union: + return (AstUnion*)(pScope); + case NT_struct: + return (AstStruct*)(pScope); + case NT_enum: + return (AstEnum*)(pScope); + default: + return NULL; + } +} + +AstScope* SAL_CALL declAsScope(AstDeclaration* pDecl) +{ + if (pDecl == NULL) return NULL; + + switch(pDecl->getNodeType()) + { + case NT_interface: + return (AstInterface*)(pDecl); + case NT_service: + case NT_singleton: + return (AstService*)(pDecl); + case NT_module: + case NT_root: + return (AstModule*)(pDecl); + case NT_constants: + return (AstConstants*)(pDecl); + case NT_exception: + return (AstException*)(pDecl); + case NT_union: + return (AstUnion*)(pDecl); + case NT_struct: + return (AstStruct*)(pDecl); + case NT_enum: + return (AstEnum*)(pDecl); + case NT_operation: + return (AstOperation*)(pDecl); + default: + return NULL; + } +} + +static void SAL_CALL predefineXInterface(AstModule* pRoot) +{ + // define the modules com::sun::star::uno + AstModule* pParentScope = pRoot; + AstModule* pModule = new AstModule(OString("com"), pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule(OString("sun"), pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule(OString("star"), pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule(OString("uno"), pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + + // define XInterface + AstInterface* pInterface = new AstInterface(OString("XInterface"), NULL, pParentScope); + pInterface->setDefined(); + pInterface->setPredefined(true); + pInterface->setPublished(); + pParentScope->addDeclaration(pInterface); + + // define XInterface::queryInterface + AstOperation* pOp = new AstOperation(0, (AstType*)(pRoot->lookupPrimitiveType(ET_any)), + OString("queryInterface"), pInterface); + AstParameter* pParam = new AstParameter(DIR_IN, false, + (AstType*)(pRoot->lookupPrimitiveType(ET_type)), + OString("aType"), pOp); + pOp->addDeclaration(pParam); + pInterface->addMember(pOp); + + // define XInterface::acquire + pOp = new AstOperation(1, (AstType*)(pRoot->lookupPrimitiveType(ET_void)), + OString("acquire"), pInterface); + pInterface->addMember(pOp); + + // define XInterface::release + pOp = new AstOperation(1, (AstType*)(pRoot->lookupPrimitiveType(ET_void)), + OString("release"), pInterface); + pInterface->addMember(pOp); +} + +static void SAL_CALL initializePredefinedTypes(AstModule* pRoot) +{ + AstBaseType* pPredefined = NULL; + if ( pRoot ) + { + pPredefined = new AstBaseType(ET_long, OString("long"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ulong, OString("unsigned long"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_hyper, OString("hyper"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_uhyper, OString("unsigned hyper"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_short, OString("short"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ushort, OString("unsigned short"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_float, OString("float"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_double, OString("double"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_char, OString("char"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_byte, OString("byte"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_any, OString("any"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_string, OString("string"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_type, OString("type"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_boolean, OString("boolean"), pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_void, OString("void"), pRoot); + pRoot->addDeclaration(pPredefined); + } +} + +Idlc::Idlc(Options* pOptions) + : m_pOptions(pOptions) + , m_bIsDocValid(sal_False) + , m_bIsInMainfile(sal_True) + , m_published(false) + , m_errorCount(0) + , m_warningCount(0) + , m_lineNumber(0) + , m_parseState(PS_NoState) +{ + m_pScopes = new AstStack(); + // init root object after construction + m_pRoot = NULL; + m_pErrorHandler = new ErrorHandler(); + m_bGenerateDoc = m_pOptions->isValid("-C"); +} + +Idlc::~Idlc() +{ + if (m_pRoot) + delete m_pRoot; + if (m_pScopes) + delete m_pScopes; + if (m_pErrorHandler) + delete m_pErrorHandler; +} + +void Idlc::init() +{ + if ( m_pRoot ) + delete m_pRoot; + + m_pRoot = new AstModule(NT_root, OString(), NULL); + + // push the root node on the stack + m_pScopes->push(m_pRoot); + initializePredefinedTypes(m_pRoot); + predefineXInterface(m_pRoot); +} + +void Idlc::reset() +{ + m_bIsDocValid = sal_False; + m_bIsInMainfile = sal_True; + m_published = false; + + m_errorCount = 0; + m_warningCount = 0; + m_lineNumber = 0; + m_parseState = PS_NoState; + + m_fileName = OString(); + m_mainFileName = OString(); + m_realFileName = OString(); + m_documentation = OString(); + + m_pScopes->clear(); + if ( m_pRoot) + delete m_pRoot; + + m_pRoot = new AstModule(NT_root, OString(), NULL); + + // push the root node on the stack + m_pScopes->push(m_pRoot); + initializePredefinedTypes(m_pRoot); +} + +sal_Bool Idlc::isDocValid() +{ + if ( m_bGenerateDoc ) + return m_bIsDocValid; + return sal_False;; +} + +static Idlc* pStaticIdlc = NULL; + +Idlc* SAL_CALL idlc() +{ + return pStaticIdlc; +} + +Idlc* SAL_CALL setIdlc(Options* pOptions) +{ + if ( pStaticIdlc ) + { + delete pStaticIdlc; + } + pStaticIdlc = new Idlc(pOptions); + pStaticIdlc->init(); + return pStaticIdlc; +} + +AstDeclaration const * resolveTypedefs(AstDeclaration const * type) { + if (type != 0) { + while (type->getNodeType() == NT_typedef) { + type = static_cast< AstTypeDef const * >(type)->getBaseType(); + } + } + return type; +} + +AstDeclaration const * deconstructAndResolveTypedefs( + AstDeclaration const * type, sal_Int32 * rank) +{ + *rank = 0; + for (;;) { + if (type == 0) { + return 0; + } + switch (type->getNodeType()) { + case NT_typedef: + type = static_cast< AstTypeDef const * >(type)->getBaseType(); + break; + case NT_sequence: + ++(*rank); + type = static_cast< AstSequence const * >(type)->getMemberType(); + break; + default: + return type; + } + } +} + +AstInterface const * resolveInterfaceTypedefs(AstType const * type) { + AstDeclaration const * decl = resolveTypedefs(type); + OSL_ASSERT(decl->getNodeType() == NT_interface); + return static_cast< AstInterface const * >(decl); +} diff --git a/idlc/source/idlccompile.cxx b/idlc/source/idlccompile.cxx new file mode 100644 index 000000000000..26bf288e2ad0 --- /dev/null +++ b/idlc/source/idlccompile.cxx @@ -0,0 +1,418 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/idlc.hxx> +#include <rtl/ustring.hxx> +#include <rtl/strbuf.hxx> +#include <osl/process.h> +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/file.hxx> + +#if defined(SAL_W32) || defined(SAL_OS2) +#include <io.h> +#endif + +#ifdef SAL_UNX +#include <unistd.h> +#if defined(MACOSX) || defined(FREEBSD) || defined(NETBSD) +#include <sys/wait.h> +#else +#include <wait.h> +#endif +#endif + +#include <string.h> + +using namespace ::rtl; +using namespace ::osl; + +extern int yyparse(); +extern FILE* yyin; +extern int yydebug; + +sal_Int32 lineNumber = 1; + + +static OUString TMP(RTL_CONSTASCII_USTRINGPARAM("TMP")); +static OUString TEMP(RTL_CONSTASCII_USTRINGPARAM("TEMP")); +static sal_Char tmpFilePattern[512]; + +sal_Bool isFileUrl(const OString& fileName) +{ + if (fileName.indexOf("file://") == 0 ) + return sal_True; + return sal_False; +} + +OString convertToAbsoluteSystemPath(const OString& fileName) +{ + OUString uSysFileName; + OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding()); + if ( isFileUrl(fileName) ) + { + if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + } else + { + OUString uWorkingDir, uUrlFileName, uTmp; + if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getFileURLFromSystemPath(uFileName, uTmp) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + } + + return OUStringToOString(uSysFileName, osl_getThreadTextEncoding()); +} + +OString convertToFileUrl(const OString& fileName) +{ + if ( !isFileUrl(fileName) ) + { + OString tmp = convertToAbsoluteSystemPath(fileName); + OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding()); + OUString uUrlFileName; + if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) + != FileBase::E_None) + { + OSL_ASSERT(false); + } + return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding()); + } + + return fileName; +} + +OString makeTempName(const OString& prefix) +{ + OUString uTmpPath; + OString tmpPath; + + if ( osl_getEnvironment(TMP.pData, &uTmpPath.pData) != osl_Process_E_None ) + { + if ( osl_getEnvironment(TEMP.pData, &uTmpPath.pData) != osl_Process_E_None ) + { +#if defined(SAL_W32) + tmpPath = OString("c:\\temp"); +#else + tmpPath = OString("/tmp"); +#endif + } + } + + if ( uTmpPath.getLength() ) + tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8); + +#if defined(SAL_W32) || defined(SAL_UNX) || defined(SAL_OS2) + + OSL_ASSERT( sizeof(tmpFilePattern) > ( strlen(tmpPath) + + RTL_CONSTASCII_LENGTH( + PATH_SEPARATOR ) + + prefix.getLength() + + RTL_CONSTASCII_LENGTH( + "XXXXXX") ) ); + + tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0'; + strncpy(tmpFilePattern, tmpPath, sizeof(tmpFilePattern)-1); + strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); + +#ifdef SAL_UNX + int nDescriptor = mkstemp(tmpFilePattern); + if( -1 == nDescriptor ) + { + fprintf( stderr,"idlc: couldn't create temporary file\n" ); + exit( 1 ); + } + // the file shall later be reopened by stdio functions + close( nDescriptor ); +#else + (void) mktemp(tmpFilePattern); +#endif +#endif + + return OString(tmpFilePattern); +} + +sal_Bool copyFile(const OString* source, const OString& target) +{ + sal_Bool bRet = sal_True; + + FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb"); + + if ( !pSource ) + return sal_False; + + FILE* pTarget = fopen(target.getStr(), "wb"); + + if ( !pTarget ) + { + fclose(pSource); + return sal_False; + } + + size_t totalSize = 512; + size_t readSize = 0; + size_t writeSize = 0; + char pBuffer[513]; + + while ( !feof(pSource) ) + { + if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) ) + { + if ( (writeSize = fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) ) + { + if (source != 0) { + fclose(pSource); + } + fclose(pTarget); + return sal_False; + } + } + } + + if (source != 0) { + fclose(pSource); + } + if ( fflush(pTarget) ) + bRet = sal_False; + fclose(pTarget); + + return bRet; +} + +sal_Int32 compileFile(const OString * pathname) +{ + // preprocess input file + OString tmpFile = makeTempName(OString("idli_")); + OString preprocFile = makeTempName(OString("idlf_")); + + OString fileName; + if (pathname == 0) { + fileName = "stdin"; + } else { + fileName = *pathname; + } + + if ( !copyFile(pathname, tmpFile) ) + { + fprintf(stderr, "%s: could not copy %s%s to %s\n", + idlc()->getOptions()->getProgramName().getStr(), + pathname == 0 ? "" : "file ", fileName.getStr(), + tmpFile.getStr()); + exit(99); + } + + idlc()->setFileName(fileName); + idlc()->setMainFileName(fileName); + idlc()->setRealFileName(tmpFile); + + OStringBuffer cppArgs(512); + cppArgs.append("-DIDL -Xi -Xc -+ -I."); + Options* pOptions = idlc()->getOptions(); + + OString filePath; + sal_Int32 index = fileName.lastIndexOf(SEPARATOR); + + if ( index > 0) + { + filePath = fileName.copy(0, index); + + if ( filePath.getLength() ) + { + cppArgs.append(" -I\""); + cppArgs.append(filePath); + cppArgs.append("\""); + } + } + + if ( pOptions->isValid("-D") ) + { + cppArgs.append(" "); + cppArgs.append(pOptions->getOption("-D")); + } + if ( pOptions->isValid("-I") ) + { + cppArgs.append(" "); + cppArgs.append(pOptions->getOption("-I")); + } + + cppArgs.append(" \""); + cppArgs.append(tmpFile); + cppArgs.append("\" \""); + cppArgs.append(preprocFile); + cppArgs.append("\""); + + OString cmdFileName = makeTempName(OString("idlc_")); + FILE* pCmdFile = fopen(cmdFileName, "w"); + + if ( !pCmdFile ) + { + fprintf(stderr, "%s: couldn't open temporary file for preprocessor commands: %s\n", + idlc()->getOptions()->getProgramName().getStr(), cmdFileName.getStr()); + exit(99); + } +#ifdef SAL_OS2_00 + char* tok = strtok( (char*)cppArgs.getStr(), " \t\n\r"); + while( tok) { + if (tok[strlen(tok)-1] == '\"') + tok[strlen(tok)-1] = '\0'; + if (*tok == '\"') + memcpy( tok, tok+1, strlen(tok)); + if (strlen(tok)>0) { + fputs(tok, pCmdFile); + fputc('\n', pCmdFile); + } + tok = strtok( NULL, " \t\n\r"); + } +#else + fprintf(pCmdFile, "%s", cppArgs.getStr()); +#endif + fclose(pCmdFile); + + OUString cmdArg(RTL_CONSTASCII_USTRINGPARAM("@")); + cmdArg += OStringToOUString(cmdFileName, RTL_TEXTENCODING_UTF8); + + OUString cpp; + OUString startDir; + if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) { + OSL_ASSERT(false); + } + + sal_Int32 idx= cpp.lastIndexOf(OUString( RTL_CONSTASCII_USTRINGPARAM("idlc")) ); + cpp = cpp.copy(0, idx); + +#if defined(SAL_W32) || defined(SAL_OS2) + cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("idlcpp.exe")); +#else + cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("idlcpp")); +#endif + + oslProcess hProcess = NULL; + oslProcessError procError = osl_Process_E_None; + + procError = osl_executeProcess(cpp.pData, &cmdArg.pData, 1, osl_Process_WAIT, + 0, startDir.pData, 0, 0, &hProcess); + + oslProcessInfo hInfo; + hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo)); + if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo) + != osl_Process_E_None) + { + OSL_ASSERT(false); + } + + if ( procError || (hInfo.Code != 0) ) + { + if ( procError != osl_Process_E_None ) + fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr()); + else + fprintf(stderr, "%s: preprocessing %s%s failed\n", + pOptions->getProgramName().getStr(), + pathname == 0 ? "" : "file ", fileName.getStr()); + + unlink(tmpFile.getStr()); + unlink(preprocFile.getStr()); + unlink(cmdFileName.getStr()); + osl_freeProcessHandle(hProcess); + exit(hInfo.Code ? hInfo.Code : 99); + } + osl_freeProcessHandle(hProcess); + + if (unlink(tmpFile.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove cpp input file %s\n", + pOptions->getProgramName().getStr(), tmpFile.getStr()); + exit(99); + } + + if (unlink(cmdFileName.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove unocpp command file %s\n", + pOptions->getProgramName().getStr(), cmdFileName.getStr()); + + exit(99); + } + + if ( pOptions->isValid("-E") ) + { + if (unlink(preprocFile) != 0) + { + fprintf(stderr, "%s: Could not remove parser input file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + exit(0); + } + + // parse file + yyin = fopen(preprocFile.getStr(), "r"); + if (yyin == NULL) + { + fprintf(stderr, "%s: Could not open cpp output file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + + //yydebug = 0 no trace information + //yydebug = 1 parser produce trace information + yydebug = 0; + + sal_Int32 nErrors = yyparse(); + nErrors = idlc()->getErrorCount(); + + fclose(yyin); + if (unlink(preprocFile.getStr()) != 0) + { + fprintf(stderr, "%s: Could not remove parser input file %s\n", + pOptions->getProgramName().getStr(), preprocFile.getStr()); + exit(99); + } + + return nErrors; +} diff --git a/idlc/source/idlcmain.cxx b/idlc/source/idlcmain.cxx new file mode 100644 index 000000000000..006131f727df --- /dev/null +++ b/idlc/source/idlcmain.cxx @@ -0,0 +1,148 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/idlc.hxx> +#include "sal/main.h" + +using namespace ::rtl; + +SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) +{ + Options options; + + try + { + if (!options.initOptions(argc, argv)) + exit(1); + } + catch( IllegalArgument& e) + { + fprintf(stderr, "Illegal argument: %s\n%s", + e.m_message.getStr(), + options.prepareVersion().getStr()); + exit(99); + } + + setIdlc(&options); + + sal_Int32 nErrors = 0; + if (options.readStdin()) { + if ( !options.quiet() ) + fprintf( + stdout, "%s: Compiling stdin\n", + options.getProgramName().getStr()); + nErrors = compileFile(0); + if ( ( idlc()->getWarningCount() > 0 ) && !options.quiet() ) { + fprintf( + stdout, "%s: detected %lu warnings compiling stdin\n", + options.getProgramName().getStr(), + sal::static_int_cast< unsigned long >( + idlc()->getWarningCount())); + } + OString outputUrl; + if (options.isValid("-O")) { + outputUrl = convertToFileUrl(options.getOption("-O")); + if (outputUrl[outputUrl.getLength() - 1] != '/') { + outputUrl += "/"; + } + outputUrl += "stdin.urd"; + } else { + outputUrl = convertToFileUrl("stdin.urd"); + } + if (nErrors > 0) { + removeIfExists(outputUrl); + } else { + nErrors = produceFile(outputUrl); + } + idlc()->reset(); + } + StringVector const & files = options.getInputFiles(); + if ( options.verbose() ) + { + fprintf( stdout, "%s: compiling %i source files ... \n", + options.getProgramName().getStr(), (int)files.size() ); + fflush( stdout ); + } + for (StringVector::const_iterator i(files.begin()); + i != files.end() && nErrors == 0; ++i) + { + OString sysFileName( convertToAbsoluteSystemPath(*i) ); + + if ( !options.quiet() ) + fprintf(stdout, "Compiling: %s\n", + (*i).getStr()); + nErrors = compileFile(&sysFileName); + + if ( idlc()->getWarningCount() && !options.quiet() ) + fprintf(stdout, "%s: detected %lu warnings compiling file '%s'\n", + options.getProgramName().getStr(), + sal::static_int_cast< unsigned long >( + idlc()->getWarningCount()), + (*i).getStr()); + + // prepare output file name + OString outputFileUrl; + if ( options.isValid("-O") ) + { + OString strippedFileName(sysFileName.copy(sysFileName.lastIndexOf(SEPARATOR) + 1)); + outputFileUrl = convertToFileUrl(options.getOption("-O")); + sal_Char c = outputFileUrl.getStr()[outputFileUrl.getLength()-1]; + + if ( c != '/' ) + outputFileUrl += OString::valueOf('/'); + + outputFileUrl += strippedFileName.replaceAt(strippedFileName.getLength() -3 , 3, "urd"); + } else + { + outputFileUrl = convertToFileUrl(sysFileName.replaceAt(sysFileName.getLength() -3 , 3, "urd")); + } + + if ( nErrors ) + removeIfExists(outputFileUrl); + else + nErrors = produceFile(outputFileUrl); + + idlc()->reset(); + } + + if ( nErrors > 0 ) + { + fprintf(stderr, "%s: detected %ld errors%s", + options.getProgramName().getStr(), + sal::static_int_cast< long >(nErrors), + options.prepareVersion().getStr()); + } else + { + if ( options.verbose() ) + fprintf(stdout, "%s: returned successful%s", + options.getProgramName().getStr(), + options.prepareVersion().getStr()); + } + return nErrors; +} diff --git a/idlc/source/idlcproduce.cxx b/idlc/source/idlcproduce.cxx new file mode 100644 index 000000000000..e20b7da1c42b --- /dev/null +++ b/idlc/source/idlcproduce.cxx @@ -0,0 +1,210 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" +#include <idlc/idlc.hxx> +#include <idlc/astmodule.hxx> +#include <rtl/strbuf.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> + +#if defined(SAL_W32) || defined(SAL_OS2) +#include <io.h> +#include <direct.h> +#include <errno.h> +#endif + +#ifdef SAL_UNX +#include <unistd.h> +#include <sys/stat.h> +#include <errno.h> +#endif + +#include <string.h> + +using namespace ::rtl; +using namespace ::osl; + +StringList* pCreatedDirectories = NULL; + +static sal_Bool checkOutputPath(const OString& completeName) +{ + OString sysPathName = convertToAbsoluteSystemPath(completeName); + OStringBuffer buffer(sysPathName.getLength()); + + if ( sysPathName.indexOf( SEPARATOR ) == -1 ) + return sal_True; + + sal_Int32 nIndex = 0; + OString token(sysPathName.getToken(0, SEPARATOR, nIndex)); + const sal_Char* p = token.getStr(); + if (strcmp(p, "..") == 0 + || *(p+1) == ':' + || strcmp(p, ".") == 0) + { + buffer.append(token); + buffer.append(SEPARATOR); + } + else + nIndex = 0; + + do + { + buffer.append(sysPathName.getToken(0, SEPARATOR, nIndex)); + + if ( buffer.getLength() > 0 && nIndex != -1 ) + { +#if defined(SAL_UNX) || defined(SAL_OS2) + if (mkdir((char*)buffer.getStr(), 0777) == -1) +#else + if (mkdir((char*)buffer.getStr()) == -1) +#endif + { + if (errno == ENOENT) + { + fprintf(stderr, "%s: cannot create directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), buffer.getStr()); + return sal_False; + } + } else + { + if ( !pCreatedDirectories ) + pCreatedDirectories = new StringList(); + pCreatedDirectories->push_front(buffer.getStr()); + } + } + buffer.append(SEPARATOR); + } while( nIndex != -1 ); + return sal_True; +} + +static sal_Bool cleanPath() +{ + if ( pCreatedDirectories ) + { + StringList::iterator iter = pCreatedDirectories->begin(); + StringList::iterator end = pCreatedDirectories->end(); + while ( iter != end ) + { +//#ifdef SAL_UNX +// if (rmdir((char*)(*iter).getStr(), 0777) == -1) +//#else + if (rmdir((char*)(*iter).getStr()) == -1) +//#endif + { + fprintf(stderr, "%s: cannot remove directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), (*iter).getStr()); + return sal_False; + } + ++iter; + } + delete pCreatedDirectories; + } + return sal_True; +} + +void removeIfExists(const OString& pathname) +{ + unlink(pathname.getStr()); +} + +sal_Int32 SAL_CALL produceFile(const OString& regFileName) +{ + Options* pOptions = idlc()->getOptions(); + + OString regTmpName = regFileName.replaceAt(regFileName.getLength() -3, 3, "_idlc_"); + + if ( !checkOutputPath(regFileName) ) + { + fprintf(stderr, "%s: could not create path of registry file '%s'.\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + return 1; + } + + removeIfExists(regTmpName); + OString urlRegTmpName = convertToFileUrl(regTmpName); + + Registry regFile; + if ( regFile.create(OStringToOUString(urlRegTmpName, RTL_TEXTENCODING_UTF8)) != REG_NO_ERROR ) + { + fprintf(stderr, "%s: could not create registry file '%s'\n", + pOptions->getProgramName().getStr(), regTmpName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + RegistryKey rootKey; + if ( regFile.openRootKey(rootKey) != REG_NO_ERROR ) + { + fprintf(stderr, "%s: could not open root of registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + // produce registry file + if ( !idlc()->getRoot()->dump(rootKey) ) + { + rootKey.releaseKey(); + regFile.close(); + regFile.destroy(OStringToOUString(regFileName, RTL_TEXTENCODING_UTF8)); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + rootKey.releaseKey(); + if ( regFile.close() != REG_NO_ERROR ) + { + fprintf(stderr, "%s: could not close registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + removeIfExists(regFileName); + + if ( File::move(OStringToOUString(regTmpName, osl_getThreadTextEncoding()), + OStringToOUString(regFileName, osl_getThreadTextEncoding())) != FileBase::E_None ) { + fprintf(stderr, "%s: cannot rename temporary registry '%s' to '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + regTmpName.getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + cleanPath(); + return 1; + } + removeIfExists(regTmpName); + + return 0; +} diff --git a/idlc/source/makefile.mk b/idlc/source/makefile.mk new file mode 100644 index 000000000000..879090d15b54 --- /dev/null +++ b/idlc/source/makefile.mk @@ -0,0 +1,129 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=.. + +PRJNAME=idlc +TARGET=idlc +TARGETTYPE=CUI +LIBTARGET=NO + +ENABLE_EXCEPTIONS=TRUE +INCPRE=$(MISC) + +.IF "$(GUI)" == "OS2" +STL_OS2_BUILDING=1 +.ENDIF + +# --- Settings ----------------------------------------------------- + + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +CXXFILES= \ + wrap_scanner.cxx \ + wrap_parser.cxx \ + idlcmain.cxx \ + idlc.cxx \ + idlccompile.cxx \ + idlcproduce.cxx \ + errorhandler.cxx \ + options.cxx \ + fehelper.cxx \ + astdeclaration.cxx \ + astscope.cxx \ + aststack.cxx \ + astdump.cxx \ + astinterface.cxx \ + aststruct.cxx \ + aststructinstance.cxx \ + astoperation.cxx \ + astconstant.cxx \ + astenum.cxx \ + astarray.cxx \ + astunion.cxx \ + astexpression.cxx \ + astservice.cxx + +YACCTARGET=$(MISC)$/parser.cxx +YACCFILES=parser.y + +OBJFILES= \ + $(OBJ)$/wrap_scanner.obj \ + $(OBJ)$/wrap_parser.obj \ + $(OBJ)$/idlcmain.obj \ + $(OBJ)$/idlc.obj \ + $(OBJ)$/idlccompile.obj \ + $(OBJ)$/idlcproduce.obj \ + $(OBJ)$/errorhandler.obj \ + $(OBJ)$/options.obj \ + $(OBJ)$/fehelper.obj \ + $(OBJ)$/astdeclaration.obj \ + $(OBJ)$/astscope.obj \ + $(OBJ)$/aststack.obj \ + $(OBJ)$/astdump.obj \ + $(OBJ)$/astinterface.obj \ + $(OBJ)$/aststruct.obj \ + $(OBJ)$/aststructinstance.obj \ + $(OBJ)$/astoperation.obj \ + $(OBJ)$/astconstant.obj \ + $(OBJ)$/astenum.obj \ + $(OBJ)$/astarray.obj \ + $(OBJ)$/astunion.obj \ + $(OBJ)$/astexpression.obj \ + $(OBJ)$/astservice.obj + +APP1TARGET= $(TARGET) +APP1OBJS= $(OBJFILES) + +APP1RPATH=SDK + +APP1STDLIBS = \ + $(REGLIB) \ + $(SALLIB) \ + $(SALHELPERLIB) + +# --- Targets ------------------------------------------------------ + +.IF "$(debug)" == "" +YACCFLAGS+=-l +.ELSE +YACCFLAGS+=-v +.ENDIF + +.INCLUDE : target.mk + +$(MISC)$/stripped_scanner.ll : scanner.ll + tr -d "\015" < scanner.ll > $(MISC)$/stripped_scanner.ll + +$(MISC)$/scanner.cxx: $(MISC)$/stripped_scanner.ll + flex -o$(MISC)$/scanner.cxx $(MISC)$/stripped_scanner.ll + +$(OBJ)$/wrap_parser.obj: $(MISC)$/parser.cxx +$(OBJ)$/wrap_scanner.obj: $(MISC)$/scanner.cxx diff --git a/idlc/source/options.cxx b/idlc/source/options.cxx new file mode 100644 index 000000000000..c90bce43b3bc --- /dev/null +++ b/idlc/source/options.cxx @@ -0,0 +1,371 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" + +#include <stdio.h> +#include /*MSVC trouble: <cstring>*/ <string.h> +#include <idlc/options.hxx> + +using namespace rtl; + +Options::Options(): m_stdin(false), m_verbose(false), m_quiet(false) +{ +} + +Options::~Options() +{ +} + +sal_Bool Options::initOptions(int ac, char* av[], sal_Bool bCmdFile) + throw( IllegalArgument ) +{ + sal_Bool ret = sal_True; + sal_uInt16 j=0; + + if (!bCmdFile) + { + bCmdFile = sal_True; + + m_program = av[0]; + + if (ac < 2) + { + fprintf(stderr, "%s", prepareHelp().getStr()); + ret = sal_False; + } + + j = 1; + } else + { + j = 0; + } + + char *s=NULL; + for (; j < ac; j++) + { + if (av[j][0] == '-') + { + switch (av[j][1]) + { + case 'O': + if (av[j][2] == '\0') + { + if (j < ac - 1 && av[j+1][0] != '-') + { + j++; + s = av[j]; + } else + { + OString tmp("'-O', please check"); + if (j <= ac - 1) + { + tmp += " your input '" + OString(av[j+1]) + "'"; + } + + throw IllegalArgument(tmp); + } + } else + { + s = av[j] + 2; + } + + m_options["-O"] = OString(s); + break; + case 'I': + { + if (av[j][2] == '\0') + { + if (j < ac - 1 && av[j+1][0] != '-') + { + j++; + s = av[j]; + } else + { + OString tmp("'-I', please check"); + if (j <= ac - 1) + { + tmp += " your input '" + OString(av[j+1]) + "'"; + } + + throw IllegalArgument(tmp); + } + } else + { + s = av[j] + 2; + } + + OString inc(s); + if ( inc.indexOf(';') > 0 ) + { + OString tmp(s); + sal_Int32 nIndex = 0; + inc = OString(); + do inc = inc + " -I\"" + tmp.getToken( 0, ';', nIndex ) +"\""; while( nIndex != -1 ); + } else + inc = OString("-I\"") + s + "\""; + + if (m_options.count("-I") > 0) + { + OString tmp(m_options["-I"]); + tmp = tmp + " " + inc; + m_options["-I"] = tmp; + } else + { + m_options["-I"] = inc; + } + } + break; + case 'D': + if (av[j][2] == '\0') + { + if (j < ac - 1 && av[j+1][0] != '-') + { + j++; + s = av[j]; + } else + { + OString tmp("'-D', please check"); + if (j <= ac - 1) + { + tmp += " your input '" + OString(av[j+1]) + "'"; + } + + throw IllegalArgument(tmp); + } + } else + { + s = av[j]; + } + + if (m_options.count("-D") > 0) + { + OString tmp(m_options["-D"]); + tmp = tmp + " " + s; + m_options["-D"] = tmp; + } else + m_options["-D"] = OString(s); + break; + case 'C': + if (av[j][2] != '\0') + { + throw IllegalArgument(OString(av[j]) + ", please check your input"); + } + if (m_options.count("-C") == 0) + m_options["-C"] = OString(av[j]); + break; + case 'c': + if (av[j][2] == 'i' && av[j][3] == 'd' && av[j][4] == '\0') + { + if (m_options.count("-cid") == 0) + m_options["-cid"] = OString(av[j]); + } else + throw IllegalArgument(OString(av[j]) + ", please check your input"); + break; + case 'v': + if ( 0 == strcmp( &av[j][1], "verbose" ) ) + { + m_verbose = true; + } + else + throw IllegalArgument(OString(av[j]) + ", please check your input"); + break; + case 'q': + if ( 0 == strcmp( &av[j][1], "quiet" ) ) + { + m_quiet = true; + } + else + throw IllegalArgument(OString(av[j]) + ", please check your input"); + break; + case 'w': + if (av[j][2] == 'e' && av[j][3] == '\0') { + if (m_options.count("-we") == 0) + m_options["-we"] = OString(av[j]); + } else { + if (av[j][2] == '\0') { + if (m_options.count("-w") == 0) + m_options["-w"] = OString(av[j]); + } else + throw IllegalArgument(OString(av[j]) + ", please check your input"); + } + break; + case 'h': + case '?': + if (av[j][2] != '\0') + { + throw IllegalArgument(OString(av[j]) + ", please check your input"); + } else + { + fprintf(stdout, "%s", prepareHelp().getStr()); + exit(0); + } + case 's': + if (/*MSVC trouble: std::*/strcmp(&av[j][2], "tdin") == 0) + { + m_stdin = true; + break; + } + // fall through + default: + throw IllegalArgument("the option is unknown" + OString(av[j])); + } + } else + { + if (av[j][0] == '@') + { + FILE* cmdFile = fopen(av[j]+1, "r"); + if( cmdFile == NULL ) + { + fprintf(stderr, "%s", prepareHelp().getStr()); + ret = sal_False; + } else + { + int rargc=0; + char* rargv[512]; + char buffer[512]=""; + + int i=0; + int found = 0; + char c; + while ( fscanf(cmdFile, "%c", &c) != EOF ) + { + if (c=='\"') { + if (found) { + found=0; + } else { + found=1; + continue; + } + } else { + if (c!=13 && c!=10) { + if (found || c!=' ') { + buffer[i++]=c; + continue; + } + } + if (i==0) + continue; + } + buffer[i]='\0'; + found=0; + i=0; + rargv[rargc]= strdup(buffer); + rargc++; + buffer[0]='\0'; + } + if (buffer[0] != '\0') { + buffer[i]='\0'; + rargv[rargc]= strdup(buffer); + rargc++; + } + fclose(cmdFile); + + ret = initOptions(rargc, rargv, bCmdFile); + + long ii = 0; + for (ii=0; ii < rargc; ii++) + { + free(rargv[ii]); + } + } + } else + { + OString name(av[j]); + name = name.toAsciiLowerCase(); + if ( name.lastIndexOf(".idl") != (name.getLength() - 4) ) + { + throw IllegalArgument("'" + OString(av[j]) + + "' is not a valid input file, only '*.idl' files will be accepted"); + } + m_inputFiles.push_back(av[j]); + } + } + } + + return ret; +} + +OString Options::prepareHelp() +{ + OString help("\nusing: "); + help += m_program + + " [-options] <file_1> ... <file_n> | @<filename> | -stdin\n"; + help += " <file_n> = file_n specifies one or more idl files.\n"; + help += " Only files with the extension '.idl' are valid.\n"; + help += " @<filename> = filename specifies the name of a command file.\n"; + help += " -stdin = read idl file from standard input.\n"; + help += " Options:\n"; + help += " -O<path> = path specifies the output directory.\n"; + help += " The generated output is a registry file with\n"; + help += " the same name as the idl input file (or 'stdin'\n"; + help += " for -stdin).\n"; + help += " -I<path> = path specifies a directory where include\n"; + help += " files will be searched by the preprocessor.\n"; + help += " Multiple directories can be combined with ';'.\n"; + help += " -D<name> = name defines a macro for the preprocessor.\n"; + help += " -C = generate complete type information, including\n"; + help += " documentation.\n"; + help += " -cid = check if identifiers fulfill the UNO naming\n"; + help += " requirements.\n"; + help += " -w = display warning messages.\n"; + help += " -we = treat warnings as errors.\n"; + help += " -h|-? = print this help message and exit.\n"; + help += prepareVersion(); + + return help; +} + +OString Options::prepareVersion() +{ + OString version("\nSun Microsystems (R) "); + version += m_program + " Version 1.1\n\n"; + return version; +} + +const OString& Options::getProgramName() const +{ + return m_program; +} + +sal_Bool Options::isValid(const OString& option) +{ + return (m_options.count(option) > 0); +} + +const OString Options::getOption(const OString& option) + throw( IllegalArgument ) +{ + if (m_options.count(option) > 0) + { + return m_options[option]; + } else + { + throw IllegalArgument("Option is not valid or currently not set."); + } +} diff --git a/idlc/source/parser.y b/idlc/source/parser.y new file mode 100644 index 000000000000..8da9c7ad63b5 --- /dev/null +++ b/idlc/source/parser.y @@ -0,0 +1,3292 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +/* + * parser.yy - BISON grammar for IDLC 1.0 + */ + +%{ +#include <string.h> + +#ifndef _IDLC_IDLC_HXX_ +#include <idlc/idlc.hxx> +#endif +#ifndef _IDLC_ERRORHANDLER_HXX_ +#include <idlc/errorhandler.hxx> +#endif +#ifndef _IDLC_FEHELPER_HXX_ +#include <idlc/fehelper.hxx> +#endif +#ifndef _IDLC_EXPRESSION_HXX_ +#include <idlc/astexpression.hxx> +#endif +#ifndef _IDLC_ASTCONSTANTS_HXX_ +#include <idlc/astconstants.hxx> +#endif +#ifndef _IDLC_ASTCONSTANT_HXX_ +#include <idlc/astconstant.hxx> +#endif +#ifndef _IDLC_ASTARRAY_HXX_ +#include <idlc/astarray.hxx> +#endif +#ifndef _IDLC_ASTBASETYPE_HXX_ +#include <idlc/astbasetype.hxx> +#endif +#ifndef _IDLC_ASTTYPEDEF_HXX_ +#include <idlc/asttypedef.hxx> +#endif +#ifndef _IDLC_ASTEXCEPTION_HXX_ +#include <idlc/astexception.hxx> +#endif +#ifndef _IDLC_ASTMEMBER_HXX_ +#include <idlc/astmember.hxx> +#endif +#ifndef _IDLC_ASTENUM_HXX_ +#include <idlc/astenum.hxx> +#endif +#ifndef _IDLC_ASTSEQUENCE_HXX_ +#include <idlc/astsequence.hxx> +#endif +#ifndef _IDLC_ASTATTRIBUTE_HXX_ +#include <idlc/astattribute.hxx> +#endif +#ifndef _IDLC_ASTOPERATION_HXX_ +#include <idlc/astoperation.hxx> +#endif +#ifndef _IDLC_ASTPARAMETER_HXX_ +#include <idlc/astparameter.hxx> +#endif +#ifndef _IDLC_ASTINTERFACEMEMBER_HXX_ +#include <idlc/astinterfacemember.hxx> +#endif +#ifndef _IDLC_ASTSERVICEMEMBER_HXX_ +#include <idlc/astservicemember.hxx> +#endif +#ifndef _IDLC_ASTOBSERVES_HXX_ +#include <idlc/astobserves.hxx> +#endif +#ifndef _IDLC_ASTNEEDS_HXX_ +#include <idlc/astneeds.hxx> +#endif +#ifndef _IDLC_ASTUNION_HXX_ +#include <idlc/astunion.hxx> +#endif +#include "idlc/aststructinstance.hxx" + +#include "attributeexceptions.hxx" + +#include "rtl/strbuf.hxx" + +#include <algorithm> +#include <vector> + +using namespace ::rtl; + +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern int yylex(void); +void yyerror(char const *); + +void checkIdentifier(::rtl::OString* id) +{ + static short check = 0; + if (check == 0) { + if (idlc()->getOptions()->isValid("-cid")) + check = 1; + else + check = 2; + } + + if ( id->indexOf('_') >= 0 ) + if ( (id->pData->buffer[0] >= 97 && id->pData->buffer[0] <= 122) + || id->pData->buffer[0] == '_') { + if (check == 1) { + ::rtl::OStringBuffer msg(25 + id->getLength()); + msg.append("mismatched identifier '"); + msg.append(*id); + msg.append("'"); + idlc()->error()->syntaxError(idlc()->getParseState(), + idlc()->getLineNumber(), + msg.getStr()); + } + else + idlc()->error()->warning0(WIDL_WRONG_NAMING_CONV, id->getStr()); + } +} + +void reportDoubleMemberDeclarations( + AstInterface::DoubleMemberDeclarations const & doubleMembers) +{ + for (AstInterface::DoubleMemberDeclarations::const_iterator i( + doubleMembers.begin()); + i != doubleMembers.end(); ++i) + { + idlc()->error()->error2(EIDL_DOUBLE_MEMBER, i->first, i->second); + } +} + +void addInheritedInterface( + AstInterface * ifc, rtl::OString const & name, bool optional, + rtl::OUString const & documentation) +{ + AstDeclaration * decl = ifc->lookupByName(name); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (resolved != 0 && resolved->getNodeType() == NT_interface) { + if (idlc()->error()->checkPublished(decl)) { + if (!static_cast< AstInterface const * >(resolved)->isDefined()) { + idlc()->error()->inheritanceError( + NT_interface, &ifc->getScopedName(), decl); + } else { + AstInterface::DoubleDeclarations doubleDecls( + ifc->checkInheritedInterfaceClashes( + static_cast< AstInterface const * >(resolved), + optional)); + if (doubleDecls.interfaces.empty() + && doubleDecls.members.empty()) + { + ifc->addInheritedInterface( + static_cast< AstType * >(decl), optional, + documentation); + } else { + for (AstInterface::DoubleInterfaceDeclarations::iterator i( + doubleDecls.interfaces.begin()); + i != doubleDecls.interfaces.end(); ++i) + { + idlc()->error()->error1( + EIDL_DOUBLE_INHERITANCE, *i); + } + reportDoubleMemberDeclarations(doubleDecls.members); + } + } + } + } else { + idlc()->error()->lookupError( + EIDL_INTERFACEMEMBER_LOOKUP, name, scopeAsDecl(ifc)); + } +} + +AstDeclaration const * createNamedType( + rtl::OString const * scopedName, DeclList const * typeArgs) +{ + AstDeclaration * decl = idlc()->scopes()->topNonNull()->lookupByName( + *scopedName); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (decl == 0) { + idlc()->error()->lookupError(*scopedName); + } else if (!idlc()->error()->checkPublished(decl)) { + decl = 0; + } else if (resolved->getNodeType() == NT_struct) { + if (static_cast< AstStruct const * >(resolved)->getTypeParameterCount() + != (typeArgs == 0 ? 0 : typeArgs->size())) + { + idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS); + decl = 0; + } else if (typeArgs != 0) { + AstScope * global = idlc()->scopes()->bottom(); + AstDeclaration * inst = new AstStructInstance( + static_cast< AstType * >(decl), typeArgs, global); + decl = global->addDeclaration(inst); + if (decl != inst) { + delete inst; + } + } + } else if (decl->isType()) { + if (typeArgs != 0) { + idlc()->error()->error0(EIDL_WRONG_NUMBER_OF_TYPE_ARGUMENTS); + decl = 0; + } + } else { + idlc()->error()->noTypeError(decl); + decl = 0; + } + delete scopedName; + delete typeArgs; + return decl; +} + +bool includes(AstDeclaration const * type1, AstDeclaration const * type2) { + OSL_ASSERT(type2 != 0); + if (type1 != 0) { + if (type1->getNodeType() == NT_instantiated_struct) { + AstStructInstance const * inst + = static_cast< AstStructInstance const * >(type1); + if (inst->getTypeTemplate() == type2) { + return true; + } + for (DeclList::const_iterator i(inst->getTypeArgumentsBegin()); + i != inst->getTypeArgumentsEnd(); ++i) + { + if (includes(*i, type2)) { + return true; + } + } + } else if (type1 == type2) { + return true; + } + } + return false; +} + +// Suppress any warnings from generated code: +#if defined __GNUC__ +#pragma GCC system_header +#elif defined __SUNPRO_CC +#pragma disable_warn +#elif defined _MSC_VER +#pragma warning(push, 1) +#pragma warning(disable: 4273 4701 4706) +#endif +%} +/* + * Declare the type of values in the grammar + */ +%union { + ExprType etval; /* Expression type */ + AstDeclaration* dclval; /* Declaration */ + AstDeclaration const * cdclval; + DeclList * dclsval; + AstExpression* exval; /* expression value */ + ExprList* exlval; /* expression list value */ + FeDeclarator* fdval; /* declarator value */ + FeDeclList* dlval; /* declarator list value */ + FeInheritanceHeader* ihval; /* inheritance header value */ + ::rtl::OString* sval; /* OString value */ + std::vector< rtl::OString > * svals; + sal_Char* strval; /* sal_Char* value */ + sal_Bool bval; /* sal_Boolean* value */ + sal_Int64 ival; /* sal_Int64 value */ + sal_uInt64 uval; /* sal_uInt64 value */ + sal_uInt32 ulval; /* sal_uInt32 value */ + double dval; /* double value */ + float fval; /* float value */ + StringList* slval; /* StringList value */ + LabelList* llval; /* LabelList value */ + AstUnionLabel* lbval; /* union label value */ + AstMember* mval; /* member value */ + AttributeExceptions::Part attexcpval; + AttributeExceptions attexcval; +} + +/* + * Token types: These are returned by the lexer + */ + +%token <sval> IDL_IDENTIFIER +%token IDL_ATTRIBUTE +%token IDL_BOUND +%token IDL_CASE +%token IDL_CONST +%token IDL_CONSTANTS +%token IDL_CONSTRAINED +%token IDL_DEFAULT +%token IDL_ENUM +%token IDL_EXCEPTION +%token IDL_INTERFACE +%token IDL_MAYBEAMBIGUOUS +%token IDL_MAYBEDEFAULT +%token IDL_MAYBEVOID +%token IDL_MODULE +%token IDL_NEEDS +%token IDL_OBSERVES +%token IDL_OPTIONAL +%token IDL_PROPERTY +%token IDL_RAISES +%token IDL_READONLY +%token IDL_REMOVEABLE +%token IDL_SERVICE +%token IDL_SEQUENCE +%token IDL_SINGLETON +%token IDL_STRUCT +%token IDL_SWITCH +%token IDL_TYPEDEF +%token IDL_TRANSIENT +%token IDL_UNION + +%token IDL_ANY +%token IDL_CHAR +%token IDL_BOOLEAN +%token IDL_BYTE +%token IDL_DOUBLE +%token IDL_FLOAT +%token IDL_HYPER +%token IDL_LONG +%token IDL_SHORT +%token IDL_VOID +%token IDL_STRING +%token IDL_TYPE +%token IDL_UNSIGNED + +%token IDL_TRUE +%token IDL_FALSE + +%token IDL_IN +%token IDL_OUT +%token IDL_INOUT +%token IDL_ONEWAY + +%token IDL_GET +%token IDL_SET + +%token IDL_PUBLISHED + +%token IDL_ELLIPSIS + +%token <strval> IDL_LEFTSHIFT +%token <strval> IDL_RIGHTSHIFT +%token <strval> IDL_SCOPESEPARATOR + +%token <ival> IDL_INTEGER_LITERAL +%token <uval> IDL_INTEGER_ULITERAL +%token <dval> IDL_FLOATING_PT_LITERAL + +/* + * These are production names: + */ +%type <dclval> type_dcl const_dcl +%type <dclval> array_declarator +%type <dclval> exception_name +%type <cdclval> array_type constructed_type_spec enum_type op_type_spec +%type <cdclval> sequence_type_spec simple_type_spec struct_type switch_type_spec +%type <cdclval> template_type_spec type_spec union_type +%type <cdclval> fundamental_type type_arg type_or_parameter +%type <dclsval> opt_raises raises exception_list +%type <attexcpval> opt_attribute_get_raises attribute_get_raises +%type <attexcpval> opt_attribute_set_raises attribute_set_raises +%type <dclsval> opt_type_args type_args + +%type <sval> identifier +%type <sval> interface_decl +%type <sval> scoped_name inheritance_spec +%type <slval> scoped_names at_least_one_scoped_name + +%type <etval> const_type integer_type char_type boolean_type +%type <etval> floating_pt_type any_type signed_int string_type +%type <etval> unsigned_int base_type_spec byte_type type_type + +%type <exval> expression const_expr or_expr xor_expr and_expr +%type <exval> add_expr mult_expr unary_expr primary_expr shift_expr +%type <exval> literal positive_int_expr array_dim + +%type <exlval> at_least_one_array_dim array_dims + +%type <fdval> declarator simple_declarator complex_declarator +%type <dlval> declarators at_least_one_declarator + +%type <ihval> exception_header structure_header interfaceheader + +%type <ulval> flag_header opt_attrflags opt_attrflag operation_head +%type <ulval> direction service_interface_header service_service_header + +%type <llval> case_labels at_least_one_case_label +%type <lbval> case_label +%type <mval> element_spec + +%type <bval> optional_inherited_interface opt_rest opt_service_body + +%type <attexcval> opt_attribute_block attribute_block_rest opt_attribute_raises + +%type <svals> opt_type_params type_params + +%% +/* + * Grammar start here + */ +start : definitions; + +definitions : + definition definitions + | /* EMPTY */ + ; + +definition : + opt_published publishable_definition + | module_dcl + { + idlc()->setParseState(PS_ModuleDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | error ';' + { + yyerror("definitions"); + yyerrok; + } + ; + +opt_published: + IDL_PUBLISHED { idlc()->setPublished(true); } + | /* empty */ { idlc()->setPublished(false); } + ; + +publishable_definition: + type_dcl + { + idlc()->setParseState(PS_TypeDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | const_dcl + { + idlc()->setParseState(PS_ConstantDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | exception_dcl + { + idlc()->setParseState(PS_ExceptionDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | interface + { + idlc()->setParseState(PS_InterfaceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | service_dcl + { + idlc()->setParseState(PS_ServiceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | singleton_dcl + { + idlc()->setParseState(PS_SingletonDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | constants_dcl + { + idlc()->setParseState(PS_ConstantsDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + ; + +module_dcl : + IDL_MODULE + { + idlc()->setParseState(PS_ModuleSeen); + idlc()->setPublished(false); + } + identifier + { + idlc()->setParseState(PS_ModuleIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstModule* pModule = NULL; + AstDeclaration* pExists = NULL; + + if ( pScope ) + { + pModule = new AstModule(*$3, pScope); + if( (pExists = pScope->lookupForAdd(pModule)) ) + { + pExists->setInMainfile(idlc()->isInMainFile()); + pExists->setFileName(pModule->getFileName()); + if (pExists->isPredefined()) + { + pExists->setPredefined(false); + if (pExists->getDocumentation().getLength() == 0 && + pModule->getDocumentation().getLength() > 0) + { + pExists->setDocumentation(pModule->getDocumentation()); + } + } + delete(pModule); + pModule = (AstModule*)pExists; + } else + { + pScope->addDeclaration(pModule); + } + idlc()->scopes()->push(pModule); + } + delete $3; + } + '{' + { + idlc()->setParseState(PS_ModuleSqSeen); + } + definitions + { + idlc()->setParseState(PS_ModuleBodySeen); + } + '}' + { + idlc()->setParseState(PS_ModuleQsSeen); + /* + * Finished with this module - pop it from the scope stack + */ + idlc()->scopes()->pop(); + } + ; + +interface : + interface_dcl + | forward_dcl + ; + +interface_decl : + IDL_INTERFACE + { + idlc()->setParseState(PS_InterfaceSeen); + } + identifier + { + idlc()->setParseState(PS_InterfaceIDSeen); + checkIdentifier($3); + $$ = $3; + } + ; + +forward_dcl : + interface_decl + { + idlc()->setParseState(PS_ForwardDeclSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstInterface* pForward = NULL; + AstDeclaration* pDecl = NULL; + + /* + * Make a new forward interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pForward = new AstInterface(*$1, NULL, pScope); + + if ( pDecl = pScope->lookupByName(pForward->getScopedName()) ) + { + if ( (pDecl != pForward) && + (pDecl->getNodeType() == NT_interface) ) + { + delete pForward; + } else + { + idlc()->error()->error2(EIDL_REDEF_SCOPE, scopeAsDecl(pScope), pDecl); + } + } else + { + /* + * Add the interface to its definition scope + */ + pScope->addDeclaration(pForward); + } + } + delete $1; + } + ; + +interface_dcl : + interfaceheader + { + idlc()->setParseState(PS_InterfaceHeadSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstInterface* pInterface = NULL; + AstInterface* pForward = NULL; + AstDeclaration* pDecl = NULL; + + /* + * Make a new interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pInterface = new AstInterface( + *$1->getName(), + static_cast< AstInterface * >($1->getInherits()), pScope); + if ( pInterface && + (pDecl = pScope->lookupByName(pInterface->getScopedName())) ) + { + /* + * See if we're defining a forward declared interface. + */ + if (pDecl->getNodeType() == NT_interface) + { + pForward = (AstInterface*)pDecl; + if ( !pForward->isDefined() ) + { + /* + * Check if redefining in same scope + */ + if ( pForward->getScope() != pScope ) + { + if ( pForward->getScopedName() != pInterface->getScopedName() ) + { + idlc()->error()->error3(EIDL_SCOPE_CONFLICT, + pInterface, pForward, scopeAsDecl(pScope)); + } + } + else if ( !pInterface->isPublished() + && pForward->isPublished() ) + { + idlc()->error()->error0(EIDL_PUBLISHED_FORWARD); + } + /* + * All OK, set full definition + */ + else + { + pForward->forwardDefined(*pInterface); + delete pInterface; + pInterface = pForward; + } + } else { + // special handling for XInterface because it is predefined + if ( pForward->isPredefined() && + pForward->getScopedName() == "com::sun::star::uno::XInterface") + { + /* replace the predefined XInterface */ + *pForward = *pInterface; + delete pInterface; + pInterface = pForward; + } + + } + } + } else + { + /* + * Add the interface to its definition scope + */ + pScope->addDeclaration(pInterface); + } + } + /* + * Push it on the scope stack + */ + idlc()->scopes()->push(pInterface); + delete($1); + } + '{' + { + idlc()->setParseState(PS_InterfaceSqSeen); + } + exports + { + AstInterface * ifc = static_cast< AstInterface * >( + idlc()->scopes()->topNonNull()); + if (!ifc->hasMandatoryInheritedInterfaces() + && ifc->getScopedName() != "com::sun::star::uno::XInterface") + { + addInheritedInterface( + ifc, rtl::OString("::com::sun::star::uno::XInterface"), false, + rtl::OUString()); + } + ifc->setDefined(); + idlc()->setParseState(PS_InterfaceBodySeen); + } + '}' + { + idlc()->setParseState(PS_InterfaceQsSeen); + /* + * Done with this interface - pop it off the scopes stack + */ + idlc()->scopes()->pop(); + } + | error '}' + { + yyerror("interface definition"); + yyerrok; + } + ; + +interfaceheader : + interface_decl inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + $$ = new FeInheritanceHeader(NT_interface, $1, $2, 0); + delete $2; + } + ; + +inheritance_spec : + ':' + { + idlc()->setParseState(PS_InheritColonSeen); + } + scoped_name + { + $$ = $3; + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +exports : + exports export + | /* EMPTY */ + ; + +export : + attribute + { + idlc()->setParseState(PS_AttributeDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | operation + { + idlc()->setParseState(PS_OperationDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + | interface_inheritance_decl + { + idlc()->setParseState(PS_InterfaceInheritanceDeclSeen); + } + ';' + { + idlc()->setParseState(PS_NoState); + } + ; + +attribute : + flag_header + simple_type_spec + { + idlc()->setParseState(PS_AttrTypeSeen); + } + simple_declarator + { + idlc()->setParseState(PS_AttrCompleted); + if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) { + idlc()->error()->flagError(EIDL_BAD_ATTRIBUTE_FLAGS, $1); + } + AstInterface * scope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstAttribute * attr = new AstAttribute( + $1, $4->compose($2), $4->getName(), scope); + delete $4; + AstInterface::DoubleMemberDeclarations doubleMembers( + scope->checkMemberClashes(attr)); + if (doubleMembers.empty()) { + scope->addMember(attr); + } else { + reportDoubleMemberDeclarations(doubleMembers); + } + idlc()->scopes()->push(attr); + } + opt_attribute_block + { + static_cast< AstAttribute * >(idlc()->scopes()->top())->setExceptions( + $6.get.documentation, $6.get.exceptions, $6.set.documentation, + $6.set.exceptions); + delete $6.get.documentation; + delete $6.get.exceptions; + delete $6.set.documentation; + delete $6.set.exceptions; + idlc()->scopes()->pop(); + } + ; + +flag_header : + '[' opt_attrflags ']' + { + idlc()->setParseState(PS_FlagHeaderSeen); + $$ = $2; + } + ; + +opt_attrflags : + opt_attrflags ',' opt_attrflag + { + if ( ($1 & $3) == $3 ) + idlc()->error()->flagError(EIDL_DEFINED_ATTRIBUTEFLAG, $3); + + $$ = $1 | $3; + } + | opt_attrflag + { + $$ = $1; + } + ; + +opt_attrflag : + IDL_ATTRIBUTE + { + idlc()->setParseState(PS_AttrSeen); + $$ = AF_ATTRIBUTE; + } + | IDL_PROPERTY + { + idlc()->setParseState(PS_PropertySeen); + $$ = AF_PROPERTY; + } + | IDL_READONLY + { + idlc()->setParseState(PS_ReadOnlySeen); + $$ = AF_READONLY; + } + | IDL_OPTIONAL + { + idlc()->setParseState(PS_OptionalSeen); + $$ = AF_OPTIONAL; + } + | IDL_MAYBEVOID + { + idlc()->setParseState(PS_MayBeVoidSeen); + $$ = AF_MAYBEVOID; + } + | IDL_BOUND + { + idlc()->setParseState(PS_BoundSeen); + $$ = AF_BOUND; + } + | IDL_CONSTRAINED + { + idlc()->setParseState(PS_ConstrainedSeen); + $$ = AF_CONSTRAINED; + } + | IDL_TRANSIENT + { + idlc()->setParseState(PS_TransientSeen); + $$ = AF_TRANSIENT; + } + | IDL_MAYBEAMBIGUOUS + { + idlc()->setParseState(PS_MayBeAmbigiousSeen); + $$ = AF_MAYBEAMBIGUOUS; + } + | IDL_MAYBEDEFAULT + { + idlc()->setParseState(PS_MayBeDefaultSeen); + $$ = AF_MAYBEDEFAULT; + } + | IDL_REMOVEABLE + { + idlc()->setParseState(PS_RemoveableSeen); + $$ = AF_REMOVEABLE; + } + | error ']' + { + yyerror("unknown property|attribute flag"); + yyerrok; + } + ; + +opt_attribute_block: + '{' attribute_block_rest { $$ = $2; } + | /* empty */ + { + $$.get.documentation = 0; + $$.get.exceptions = 0; + $$.set.documentation = 0; + $$.set.exceptions = 0; + } + ; + +attribute_block_rest: + opt_attribute_raises '}' + | error '}' + { + yyerror("bad attribute raises block"); + yyerrok; + $$.get.documentation = 0; + $$.get.exceptions = 0; + $$.set.documentation = 0; + $$.set.exceptions = 0; + } + ; + +opt_attribute_raises: + attribute_get_raises + opt_attribute_set_raises + { + $$.get = $1; + $$.set = $2; + } + | attribute_set_raises + opt_attribute_get_raises + { + $$.get = $2; + $$.set = $1; + } + | /* empty */ + { + $$.get.documentation = 0; + $$.get.exceptions = 0; + $$.set.documentation = 0; + $$.set.exceptions = 0; + } + ; + +opt_attribute_get_raises: + attribute_get_raises + | /* empty */ { $$.documentation = 0; $$.exceptions = 0; } + ; + +attribute_get_raises: + IDL_GET raises ';' + { + $$.documentation = new rtl::OUString( + rtl::OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $2; + } + ; + +opt_attribute_set_raises: + attribute_set_raises + | /* empty */ { $$.documentation = 0; $$.exceptions = 0; } + ; + +attribute_set_raises: + IDL_SET + { + if (static_cast< AstAttribute * >(idlc()->scopes()->top())-> + isReadonly()) + { + idlc()->error()->error0(EIDL_READONLY_ATTRIBUTE_SET_EXCEPTIONS); + } + } + raises ';' + { + $$.documentation = new rtl::OUString( + rtl::OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $3; + } + ; + +operation : + operation_head + op_type_spec + { + idlc()->setParseState(PS_OpTypeSeen); + } + identifier + { + idlc()->setParseState(PS_OpIDSeen); + checkIdentifier($4); + + AstInterface * pScope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstOperation* pOp = NULL; + + /* + * Create a node representing an operation on an interface + * and add it to its enclosing scope + */ + if ( pScope && $2 ) + { + AstType *pType = (AstType*)$2; + if ( !pType || (pType->getNodeType() == NT_exception) ) + { + // type ERROR + } else + { + pOp = new AstOperation($1, pType, *$4, pScope); + + AstInterface::DoubleMemberDeclarations doubleMembers( + pScope->checkMemberClashes(pOp)); + if (doubleMembers.empty()) { + pScope->addMember(pOp); + } else { + reportDoubleMemberDeclarations(doubleMembers); + } + } + } + delete $4; + /* + * Push the operation scope onto the scopes stack + */ + idlc()->scopes()->push(pOp); + } + '(' + { + idlc()->setParseState(PS_OpSqSeen); + } + parameters + { + idlc()->setParseState(PS_OpParsCompleted); + } + ')' + { + idlc()->setParseState(PS_OpQsSeen); + } + opt_raises + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstOperation* pOp = NULL; + /* + * Add exceptions and context to the operation + */ + if ( pScope && pScope->getScopeNodeType() == NT_operation) + { + pOp = (AstOperation*)pScope; + + if ( pOp ) + pOp->setExceptions($12); + } + delete $12; + /* + * Done with this operation. Pop its scope from the scopes stack + */ + idlc()->scopes()->pop(); + } + ; + +operation_head : + '[' + IDL_ONEWAY + { + idlc()->setParseState(PS_OpOnewaySeen); + } + ']' + { + idlc()->setParseState(PS_OpHeadSeen); + $$ = OP_ONEWAY; + } + | /* EMPTY */ + { + $$ = OP_NONE; + } + ; + +op_type_spec : + simple_type_spec + | IDL_VOID + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType(ET_void); + } + ; + +parameters : + parameter + | parameters + ',' + { + idlc()->setParseState(PS_OpParCommaSeen); + } + parameter + | /* EMPTY */ + | error ',' + { + yyerror("parameter definition"); + yyerrok; + } + ; + +parameter : + '[' + direction + ']' + { + idlc()->setParseState(PS_OpParDirSeen); + } + simple_type_spec + { + idlc()->setParseState(PS_OpParTypeSeen); + } + opt_rest + declarator + { + idlc()->setParseState(PS_OpParDeclSeen); + + AstOperation * pScope = static_cast< AstOperation * >( + idlc()->scopes()->top()); + AstParameter* pParam = NULL; + + /* + * Create a node representing an argument to an operation + * Add it to the enclosing scope (the operation scope) + */ + if ( pScope && $5 && $8 ) + { + AstType const * pType = $8->compose($5); + if ( pType ) + { + if (pScope->isConstructor() && $2 != DIR_IN) { + idlc()->error()->error0(EIDL_CONSTRUCTOR_PARAMETER_NOT_IN); + } + if (pScope->isVariadic()) { + idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_LAST); + } + if ($7) { + AstDeclaration const * type = resolveTypedefs(pType); + if (type->getNodeType() != NT_predefined + || (static_cast< AstBaseType const * >(type)-> + getExprType() != ET_any)) + { + idlc()->error()->error0(EIDL_REST_PARAMETER_NOT_ANY); + } + if (pScope->isConstructor()) { + if (pScope->getIteratorBegin() + != pScope->getIteratorEnd()) + { + idlc()->error()->error0( + EIDL_CONSTRUCTOR_REST_PARAMETER_NOT_FIRST); + } + } else { + idlc()->error()->error0(EIDL_METHOD_HAS_REST_PARAMETER); + } + } + + pParam = new AstParameter( + static_cast< Direction >($2), $7, pType, $8->getName(), + pScope); + + if ( !$8->checkType($5) ) + { + // WARNING + } + + pScope->addDeclaration(pParam); + } + } + } + | error + simple_type_spec + { + idlc()->setParseState(PS_NoState); + yyerrok; + } + ; + +direction : + IDL_IN + { + $$ = DIR_IN; + } + | IDL_OUT + { + $$ = DIR_OUT; + } + | IDL_INOUT + { + $$ = DIR_INOUT; + } + ; + +opt_rest: + IDL_ELLIPSIS + { + $$ = true; + } + | /* empty */ + { + $$ = false; + } + ; + +opt_raises: + raises + | /* empty */ + { + $$ = 0; + } + ; + +raises: + IDL_RAISES + { + idlc()->setParseState(PS_RaiseSeen); + } + '(' + { + idlc()->setParseState(PS_RaiseSqSeen); + } + exception_list + ')' + { + idlc()->setParseState(PS_RaiseQsSeen); + $$ = $5; + } + ; + +exception_list: + exception_name + { + $$ = new DeclList; + $$->push_back($1); + } + | exception_list ',' exception_name + { + $1->push_back($3); + $$ = $1; + } + ; + +exception_name: + scoped_name + { + // The topmost scope is either an AstOperation (for interface methods + // and service constructors) or an AstAttribute (for interface + // attributes), so look up exception names in the next-to-topmost scope: + AstDeclaration * decl = idlc()->scopes()->nextToTop()->lookupByName( + *$1); + if (decl == 0) { + idlc()->error()->lookupError(*$1); + } else if (!idlc()->error()->checkPublished(decl)) { + decl = 0; + } else if (decl->getNodeType() != NT_exception) { + idlc()->error()->error1(EIDL_ILLEGAL_RAISES, decl); + decl = 0; + } + delete $1; + $$ = decl; + } + ; + +interface_inheritance_decl: + optional_inherited_interface + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + } + scoped_name + { + AstInterface * ifc = static_cast< AstInterface * >( + idlc()->scopes()->top()); + if (ifc->usesSingleInheritance()) { + idlc()->error()->error0(EIDL_MIXED_INHERITANCE); + } else { + addInheritedInterface( + ifc, *$4, $1, + rtl::OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + } + delete $4; + } + ; + +optional_inherited_interface: + '[' IDL_OPTIONAL ']' { $$ = true; } + | /* EMPTY */ { $$ = false; } + ; + +constants_exports : + constants_export constants_exports + | /* EMPTY */ + ; + +constants_export : + const_dcl + { + idlc()->setParseState(PS_ConstantDeclSeen); + } + ';' {}; + +const_dcl : + IDL_CONST + { + idlc()->setParseState(PS_ConstSeen); + } + const_type + { + idlc()->setParseState(PS_ConstTypeSeen); + } + identifier + { + idlc()->setParseState(PS_ConstIDSeen); + checkIdentifier($5); + } + '=' + { + idlc()->setParseState(PS_ConstAssignSeen); + } + expression + { + idlc()->setParseState(PS_ConstExprSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstConstant* pConstant = NULL; + + if ( $9 && pScope ) + { + if ( !$9->coerce($3) ) + { + idlc()->error()->coercionError($9, $3); + } else + { + pConstant = new AstConstant($3, $9, *$5, pScope); + pScope->addDeclaration(pConstant); + } + } + delete $5; + } + ; + +constants_dcl : + IDL_CONSTANTS + { + idlc()->setParseState(PS_ConstantsSeen); + } + identifier + { + idlc()->setParseState(PS_ConstantsIDSeen); + checkIdentifier($3); + } + '{' + { + idlc()->setParseState(PS_ConstantsSqSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstConstants* pConstants = NULL; + AstDeclaration* pExists = NULL; + + if ( pScope ) + { + pConstants = new AstConstants(*$3, pScope); + if( (pExists = pScope->lookupForAdd(pConstants)) ) + { + pExists->setInMainfile(idlc()->isInMainFile()); + delete(pConstants); + pConstants = (AstConstants*)pExists; + } else + { + pScope->addDeclaration(pConstants); + } + idlc()->scopes()->push(pConstants); + } + delete $3; + } + constants_exports + { + idlc()->setParseState(PS_ConstantsBodySeen); + } + '}' + { + idlc()->setParseState(PS_ConstantsQsSeen); + /* + * Finished with this constants - pop it from the scope stack + */ + idlc()->scopes()->pop(); + } + ; + +expression : const_expr ; + +const_expr : or_expr ; + +or_expr : + xor_expr + | or_expr '|' xor_expr + { + $$ = new AstExpression(EC_or, $1, $3); + } + ; + +xor_expr : + and_expr + | xor_expr '^' and_expr + { + $$ = new AstExpression(EC_xor, $1, $3); + } + ; + +and_expr : + shift_expr + | and_expr '&' shift_expr + { + $$ = new AstExpression(EC_and, $1, $3); + } + ; + +shift_expr : + add_expr + | shift_expr IDL_LEFTSHIFT add_expr + { + $$ = new AstExpression(EC_left, $1, $3); + } + | shift_expr IDL_RIGHTSHIFT add_expr + { + $$ = new AstExpression(EC_right, $1, $3); + } + ; + +add_expr : + mult_expr + | add_expr '+' mult_expr + { + $$ = new AstExpression(EC_add, $1, $3); + } + | add_expr '-' mult_expr + { + $$ = new AstExpression(EC_minus, $1, $3); + } + ; + +mult_expr : + unary_expr + | mult_expr '*' unary_expr + { + $$ = new AstExpression(EC_mul, $1, $3); + } + | mult_expr '/' unary_expr + { + $$ = new AstExpression(EC_div, $1, $3); + } + | mult_expr '%' unary_expr + { + $$ = new AstExpression(EC_mod, $1, $3); + } + ; + +unary_expr : + primary_expr + | '+' primary_expr + { + $$ = new AstExpression(EC_u_plus, $2, NULL); + } + | '-' primary_expr + { + $$ = new AstExpression(EC_u_minus, $2, NULL); + } + | '~' primary_expr + { + } + ; + +primary_expr : + scoped_name + { + /* + * An expression which is a scoped name is not resolved now, + * but only when it is evaluated (such as when it is assigned + * as a constant value) + */ + $$ = new AstExpression($1); + } + | literal + | '(' const_expr ')' + { + $$ = $2; + } + ; + +literal : + IDL_INTEGER_LITERAL + { + $$ = new AstExpression($1); + } + | IDL_INTEGER_ULITERAL + { + $$ = new AstExpression($1); + } + | IDL_FLOATING_PT_LITERAL + { + $$ = new AstExpression($1); + } + | IDL_TRUE + { + $$ = new AstExpression((sal_Int32)1, ET_boolean); + } + | IDL_FALSE + { + $$ = new AstExpression((sal_Int32)0, ET_boolean); + } + ; + +positive_int_expr : + const_expr + { + $1->evaluate(EK_const); + if ( !$1->coerce(ET_ulong) ) + { + idlc()->error()->coercionError($1, ET_ulong); + delete $1; + $$ = NULL; + } + } + ; + +const_type : + integer_type + | char_type + | byte_type + | boolean_type + | floating_pt_type + | scoped_name + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration const * type = 0; + + /* + * If the constant's type is a scoped name, it must resolve + * to a scalar constant type + */ + if ( pScope && (type = pScope->lookupByName(*$1)) ) { + if (!idlc()->error()->checkPublished(type)) + { + type = 0; + } + else + { + type = resolveTypedefs(type); + if (type->getNodeType() == NT_predefined) + { + $$ = static_cast< AstBaseType const * >(type)-> + getExprType(); + } else + $$ = ET_any; + } + } else + $$ = ET_any; + } + ; + +exception_header : + IDL_EXCEPTION + { + idlc()->setParseState(PS_ExceptSeen); + } + identifier + { + idlc()->setParseState(PS_ExceptIDSeen); + checkIdentifier($3); + } + inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + $$ = new FeInheritanceHeader(NT_exception, $3, $5, 0); + delete $5; + } + ; + +exception_dcl : + exception_header + { + idlc()->setParseState(PS_ExceptHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstException* pExcept = NULL; + + if ( pScope ) + { + AstException* pBase = static_cast< AstException* >( + $1->getInherits()); + pExcept = new AstException(*$1->getName(), pBase, pScope); + pScope->addDeclaration(pExcept); + } + /* + * Push the scope of the exception on the scopes stack + */ + idlc()->scopes()->push(pExcept); + delete $1; + } + '{' + { + idlc()->setParseState(PS_ExceptSqSeen); + } + members + { + idlc()->setParseState(PS_ExceptBodySeen); + } + '}' + { + idlc()->setParseState(PS_ExceptQsSeen); + /* this exception is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +property : + flag_header + simple_type_spec + { + idlc()->setParseState(PS_PropertyTypeSeen); + } + at_least_one_declarator + { + idlc()->setParseState(PS_PropertyCompleted); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstAttribute* pAttr = NULL; + FeDeclList* pList = $4; + FeDeclarator* pDecl = NULL; + AstType const * pType = NULL; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + idlc()->error()->error0(EIDL_ILLEGAL_ADD); + } else + { + if ( ($1 & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + idlc()->error()->flagError(EIDL_WRONGATTRIBUTEKEYWORD, AF_ATTRIBUTE); + + if ( ($1 & AF_PROPERTY) != AF_PROPERTY ) + idlc()->error()->flagError(EIDL_MISSINGATTRIBUTEKEYWORD, AF_PROPERTY); + + /* + * Create nodes representing attributes and add them to the + * enclosing scope + */ + if ( pScope && $2 && pList ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + iter++; + continue; + } + + pType = pDecl->compose($2); + + if ( !pType ) + { + iter++; + continue; + } + + pAttr = new AstAttribute(NT_property, $1, pType, pDecl->getName(), pScope); + + pScope->addDeclaration(pAttr); + iter++; + delete pDecl; + } + } + } + + if ( pList ) + delete pList; + } + | error ';' + { + yyerror("property"); + yyerrok; + } + ; + +service_exports : + service_exports service_export + | /* EMPTY */ + ; + +service_export : + service_interface_header + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = NULL; + AstInterfaceMember* pIMember = NULL; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + idlc()->error()->error0(EIDL_ILLEGAL_ADD); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + StringList::iterator iter = $2->begin(); + StringList::iterator end = $2->end(); + + while ( iter != end ) + { + pDecl = pScope->lookupByName(*iter); + if ( pDecl && (pDecl->getNodeType() == NT_interface) ) + { + /* we relax the strict published check and allow to add new + * interfaces if they are optional + */ + bool bOptional = (($1 & AF_OPTIONAL) == AF_OPTIONAL); + if ( idlc()->error()->checkPublished(pDecl, bOptional) ) + { + pIMember = new AstInterfaceMember( + $1, (AstInterface*)pDecl, *iter, pScope); + pScope->addDeclaration(pIMember); + } + } else + { + idlc()->error()-> + lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope)); + } + iter++; + } + } + } + delete $2; + } + | service_service_header + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = NULL; + AstServiceMember* pSMember = NULL; + + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + StringList::iterator iter = $2->begin(); + StringList::iterator end = $2->end(); + + while ( iter != end ) + { + pDecl = pScope->lookupByName(*iter); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + if ( pScope->getScopeNodeType() == NT_singleton && pScope->nMembers() > 0 ) + idlc()->error()->error0(EIDL_ILLEGAL_ADD); + else if ( idlc()->error()->checkPublished(pDecl) ) + { + pSMember = new AstServiceMember( + $1, (AstService*)pDecl, *iter, pScope); + pScope->addDeclaration(pSMember); + } + } else + { + idlc()->error()-> + lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope)); + } + iter++; + } + } + delete $2; + } + | IDL_OBSERVES + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = NULL; + AstObserves* pObserves = NULL; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + idlc()->error()->error0(EIDL_ILLEGAL_ADD); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + StringList::iterator iter = $2->begin(); + StringList::iterator end = $2->end(); + + while ( iter != end ) + { + pDecl = pScope->lookupByName(*iter); + if ( pDecl && (pDecl->getNodeType() == NT_interface) ) + { + pObserves = new AstObserves((AstInterface*)pDecl, *iter, pScope); + pScope->addDeclaration(pObserves); + } else + { + idlc()->error()-> + lookupError(EIDL_INTERFACEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope)); + } + iter++; + } + } + } + delete $2; + } + | IDL_NEEDS + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = NULL; + AstNeeds* pNeeds = NULL; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + idlc()->error()->error0(EIDL_ILLEGAL_ADD); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + StringList::iterator iter = $2->begin(); + StringList::iterator end = $2->end(); + + while ( iter != end ) + { + pDecl = pScope->lookupByName(*iter); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + pNeeds = new AstNeeds((AstService*)pDecl, *iter, pScope); + pScope->addDeclaration(pNeeds); + } else + { + idlc()->error()-> + lookupError(EIDL_SERVICEMEMBER_LOOKUP, *iter, scopeAsDecl(pScope)); + } + iter++; + } + } + } + delete $2; + } + | property + ';' + { + idlc()->setParseState(PS_PropertyDeclSeen); + } + ; + +service_interface_header : + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + $$ = AF_INVALID; + } + | flag_header + IDL_INTERFACE + { + idlc()->setParseState(PS_ServiceIFHeadSeen); + if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) ) + idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1); + $$ = $1; + } + ; + +service_service_header : + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSHeadSeen); + $$ = AF_INVALID; + } + | flag_header + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSHeadSeen); + if ( (AF_OPTIONAL != $1) && ( AF_INVALID != $1) ) + idlc()->error()->flagError(EIDL_OPTIONALEXPECTED, $1); + $$ = $1; + } + ; + +service_dcl : + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSeen); + } + identifier + { + idlc()->setParseState(PS_ServiceIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = NULL; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != NULL) + { + pService = new AstService(*$3, pScope); + pScope->addDeclaration(pService); + } + delete $3; + /* + * Push it on the stack + */ + idlc()->scopes()->push(pService); + } + service_dfn + { + /* this service is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +service_dfn: + service_interface_dfn + | service_obsolete_dfn + ; + +service_interface_dfn: + ':' scoped_name + { + AstScope * scope = idlc()->scopes()->nextToTop(); + // skip the scope pushed by service_dcl + AstDeclaration * decl = scope->lookupByName(*$2); + if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) { + if (idlc()->error()->checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + idlc()->error()->lookupError( + EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope)); + } + delete $2; + } + opt_service_body + { + AstService * s = static_cast< AstService * >(idlc()->scopes()->top()); + if (s != 0) { + s->setDefaultConstructor(!$4); + } + } + ; + +opt_service_body: + service_body { $$ = true; } + | /* empty */ { $$ = false; } + ; + +service_body: + '{' + constructors + '}' + ; + +constructors: + constructors constructor + | /* empty */ + ; + +constructor: + identifier + { + checkIdentifier($1); + AstScope * scope = idlc()->scopes()->top(); + AstOperation * ctor = new AstOperation(OP_NONE, 0, *$1, scope); + delete $1; + scope->addDeclaration(ctor); + idlc()->scopes()->push(ctor); + } + '(' + parameters + ')' + opt_raises + { + static_cast< AstOperation * >(idlc()->scopes()->top())->setExceptions( + $6); + delete $6; + idlc()->scopes()->pop(); + if (static_cast< AstService * >(idlc()->scopes()->top())-> + checkLastConstructor()) + { + idlc()->error()->error0(EIDL_SIMILAR_CONSTRUCTORS); + } + } + ';' + ; + +singleton_dcl : + IDL_SINGLETON + { + idlc()->setParseState(PS_SingletonSeen); + } + identifier + { + idlc()->setParseState(PS_SingletonIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = NULL; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != NULL) + { + pService = new AstService(NT_singleton, *$3, pScope); + pScope->addDeclaration(pService); + } + delete $3; + /* + * Push it on the stack + */ + idlc()->scopes()->push(pService); + } + singleton_dfn + { + /* this singelton is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +singleton_dfn: + singleton_interface_dfn + | service_obsolete_dfn + ; + +singleton_interface_dfn: + ':' scoped_name + { + AstScope * scope = idlc()->scopes()->nextToTop(); + // skip the scope (needlessly) pushed by singleton_dcl + AstDeclaration * decl = scope->lookupByName(*$2); + if (decl != 0 && resolveTypedefs(decl)->getNodeType() == NT_interface) { + if (idlc()->error()->checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + idlc()->error()->lookupError( + EIDL_INTERFACEMEMBER_LOOKUP, *$2, scopeAsDecl(scope)); + } + delete $2; + } + ; + +service_obsolete_dfn: + '{' + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceSqSeen : PS_SingletonSqSeen); + } + service_exports + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceBodySeen : PS_SingletonBodySeen); + } + '}' + { + idlc()->setParseState( + idlc()->scopes()->top()->getScopeNodeType() == NT_service + ? PS_ServiceQsSeen : PS_SingletonQsSeen); + } + ; + +type_dcl : + IDL_TYPEDEF + { + idlc()->setParseState(PS_TypedefSeen); + } + type_declarator {} + | struct_type {} + | union_type {} + | enum_type {} + ; + +type_declarator : + type_spec + { + idlc()->setParseState(PS_TypeSpecSeen); + if ($1 != 0 && $1->getNodeType() == NT_instantiated_struct) { + idlc()->error()->error0(EIDL_INSTANTIATED_STRUCT_TYPE_TYPEDEF); + } + } + at_least_one_declarator + { + idlc()->setParseState(PS_DeclaratorsSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstTypeDef* pTypeDef = NULL; + FeDeclList* pList = $3; + FeDeclarator* pDecl = NULL; + AstType const * pType = NULL; + + /* + * Create nodes representing typedefs and add them to the + * enclosing scope + */ + if ( pScope && $1 && pList ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + iter++; + continue; + } + + pType = pDecl->compose($1); + + if ( !pType ) + { + iter++; + continue; + } + + pTypeDef = new AstTypeDef(pType, pDecl->getName(), pScope); + + pScope->addDeclaration(pTypeDef); + iter++; + delete pDecl; + } + delete pList; + } + } + ; + +at_least_one_declarator : + declarator declarators + { + if ( $2 ) + { + $2->push_back($1); + $$ = $2; + } else + { + FeDeclList* pList = new FeDeclList(); + pList->push_back($1); + $$ = pList; + } + } + ; + +declarators : + declarators + ',' + { + idlc()->setParseState(PS_DeclsCommaSeen); + } + declarator + { + idlc()->setParseState(PS_DeclsDeclSeen); + if ( $1 ) + { + $1->push_back($4); + $$ = $1; + } else + { + FeDeclList* pList = new FeDeclList(); + pList->push_back($4); + $$ = pList; + } + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +declarator : + simple_declarator + | complex_declarator + ; + +simple_declarator : + identifier + { + // For historic reasons, the struct com.sun.star.uno.Uik contains + // members with illegal names (of the form "m_DataN"); avoid useless + // warnings about them: + AstScope * scope = idlc()->scopes()->top(); + if (scope == 0 || scope->getScopeNodeType() != NT_struct + || (scopeAsDecl(scope)->getScopedName() + != "com::sun::star::uno::Uik")) + { + checkIdentifier($1); + } + + $$ = new FeDeclarator(*$1, FeDeclarator::FD_simple, NULL); + delete $1; + } + ; + +complex_declarator : + array_declarator + { + $$ = new FeDeclarator($1->getLocalName(), FeDeclarator::FD_complex, $1); + } + ; + +array_declarator : + identifier + { + idlc()->setParseState(PS_ArrayIDSeen); + checkIdentifier($1); + } + at_least_one_array_dim + { + idlc()->setParseState(PS_ArrayCompleted); + $$ = new AstArray(*$1, NULL, *$3, idlc()->scopes()->bottom()); + delete $1; + } + ; + +at_least_one_array_dim : + array_dim array_dims + { + if( $2 ) + { + $2->push_front($1); + $$ = $2; + } else + { + ExprList* pList = new ExprList(); + pList->push_back($1); + $$ = pList; + } + } + ; + +array_dims : + array_dims array_dim + { + if( $1 ) + { + $1->push_back($2); + $$ = $1; + } else + { + ExprList* pList = new ExprList(); + pList->push_back($2); + $$ = pList; + } + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +array_dim : + '[' + { + idlc()->setParseState(PS_DimSqSeen); + } + positive_int_expr + { + idlc()->setParseState(PS_DimExprSeen); + } + ']' + { + idlc()->setParseState(PS_DimQsSeen); + /* + * Array dimensions are expressions which must be coerced to + * positive integers + */ + if ( !$3 || !$3->coerce(ET_uhyper) ) + { + idlc()->error()->coercionError($3, ET_uhyper); + $$ = NULL; + } else + $$ = $3; + } + ; + +at_least_one_scoped_name : + scoped_name scoped_names + { + if ($2) + { + $2->push_front(*$1); + $$ = $2; + } else + { + StringList* pNames = new StringList(); + pNames->push_back(*$1); + $$ = pNames; + } + delete($1); + } + ; + +scoped_names : + scoped_names + ',' + { + idlc()->setParseState(PS_SNListCommaSeen); + } + scoped_name + { + idlc()->setParseState(PS_ScopedNameSeen); + if ($1) + { + $1->push_back(*$4); + $$ = $1; + } else + { + StringList* pNames = new StringList(); + pNames->push_back(*$4); + $$ = pNames; + } + delete($4); + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +scoped_name : + identifier + { + idlc()->setParseState(PS_SN_IDSeen); + checkIdentifier($1); + $$ = $1; + } + | IDL_SCOPESEPARATOR + { + idlc()->setParseState(PS_ScopeDelimSeen); + } + identifier + { + checkIdentifier($3); + OString* pName = new OString("::"); + *pName += *$3; + delete $3; + $$ = pName; + } + | scoped_name + IDL_SCOPESEPARATOR + { + } + identifier + { + checkIdentifier($4); + *$1 += ::rtl::OString("::"); + *$1 += *$4; + delete $4; + $$ = $1; + } + ; + +type_spec : + simple_type_spec + | constructed_type_spec + ; + +simple_type_spec : + fundamental_type + | scoped_name opt_type_args + { + $$ = createNamedType($1, $2); + } + ; + +fundamental_type: + base_type_spec + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1); + } + | template_type_spec + ; + +opt_type_args: + '<' type_args '>' { $$ = $2; } + | /* empty */ { $$ = 0; } + ; + +type_args: + type_arg + { + $$ = new DeclList; + $$->push_back(const_cast< AstDeclaration * >($1)); //TODO: const_cast + } + | type_args ',' type_arg + { + $1->push_back(const_cast< AstDeclaration * >($3)); //TODO: const_cast + $$ = $1; + } + ; + +type_arg: + simple_type_spec + { + if ($1 != 0 && static_cast< AstType const * >($1)->isUnsigned()) { + idlc()->error()->error0(EIDL_UNSIGNED_TYPE_ARGUMENT); + } + $$ = $1; + } + ; + +base_type_spec : + integer_type + | floating_pt_type + | char_type + | boolean_type + | byte_type + | any_type + | type_type + | string_type + ; + +integer_type : + signed_int + | unsigned_int + ; + +signed_int : + IDL_LONG + { + $$ = ET_long; + } + | IDL_HYPER + { + $$ = ET_hyper; + } + | IDL_SHORT + { + $$ = ET_short; + } + ; + +unsigned_int : + IDL_UNSIGNED IDL_LONG + { + $$ = ET_ulong; + } + | IDL_UNSIGNED IDL_HYPER + { + $$ = ET_uhyper; + } + | IDL_UNSIGNED IDL_SHORT + { + $$ = ET_ushort; + } + ; + +floating_pt_type : + IDL_DOUBLE + { + $$ = ET_double; + } + | IDL_FLOAT + { + $$ = ET_float; + } + ; + +char_type : + IDL_CHAR + { + $$ = ET_char; + } + ; + +byte_type : + IDL_BYTE + { + $$ = ET_byte; + } + ; + +boolean_type : + IDL_BOOLEAN + { + $$ = ET_boolean; + } + ; + +any_type : + IDL_ANY + { + $$ = ET_any; + } + ; + +type_type : + IDL_TYPE + { + $$ = ET_type; + } + ; + +string_type : + IDL_STRING + { + $$ = ET_string; + } + ; + +template_type_spec : + sequence_type_spec + | array_type + ; + +constructed_type_spec : + struct_type + | union_type + | enum_type + ; + +array_type : + simple_type_spec + { + idlc()->setParseState(PS_ArrayTypeSeen); + } + at_least_one_array_dim + { + idlc()->setParseState(PS_ArrayCompleted); + + AstScope* pScope = idlc()->scopes()->bottom(); + AstDeclaration* pDecl = NULL; + AstDeclaration* pArray = NULL; + + if ( $1 ) + { + pArray = new AstArray((AstType*)$1, *$3, idlc()->scopes()->bottom()); + if ( pScope ) + { + pDecl = pScope->addDeclaration(pArray); + if ( pArray != pDecl ) + { + // if array type already defined then use it + delete pArray; + pArray = pDecl; + } + } + } + $$ = pArray; + } + ; + +sequence_type_spec : + IDL_SEQUENCE + { + idlc()->setParseState(PS_SequenceSeen); + /* + * Push a sequence marker on scopes stack + */ + idlc()->scopes()->push(NULL); + } + '<' + { + idlc()->setParseState(PS_SequenceSqSeen); + } + simple_type_spec + { + idlc()->setParseState(PS_SequenceTypeSeen); + } + '>' + { + idlc()->setParseState(PS_SequenceQsSeen); + /* + * Remove sequence marker from scopes stack + */ + if (idlc()->scopes()->top() == NULL) + idlc()->scopes()->pop(); + /* + * Create a node representing a sequence + */ + AstScope* pScope = idlc()->scopes()->bottom(); + AstDeclaration* pDecl = NULL; + AstDeclaration* pSeq = NULL; + + if ( $5 ) + { + AstType *pType = (AstType*)$5; + if ( pType ) + { + pSeq = new AstSequence(pType, pScope); + /* + * Add this AstSequence to the types defined in the global scope + */ + pDecl = pScope->addDeclaration(pSeq); + if ( pSeq != pDecl ) + { + // if sequence type already defined then use it + delete pSeq; + pSeq = pDecl; + } + } + } + $$ = pSeq; + } + | error '>' + { + yyerror("sequence declaration"); + yyerrok; + $$ = 0; + } + ; + +struct_type : + structure_header + { + idlc()->setParseState(PS_StructHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstStruct* pStruct = NULL; + + if ( pScope ) + { + AstStruct* pBase= static_cast< AstStruct* >($1->getInherits()); + pStruct = new AstStruct( + *$1->getName(), $1->getTypeParameters(), pBase, pScope); + pScope->addDeclaration(pStruct); + } + /* + * Push the scope of the struct on the scopes stack + */ + idlc()->scopes()->push(pStruct); + delete $1; + } + '{' + { + idlc()->setParseState(PS_StructSqSeen); + } + at_least_one_member + { + idlc()->setParseState(PS_StructBodySeen); + } + '}' + { + idlc()->setParseState(PS_StructQsSeen); + /* this exception is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +structure_header : + IDL_STRUCT + { + idlc()->setParseState(PS_StructSeen); + } + identifier + { + idlc()->setParseState(PS_StructIDSeen); + checkIdentifier($3); + } + opt_type_params + inheritance_spec + { + idlc()->setParseState(PS_InheritSpecSeen); + + // Polymorphic struct type templates with base types would cause various + // problems in language bindings, so forbid them here. For example, + // GCC prior to version 3.4 fails with code like + // + // struct Base { ... }; + // template< typename typeparam_T > struct Derived: public Base { + // int member1 CPPU_GCC3_ALIGN(Base); + // ... }; + // + // (Note that plain struct types with instantiated polymorphic struct + // type bases, which might also cause problems in language bindings, are + // already rejected on a syntactic level.) + if ($5 != 0 && $6 != 0) { + idlc()->error()->error0(EIDL_STRUCT_TYPE_TEMPLATE_WITH_BASE); + } + + $$ = new FeInheritanceHeader(NT_struct, $3, $6, $5); + delete $5; + delete $6; + } + ; + +opt_type_params: + '<' type_params '>' { $$ = $2; } + | /* empty */ { $$ = 0; } + ; + +type_params: + identifier + { + $$ = new std::vector< rtl::OString >; + $$->push_back(*$1); + delete $1; + } + | type_params ',' identifier + { + if (std::find($1->begin(), $1->end(), *$3) != $1->end()) { + idlc()->error()->error0(EIDL_IDENTICAL_TYPE_PARAMETERS); + } + $1->push_back(*$3); + delete $3; + $$ = $1; + } + ; + +at_least_one_member : member members ; + +members : + members member + | /* EMPTY */ + ; + +member : + type_or_parameter + { + idlc()->setParseState(PS_MemberTypeSeen); + } + at_least_one_declarator + { + idlc()->setParseState(PS_MemberDeclsSeen); + } + ';' + { + idlc()->setParseState(PS_MemberDeclsCompleted); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstMember* pMember = NULL; + FeDeclList* pList = $3; + FeDeclarator* pDecl = NULL; + AstType const * pType = NULL; + + // !!! check recursive type + + if ( pScope && pList && $1 ) + { + FeDeclList::iterator iter = pList->begin(); + FeDeclList::iterator end = pList->end(); + while (iter != end) + { + pDecl = (*iter); + if ( !pDecl ) + { + iter++; + continue; + } + + pType = pDecl->compose($1); + + if ( !pType ) + { + iter++; + continue; + } + + pMember = new AstMember(pType, pDecl->getName(), pScope); + + if ( !pDecl->checkType($1) ) + { + // WARNING + } + + pScope->addDeclaration(pMember); + iter++; + delete pDecl; + } + delete pList; + } + } + | error ';' + { + yyerror("member definition"); + yyerrok; + } + ; + +type_or_parameter: + fundamental_type + | scoped_name opt_type_args + { + AstDeclaration const * decl = 0; + AstStruct * scope = static_cast< AstStruct * >(idlc()->scopes()->top()); + if (scope != 0 && $2 == 0) { + decl = scope->findTypeParameter(*$1); + } + if (decl != 0) { + delete $1; + delete $2; + } else { + decl = createNamedType($1, $2); + if (scope != 0 && includes(decl, scopeAsDecl(scope))) { + idlc()->error()->error1( + EIDL_RECURSIVE_TYPE, scopeAsDecl(scope)); + decl = 0; + } + } + $$ = decl; + } + ; + +enum_type : + IDL_ENUM + { + idlc()->setParseState(PS_EnumSeen); + } + identifier + { + idlc()->setParseState(PS_EnumIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = NULL; + + /* + * Create a node representing an enum and add it to its + * enclosing scope + */ + if (pScope != NULL) + { + pEnum = new AstEnum(*$3, pScope); + /* + * Add it to its defining scope + */ + pScope->addDeclaration(pEnum); + } + delete $3; + /* + * Push the enum scope on the scopes stack + */ + idlc()->scopes()->push(pEnum); + + } + '{' + { + idlc()->setParseState(PS_EnumSqSeen); + } + at_least_one_enumerator + { + idlc()->setParseState(PS_EnumBodySeen); + } + '}' + { + idlc()->setParseState(PS_EnumQsSeen); + /* + * Done with this enum. Pop its scope from the scopes stack + */ + if (idlc()->scopes()->top() == NULL) + $$ = NULL; + else + { + $$ = (AstEnum*)idlc()->scopes()->topNonNull(); + idlc()->scopes()->pop(); + } + } + ; + +at_least_one_enumerator : enumerator enumerators ; + +enumerators : + enumerators + ',' + { + idlc()->setParseState(PS_EnumCommaSeen); + } + enumerator + | /* EMPTY */ + | error ',' + { + yyerror("enumerator definition"); + yyerrok; + } + ; + +enumerator : + identifier + { + checkIdentifier($1); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = NULL; + AstConstant* pEnumVal = NULL; + + if ( pScope && pScope->getScopeNodeType() == NT_enum) + { + pEnum = (AstEnum*)pScope; + if (pEnum && $1) + { + AstExpression* pExpr = new AstExpression(pEnum->getEnumValueCount()); + pEnumVal = new AstConstant(ET_long , NT_enum_val, + pExpr, *$1, pScope); + } + if ( pEnum->checkValue(pEnumVal->getConstValue()) ) + idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum); + + pScope->addDeclaration(pEnumVal); + } + delete $1; + } + | identifier + '=' + const_expr + { + checkIdentifier($1); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = NULL; + AstConstant* pEnumVal = NULL; + + if ( $3 && pScope && pScope->getScopeNodeType() == NT_enum) + { + $3->evaluate(EK_const); + if ( $3->coerce(ET_long) ) + { + pEnum = (AstEnum*)pScope; + if (pEnum) + { + pEnumVal = new AstConstant(ET_long , NT_enum_val, + $3, *$1, pScope); + } + if ( pEnum->checkValue(pEnumVal->getConstValue()) ) + idlc()->error()->error1(EIDL_EVAL_ERROR, pEnum); + + pScope->addDeclaration(pEnumVal); + } else + { + idlc()->error()->coercionError($3, ET_long); + delete $3; + } + } + delete $1; + } + ; + +union_type : + IDL_UNION + { + idlc()->setParseState(PS_UnionSeen); + } + identifier + { + idlc()->setParseState(PS_UnionIDSeen); + checkIdentifier($3); + } + IDL_SWITCH + { + idlc()->setParseState(PS_SwitchSeen); + } + '(' + { + idlc()->setParseState(PS_SwitchOpenParSeen); + } + switch_type_spec + { + idlc()->setParseState(PS_SwitchTypeSeen); + } + ')' + { + idlc()->setParseState(PS_SwitchCloseParSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstUnion* pUnion = NULL; + + /* + * Create a node representing a union. Add it to its enclosing + * scope + */ + if ( $9 && pScope ) + { + AstType* pType = (AstType*)$9; + if ( !pType) + { + idlc()->error()->noTypeError($9); + } else + { + pUnion = new AstUnion(*$3, pType, pScope); + pScope->addDeclaration(pUnion); + } + } + delete $3; + /* + * Push the scope of the union on the scopes stack + */ + idlc()->scopes()->push(pUnion); + } + '{' + { + idlc()->setParseState(PS_UnionSqSeen); + } + at_least_one_case_branch + { + idlc()->setParseState(PS_UnionBodySeen); + } + '}' + { + idlc()->setParseState(PS_UnionQsSeen); + /* this union is finished, pop its scope from the stack */ + idlc()->scopes()->pop(); + } + ; + +switch_type_spec : + integer_type + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1); + } + | char_type + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1); + } + | boolean_type + { + $$ = idlc()->scopes()->bottom()->lookupPrimitiveType($1); + } + | enum_type + | scoped_name + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstBaseType* pBaseType = NULL; + AstDeclaration const * pDecl = NULL; + AstTypeDef* pTypeDef = NULL; + sal_Bool bFound = sal_False; + /* + * If the constant's type is a scoped name, it must resolve + * to a scalar constant type + */ + if ( pScope && (pDecl = pScope->lookupByName(*$1)) ) + { + /* + * Look through typedefs + */ + while ( !bFound ) + { + switch (pDecl->getNodeType()) + { + case NT_enum: + $$ = pDecl; + bFound = sal_True; + break; + case NT_predefined: + pBaseType = (AstBaseType*)pDecl; + if ( pBaseType ) + { + switch (pBaseType->getExprType()) + { + case ET_short: + case ET_ushort: + case ET_long: + case ET_ulong: + case ET_hyper: + case ET_uhyper: + case ET_char: + case ET_byte: + case ET_boolean: + $$ = pBaseType; + bFound = sal_True; + break; + default: + $$ = NULL; + bFound = sal_True; + break; + } + } + break; + case NT_typedef: + pTypeDef = (AstTypeDef*)pDecl; + if ( pTypeDef ) + pDecl = pTypeDef->getBaseType(); + break; + default: + $$ = NULL; + bFound = sal_True; + break; + } + } + } else + $$ = NULL; + + if ($$ == NULL) + idlc()->error()->lookupError(*$1); + } + ; + +at_least_one_case_branch : case_branch case_branches ; + +case_branches : + case_branches case_branch + | /* EMPTY */ + ; + +case_branch : + at_least_one_case_label + { + idlc()->setParseState(PS_UnionLabelSeen); + } + element_spec + { + idlc()->setParseState(PS_UnionElemSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstUnionLabel* pLabel = NULL; + AstUnionBranch* pBranch = NULL; + AstMember* pMember = $3; + + /* + * Create several nodes representing branches of a union. + * Add them to the enclosing scope (the union scope) + */ + if ( pScope && $1 && $3 ) + { + LabelList::iterator iter = $1->begin(); + LabelList::iterator end = $1->end(); + for (;iter != end; iter++) + { + pLabel = *iter; + if ( !pLabel ) + { + iter++; + continue; + } + pBranch = new AstUnionBranch(pLabel, pMember->getType(), + pMember->getLocalName(), pScope); + pScope->addDeclaration(pBranch); + } + } + if ( $1 ) delete($1); + } + ; + +at_least_one_case_label : + case_label case_labels + { + if ( $2 ) + { + $2->push_front($1); + $$ = $2; + } else + { + LabelList* pLabels = new LabelList(); + pLabels->push_back($1); + $$ = pLabels; + } + } + ; + +case_labels : + case_labels case_label + { + if ( $1 ) + { + $1->push_back($2); + $$ = $1; + } else + { + LabelList* pLabels = new LabelList(); + pLabels->push_back($2); + $$ = pLabels; + } + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +case_label : + IDL_DEFAULT + { + idlc()->setParseState(PS_DefaultSeen); + } + ':' + { + idlc()->setParseState(PS_LabelColonSeen); + $$ = new AstUnionLabel(UL_default, NULL); + } + | IDL_CASE + { + idlc()->setParseState(PS_CaseSeen); + } + const_expr + { + idlc()->setParseState(PS_LabelExprSeen); + } + ':' + { + idlc()->setParseState(PS_LabelColonSeen); + $$ = new AstUnionLabel(UL_label, $3); + } + ; + +element_spec : + type_spec + { + idlc()->setParseState(PS_UnionElemTypeSeen); + } + declarator + { + idlc()->setParseState(PS_UnionElemDeclSeen); + } + ';' + { + idlc()->setParseState(PS_UnionElemCompleted); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + /* + * Check for illegal recursive use of type + */ +// if ( $1 && AST_illegal_recursive_type($1)) +// idlc()->error()->error1(EIDL_RECURSIVE_TYPE, $1); + /* + * Create a field in a union branch + */ + if ( $1 && $3 ) + { + AstType const * pType = $3->compose($1); + if ( !pType ) + $$ = NULL; + else + $$ = new AstMember(pType, $3->getName(), pScope); + } else + $$ = NULL; + + if ( $3 ) delete $3; + } + | error + ';' + { + $$ = NULL; + } + ; + +identifier: + IDL_IDENTIFIER + | IDL_GET { $$ = new OString("get"); } + | IDL_SET { $$ = new OString("set"); } + | IDL_PUBLISHED { $$ = new OString("published"); } + ; + +%% + +/* + * Report an error situation discovered in a production + */ +void yyerror(char const *errmsg) +{ + idlc()->error()->syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg); + idlc()->setParseState(PS_NoState); +} diff --git a/idlc/source/preproc/cpp.c b/idlc/source/preproc/cpp.c new file mode 100644 index 000000000000..59e0b615cae9 --- /dev/null +++ b/idlc/source/preproc/cpp.c @@ -0,0 +1,498 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <stdarg.h> +#include "cpp.h" + +#define OUTS 16384 +char outbuf[OUTS]; +char *outptr = outbuf; +Source *cursource; +int nerrs; +struct token nltoken = {NL, 0, 0, 1, (uchar *) "\n"}; +char *curtime; +int incdepth; +int ifdepth; +int ifsatisfied[NIF]; +int skipping; + +char rcsid[] = "$Version 1.2 $ $Revision: 1.10 $ $Date: 2008-07-11 14:50:24 $"; + +int realargc; +char* realargv[512]; + +void checkCommandFile(char* cmdfile) +{ + FILE *commandfile; + char option[256]; + + commandfile = fopen(cmdfile+1, "r"); + if( commandfile == NULL ) + { + error(FATAL, "Can't open command file %s", cmdfile); + } else + { + int i=0; + int found = 0; + char c; + while ( fscanf(commandfile, "%c", &c) != EOF ) + { + if (c=='\"') { + if (found) { + found=0; + } else { + found=1; + continue; + } + } else { + if (c!=13 && c!=10) { + if (found || c!=' ') { + option[i++]=c; + continue; + } + } + if (i==0) + continue; + } + option[i]='\0'; + found=0; + i=0; + if (option[0]== '@' || option[1]== '@') + { + checkCommandFile(option); + } else + { + realargv[realargc]= strdup(option); + realargc++; + option[0]='\0'; + } + } + if (option[0] != '\0') { + option[i]='\0'; + realargv[realargc]= strdup(option); + realargc++; + } + fclose(commandfile); + } +} + +void checkCommandArgs(int argc, char **argv) +{ + int i; + + for (i=0; i<argc; i++) + { + if (argv[i][0]== '@') + { + checkCommandFile(argv[i]); + } else + { + realargv[i]= strdup(argv[i]); + realargc++; + } + } +} + +void cleanCommandArgs() +{ + int i; + + for (i=0; i<realargc; i++) + { + free(realargv[i]); + } +} + +#ifdef WNT +int __cdecl main(int argc, char **argv) +#else +int main(int argc, char **argv) +#endif +{ + Tokenrow tr; + time_t t; + char ebuf[BUFSIZ]; + + checkCommandArgs(argc, argv); + + setbuf(stderr, ebuf); + t = time(NULL); + curtime = ctime(&t); + maketokenrow(3, &tr); + expandlex(); + setup(realargc, realargv); + if (!Pflag) + genline(); + process(&tr); + flushout(); + fflush(stderr); + cleanCommandArgs(); + exit(nerrs); + //return nerrs; +} + +void + process(Tokenrow * trp) +{ + int anymacros = 0; + + for (;;) + { + if (trp->tp >= trp->lp) + { + trp->tp = trp->lp = trp->bp; + outptr = outbuf; + anymacros |= gettokens(trp, 1); + trp->tp = trp->bp; + } + if (trp->tp->type == END) + { + if (--incdepth >= 0) + { + if (cursource->ifdepth) + error(ERROR, + "Unterminated conditional in #include"); + unsetsource(); + cursource->line += cursource->lineinc; + trp->tp = trp->lp; + if (!Pflag) + genline(); + continue; + } + if (ifdepth) + error(ERROR, "Unterminated #if/#ifdef/#ifndef"); + break; + } + if (trp->tp->type == SHARP) + { + trp->tp += 1; + control(trp); + } + else + if (!skipping && anymacros) + expandrow(trp, NULL); + if (skipping) + setempty(trp); + puttokens(trp); + anymacros = 0; + cursource->line += cursource->lineinc; + if (cursource->lineinc > 1) + { + if (!Pflag) + genline(); + } + } +} + +void + control(Tokenrow * trp) +{ + Nlist *np; + Token *tp; + + tp = trp->tp; + if (tp->type != NAME) + { + if (tp->type == NUMBER) + goto kline; + if (tp->type != NL) + error(ERROR, "Unidentifiable control line"); + return; /* else empty line */ + } + if ((np = lookup(tp, 0)) == NULL || ((np->flag & ISKW) == 0 && !skipping)) + { + error(WARNING, "Unknown preprocessor control %t", tp); + return; + } + if (skipping) + { + switch (np->val) + { + case KENDIF: + if (--ifdepth < skipping) + skipping = 0; + --cursource->ifdepth; + setempty(trp); + return; + + case KIFDEF: + case KIFNDEF: + case KIF: + if (++ifdepth >= NIF) + error(FATAL, "#if too deeply nested"); + ++cursource->ifdepth; + return; + + case KELIF: + case KELSE: + if (ifdepth <= skipping) + break; + return; + + default: + return; + } + } + switch (np->val) + { + case KDEFINE: + dodefine(trp); + break; + + case KUNDEF: + tp += 1; + if (tp->type != NAME || trp->lp - trp->bp != 4) + { + error(ERROR, "Syntax error in #undef"); + break; + } + if ((np = lookup(tp, 0)) != NULL) + { + np->flag &= ~ISDEFINED; + + if (Mflag) + { + if (np->ap) + error(INFO, "Macro deletion of %s(%r)", np->name, np->ap); + else + error(INFO, "Macro deletion of %s", np->name); + } + } + break; + + case KPRAGMA: + case KIDENT: + for (tp = trp->tp - 1; ((tp->type != NL) && (tp < trp->lp)); tp++) + tp->type = UNCLASS; + return; + + case KIFDEF: + case KIFNDEF: + case KIF: + if (++ifdepth >= NIF) + error(FATAL, "#if too deeply nested"); + ++cursource->ifdepth; + ifsatisfied[ifdepth] = 0; + if (eval(trp, np->val)) + ifsatisfied[ifdepth] = 1; + else + skipping = ifdepth; + break; + + case KELIF: + if (ifdepth == 0) + { + error(ERROR, "#elif with no #if"); + return; + } + if (ifsatisfied[ifdepth] == 2) + error(ERROR, "#elif after #else"); + if (eval(trp, np->val)) + { + if (ifsatisfied[ifdepth]) + skipping = ifdepth; + else + { + skipping = 0; + ifsatisfied[ifdepth] = 1; + } + } + else + skipping = ifdepth; + break; + + case KELSE: + if (ifdepth == 0 || cursource->ifdepth == 0) + { + error(ERROR, "#else with no #if"); + return; + } + if (ifsatisfied[ifdepth] == 2) + error(ERROR, "#else after #else"); + if (trp->lp - trp->bp != 3) + error(ERROR, "Syntax error in #else"); + skipping = ifsatisfied[ifdepth] ? ifdepth : 0; + ifsatisfied[ifdepth] = 2; + break; + + case KENDIF: + if (ifdepth == 0 || cursource->ifdepth == 0) + { + error(ERROR, "#endif with no #if"); + return; + } + --ifdepth; + --cursource->ifdepth; + if (trp->lp - trp->bp != 3) + error(WARNING, "Syntax error in #endif"); + break; + + case KERROR: + trp->tp = tp + 1; + error(WARNING, "#error directive: %r", trp); + break; + + case KLINE: + trp->tp = tp + 1; + expandrow(trp, "<line>"); + tp = trp->bp + 2; + kline: + if (tp + 1 >= trp->lp || tp->type != NUMBER || tp + 3 < trp->lp + || (tp + 3 == trp->lp + && ((tp + 1)->type != STRING || *(tp + 1)->t == 'L'))) + { + error(ERROR, "Syntax error in #line"); + return; + } + cursource->line = atol((char *) tp->t) - 1; + if (cursource->line < 0 || cursource->line >= 32768) + error(WARNING, "#line specifies number out of range"); + tp = tp + 1; + if (tp + 1 < trp->lp) + cursource->filename = (char *) newstring(tp->t + 1, tp->len - 2, 0); + return; + + case KDEFINED: + error(ERROR, "Bad syntax for control line"); + break; + + case KIMPORT: + doinclude(trp, -1, 1); + trp->lp = trp->bp; + return; + + case KINCLUDE: + doinclude(trp, -1, 0); + trp->lp = trp->bp; + return; + + case KINCLUDENEXT: + doinclude(trp, cursource->pathdepth, 0); + trp->lp = trp->bp; + return; + + case KEVAL: + eval(trp, np->val); + break; + + default: + error(ERROR, "Preprocessor control `%t' not yet implemented", tp); + break; + } + setempty(trp); + return; +} + +void * + domalloc(int size) +{ + void *p = malloc(size); + + if (p == NULL) + error(FATAL, "Out of memory from malloc"); + return p; +} + +void + dofree(void *p) +{ + free(p); +} + +void + error(enum errtype type, char *string,...) +{ + va_list ap; + char c, *cp, *ep; + Token *tp; + Tokenrow *trp; + Source *s; + int i; + + fprintf(stderr, "cpp: "); + for (s = cursource; s; s = s->next) + if (*s->filename) + fprintf(stderr, "%s:%d ", s->filename, s->line); + va_start(ap, string); + for (ep = string; *ep; ep++) + { + if (*ep == '%') + { + switch (*++ep) + { + + case 'c': + /* need a cast here since va_arg only + takes fully promoted types */ + c = (char) va_arg(ap, int); + fprintf(stderr, "%c", c); + break; + + case 's': + cp = va_arg(ap, char *); + fprintf(stderr, "%s", cp); + break; + + case 'd': + i = va_arg(ap, int); + fprintf(stderr, "%d", i); + break; + + case 't': + tp = va_arg(ap, Token *); + fprintf(stderr, "%.*s", tp->len, tp->t); + break; + + case 'r': + trp = va_arg(ap, Tokenrow *); + for (tp = trp->tp; tp < trp->lp && tp->type != NL; tp++) + { + if (tp > trp->tp && tp->wslen) + fputc(' ', stderr); + fprintf(stderr, "%.*s", tp->len, tp->t); + } + break; + + default: + fputc(*ep, stderr); + break; + } + } + else + fputc(*ep, stderr); + } + va_end(ap); + fputc('\n', stderr); + if (type == FATAL) + exit(-1); + if (type != WARNING) + nerrs += 1; + fflush(stderr); +} diff --git a/idlc/source/preproc/cpp.h b/idlc/source/preproc/cpp.h new file mode 100644 index 000000000000..4b8645b2d34e --- /dev/null +++ b/idlc/source/preproc/cpp.h @@ -0,0 +1,213 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#define INS 32768 /* input buffer */ +#define OBS 8092 /* outbut buffer */ +#define NARG 32 /* Max number arguments to a macro */ +#define NINCLUDE 32 /* Max number of include directories (-I) */ +#define NIF 64 /* depth of nesting of #if */ +#define NINC 32 /* depth of nesting of #include */ + +#ifndef EOF +#define EOF (-1) +#endif + +#ifndef NULL +#define NULL 0 +#endif + +typedef unsigned char uchar; + +enum toktype +{ + END, UNCLASS, NAME, NUMBER, STRING, CCON, NL, WS, DSHARP, + EQ, NEQ, LEQ, GEQ, LSH, RSH, LAND, LOR, PPLUS, MMINUS, + ARROW, SBRA, SKET, LP, RP, DOT, AND, STAR, PLUS, MINUS, + TILDE, NOT, SLASH, PCT, LT, GT, CIRC, OR, QUEST, + COLON, ASGN, COMMA, SHARP, SEMIC, CBRA, CKET, + ASPLUS, ASMINUS, ASSTAR, ASSLASH, ASPCT, ASCIRC, ASLSH, + ASRSH, ASOR, ASAND, ELLIPS, + DSHARP1, NAME1, NAME2, DEFINED, UMINUS, ARCHITECTURE, IDENT, + COMMENT +}; + +enum kwtype +{ + KIF, KIFDEF, KIFNDEF, KELIF, KELSE, KENDIF, KINCLUDE, KINCLUDENEXT, + KIMPORT, KDEFINE, KUNDEF, KLINE, KERROR, KPRAGMA, KIDENT, KDEFINED, + KMACHINE, KLINENO, KFILE, KDATE, KTIME, KSTDC, KEVAL +}; + +#define ISDEFINED 0x01 /* has #defined value */ +#define ISKW 0x02 /* is PP keyword */ +#define ISUNCHANGE 0x04 /* can't be #defined in PP */ +#define ISMAC 0x08 /* builtin macro, e.g. __LINE__ */ +#define ISARCHITECTURE 0x10 /* architecture */ +#define ISACTIVE 0x80 /* is macro currently expanded */ + +#define EOB 0xFE /* sentinel for end of input buffer */ +#define EOFC 0xFD /* sentinel for end of input file */ +#define XPWS 1 /* token flag: white space to assure token sep. */ +#define XTWS 2 + +typedef struct token +{ + unsigned char type; + unsigned char flag; + unsigned int wslen; + unsigned int len; + uchar *t; +} Token; + +typedef struct tokenrow +{ + Token *tp; /* current one to scan */ + Token *bp; /* base (allocated value) */ + Token *lp; /* last+1 token used */ + int max; /* number allocated */ +} Tokenrow; + +typedef struct source +{ + char *filename; /* name of file of the source */ + int line; /* current line number */ + int lineinc; /* adjustment for \\n lines */ + uchar *inb; /* input buffer */ + uchar *inp; /* input pointer */ + uchar *inl; /* end of input */ + int fd; /* input source */ + int ifdepth; /* conditional nesting in include */ + int pathdepth; + int wrap; + struct source *next; /* stack for #include */ +} Source; + +typedef struct nlist +{ + struct nlist *next; + uchar *name; + int len; + Tokenrow *vp; /* value as macro */ + Tokenrow *ap; /* list of argument names, if any */ + char val; /* value as preprocessor name */ + char flag; /* is defined, is pp name */ + uchar *loc; /* location of definition */ +} Nlist; + +typedef struct includelist +{ + char deleted; + char always; + char *file; +} Includelist; + +typedef struct wraplist +{ + char *file; +} Wraplist; + +#define new(t) (t *)domalloc(sizeof(t)) +#define quicklook(a,b) (namebit[(a)&077] & (1<<((b)&037))) +#define quickset(a,b) namebit[(a)&077] |= (1<<((b)&037)) +extern unsigned long namebit[077 + 1]; + +enum errtype +{ + INFO, WARNING, ERROR, FATAL +}; + +void expandlex(void); +void setup(int, char **); +int gettokens(Tokenrow *, int); +int comparetokens(Tokenrow *, Tokenrow *); +Source *setsource(char *, int, int, char *, int); +void unsetsource(void); +void puttokens(Tokenrow *); +void process(Tokenrow *); +void *domalloc(int); +void dofree(void *); +void error(enum errtype, char *,...); +void flushout(void); +int fillbuf(Source *); +int trigraph(Source *); +int foldline(Source *); +Nlist *lookup(Token *, int); +void control(Tokenrow *); +void dodefine(Tokenrow *); +void doadefine(Tokenrow *, int); +void doinclude(Tokenrow *, int, int); +void doif(Tokenrow *, enum kwtype); +void expand(Tokenrow *, Nlist *); +void builtin(Tokenrow *, int); +int gatherargs(Tokenrow *, Tokenrow **, int *); +void substargs(Nlist *, Tokenrow *, Tokenrow **); +void expandrow(Tokenrow *, char *); +void maketokenrow(int, Tokenrow *); +Tokenrow *copytokenrow(Tokenrow *, Tokenrow *); +Token *growtokenrow(Tokenrow *); +Tokenrow *normtokenrow(Tokenrow *); +void adjustrow(Tokenrow *, int); +void movetokenrow(Tokenrow *, Tokenrow *); +void insertrow(Tokenrow *, int, Tokenrow *); +void peektokens(Tokenrow *, char *); +void doconcat(Tokenrow *); +Tokenrow *stringify(Tokenrow *); +int lookuparg(Nlist *, Token *); +long eval(Tokenrow *, int); +void genline(void); +void genimport(char *, int, char *, int); +void genwrap(int); +void setempty(Tokenrow *); +void makespace(Tokenrow *, Token *); +char *outnum(char *, int); +int digit(int); +uchar *newstring(uchar *, int, int); + +#define rowlen(tokrow) ((tokrow)->lp - (tokrow)->bp) + +extern char *outptr; +extern Token nltoken; +extern Source *cursource; +extern char *curtime; +extern int incdepth; +extern int ifdepth; +extern int ifsatisfied[NIF]; +extern int Mflag; +extern int Iflag; +extern int Pflag; +extern int Aflag; +extern int Lflag; +extern int Xflag; +extern int Vflag; +extern int Cflag; +extern int Cplusplus; +extern int skipping; +extern Nlist *kwdefined; +extern Includelist includelist[NINCLUDE]; +extern Wraplist wraplist[NINCLUDE]; +extern char wd[]; + diff --git a/idlc/source/preproc/eval.c b/idlc/source/preproc/eval.c new file mode 100644 index 000000000000..cd3adc2204c7 --- /dev/null +++ b/idlc/source/preproc/eval.c @@ -0,0 +1,790 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdlib.h> +#include <string.h> +#include "cpp.h" + +#define NSTAK 32 +#define SGN 0 +#define UNS 1 +#define UND 2 + +#define UNSMARK 0x1000 + +struct value +{ + long val; + int type; +}; + +/* conversion types */ +#define RELAT 1 +#define ARITH 2 +#define LOGIC 3 +#define SPCL 4 +#define SHIFT 5 +#define UNARY 6 + +/* operator priority, arity, and conversion type, indexed by tokentype */ +struct pri +{ + char pri; + char arity; + char ctype; +} priority[] = + +{ + { + 0, 0, 0 + }, /* END */ + { + 0, 0, 0 + }, /* UNCLASS */ + { + 0, 0, 0 + }, /* NAME */ + { + 0, 0, 0 + }, /* NUMBER */ + { + 0, 0, 0 + }, /* STRING */ + { + 0, 0, 0 + }, /* CCON */ + { + 0, 0, 0 + }, /* NL */ + { + 0, 0, 0 + }, /* WS */ + { + 0, 0, 0 + }, /* DSHARP */ + { + 11, 2, RELAT + }, /* EQ */ + { + 11, 2, RELAT + }, /* NEQ */ + { + 12, 2, RELAT + }, /* LEQ */ + { + 12, 2, RELAT + }, /* GEQ */ + { + 13, 2, SHIFT + }, /* LSH */ + { + 13, 2, SHIFT + }, /* RSH */ + { + 7, 2, LOGIC + }, /* LAND */ + { + 6, 2, LOGIC + }, /* LOR */ + { + 0, 0, 0 + }, /* PPLUS */ + { + 0, 0, 0 + }, /* MMINUS */ + { + 0, 0, 0 + }, /* ARROW */ + { + 0, 0, 0 + }, /* SBRA */ + { + 0, 0, 0 + }, /* SKET */ + { + 3, 0, 0 + }, /* LP */ + { + 3, 0, 0 + }, /* RP */ + { + 0, 0, 0 + }, /* DOT */ + { + 10, 2, ARITH + }, /* AND */ + { + 15, 2, ARITH + }, /* STAR */ + { + 14, 2, ARITH + }, /* PLUS */ + { + 14, 2, ARITH + }, /* MINUS */ + { + 16, 1, UNARY + }, /* TILDE */ + { + 16, 1, UNARY + }, /* NOT */ + { + 15, 2, ARITH + }, /* SLASH */ + { + 15, 2, ARITH + }, /* PCT */ + { + 12, 2, RELAT + }, /* LT */ + { + 12, 2, RELAT + }, /* GT */ + { + 9, 2, ARITH + }, /* CIRC */ + { + 8, 2, ARITH + }, /* OR */ + { + 5, 2, SPCL + }, /* QUEST */ + { + 5, 2, SPCL + }, /* COLON */ + { + 0, 0, 0 + }, /* ASGN */ + { + 4, 2, 0 + }, /* COMMA */ + { + 0, 0, 0 + }, /* SHARP */ + { + 0, 0, 0 + }, /* SEMIC */ + { + 0, 0, 0 + }, /* CBRA */ + { + 0, 0, 0 + }, /* CKET */ + { + 0, 0, 0 + }, /* ASPLUS */ + { + 0, 0, 0 + }, /* ASMINUS */ + { + 0, 0, 0 + }, /* ASSTAR */ + { + 0, 0, 0 + }, /* ASSLASH */ + { + 0, 0, 0 + }, /* ASPCT */ + { + 0, 0, 0 + }, /* ASCIRC */ + { + 0, 0, 0 + }, /* ASLSH */ + { + 0, 0, 0 + }, /* ASRSH */ + { + 0, 0, 0 + }, /* ASOR */ + { + 0, 0, 0 + }, /* ASAND */ + { + 0, 0, 0 + }, /* ELLIPS */ + { + 0, 0, 0 + }, /* DSHARP1 */ + { + 0, 0, 0 + }, /* NAME1 */ + { + 0, 0, 0 + }, /* NAME2 */ + { + 16, 1, UNARY + }, /* DEFINED */ + { + 16, 0, UNARY + }, /* UMINUS */ + { + 16, 1, UNARY + }, /* ARCHITECTURE */ +}; + +int evalop(struct pri); +struct value tokval(Token *); +struct value vals[NSTAK], *vp; +enum toktype ops[NSTAK], *op; + +/* + * Evaluate an #if #elif #ifdef #ifndef line. trp->tp points to the keyword. + */ +long + eval(Tokenrow * trp, int kw) +{ + Token *tp; + Nlist *np; + int ntok, rand; + + trp->tp++; + if (kw == KIFDEF || kw == KIFNDEF) + { + if (trp->lp - trp->bp != 4 || trp->tp->type != NAME) + { + error(ERROR, "Syntax error in #ifdef/#ifndef"); + return 0; + } + np = lookup(trp->tp, 0); + return (kw == KIFDEF) == (np && np->flag & (ISDEFINED | ISMAC)); + } + ntok = trp->tp - trp->bp; + kwdefined->val = KDEFINED; /* activate special meaning of + * defined */ + expandrow(trp, "<if>"); + kwdefined->val = NAME; + vp = vals; + op = ops; + *op++ = END; + for (rand = 0, tp = trp->bp + ntok; tp < trp->lp; tp++) + { + switch (tp->type) + { + case WS: + case NL: + continue; + + /* nilary */ + case NAME: + case NAME1: + case NAME2: + case NUMBER: + case CCON: + case STRING: + if (rand) + goto syntax; + *vp++ = tokval(tp); + rand = 1; + continue; + + /* unary */ + case DEFINED: + case TILDE: + case NOT: + if (rand) + goto syntax; + *op++ = tp->type; + continue; + + /* unary-binary */ + case PLUS: + case MINUS: + case STAR: + case AND: + if (rand == 0) + { + if (tp->type == MINUS) + *op++ = UMINUS; + if (tp->type == STAR || tp->type == AND) + { + error(ERROR, "Illegal operator * or & in #if/#elsif"); + return 0; + } + continue; + } + /* flow through */ + + /* plain binary */ + case EQ: + case NEQ: + case LEQ: + case GEQ: + case LSH: + case RSH: + case LAND: + case LOR: + case SLASH: + case PCT: + case LT: + case GT: + case CIRC: + case OR: + case QUEST: + case COLON: + case COMMA: + if (rand == 0) + goto syntax; + if (evalop(priority[tp->type]) != 0) + return 0; + *op++ = tp->type; + rand = 0; + continue; + + case LP: + if (rand) + goto syntax; + *op++ = LP; + continue; + + case RP: + if (!rand) + goto syntax; + if (evalop(priority[RP]) != 0) + return 0; + if (op <= ops || op[-1] != LP) + { + goto syntax; + } + op--; + continue; + + case SHARP: + if ((tp + 1) < trp->lp) + { + np = lookup(tp + 1, 0); + if (np && (np->val == KMACHINE)) + { + tp++; + if (rand) + goto syntax; + *op++ = ARCHITECTURE; + continue; + } + } + /* fall through */ + + default: + error(ERROR, "Bad operator (%t) in #if/#elsif", tp); + return 0; + } + } + if (rand == 0) + goto syntax; + if (evalop(priority[END]) != 0) + return 0; + if (op != &ops[1] || vp != &vals[1]) + { + error(ERROR, "Botch in #if/#elsif"); + return 0; + } + if (vals[0].type == UND) + error(ERROR, "Undefined expression value"); + return vals[0].val; +syntax: + error(ERROR, "Syntax error in #if/#elsif"); + return 0; +} + +int + evalop(struct pri pri) +{ + struct value v1, v2 = { 0, 0 }; + long rv1, rv2; + int rtype, oper; + + rv2 = 0; + rtype = 0; + while (pri.pri < priority[op[-1]].pri) + { + oper = *--op; + if (priority[oper].arity == 2) + { + v2 = *--vp; + rv2 = v2.val; + } + v1 = *--vp; + rv1 = v1.val; +/*lint -e574 -e644 */ + switch (priority[oper].ctype) + { + case 0: + default: + error(WARNING, "Syntax error in #if/#endif"); + return 1; + case ARITH: + case RELAT: + if (v1.type == UNS || v2.type == UNS) + rtype = UNS; + else + rtype = SGN; + if (v1.type == UND || v2.type == UND) + rtype = UND; + if (priority[oper].ctype == RELAT && rtype == UNS) + { + oper |= UNSMARK; + rtype = SGN; + } + break; + case SHIFT: + if (v1.type == UND || v2.type == UND) + rtype = UND; + else + rtype = v1.type; + if (rtype == UNS) + oper |= UNSMARK; + break; + case UNARY: + rtype = v1.type; + break; + case LOGIC: + case SPCL: + break; + } + switch (oper) + { + case EQ: + case EQ | UNSMARK: + rv1 = rv1 == rv2; + break; + case NEQ: + case NEQ | UNSMARK: + rv1 = rv1 != rv2; + break; + case LEQ: + rv1 = rv1 <= rv2; + break; + case GEQ: + rv1 = rv1 >= rv2; + break; + case LT: + rv1 = rv1 < rv2; + break; + case GT: + rv1 = rv1 > rv2; + break; + case LEQ | UNSMARK: + rv1 = (unsigned long)rv1 <= (unsigned long)rv2; + break; + case GEQ | UNSMARK: + rv1 = (unsigned long)rv1 >= (unsigned long)rv2; + break; + case LT | UNSMARK: + rv1 = (unsigned long)rv1 < (unsigned long)rv2; + break; + case GT | UNSMARK: + rv1 = (unsigned long)rv1 > (unsigned long)rv2; + break; + case LSH: + rv1 <<= rv2; + break; + case LSH | UNSMARK: + rv1 = (unsigned long) rv1 << rv2; + break; + case RSH: + rv1 >>= rv2; + break; + case RSH | UNSMARK: + rv1 = (unsigned long) rv1 >> rv2; + break; + case LAND: + rtype = UND; + if (v1.type == UND) + break; + if (rv1 != 0) + { + if (v2.type == UND) + break; + rv1 = rv2 != 0; + } + else + rv1 = 0; + rtype = SGN; + break; + case LOR: + rtype = UND; + if (v1.type == UND) + break; + if (rv1 == 0) + { + if (v2.type == UND) + break; + rv1 = rv2 != 0; + } + else + rv1 = 1; + rtype = SGN; + break; + case AND: + rv1 &= rv2; + break; + case STAR: + rv1 *= rv2; + break; + case PLUS: + rv1 += rv2; + break; + case MINUS: + rv1 -= rv2; + break; + case UMINUS: + if (v1.type == UND) + rtype = UND; + rv1 = -rv1; + break; + case OR: + rv1 |= rv2; + break; + case CIRC: + rv1 ^= rv2; + break; + case TILDE: + rv1 = ~rv1; + break; + case NOT: + rv1 = !rv1; + if (rtype != UND) + rtype = SGN; + break; + case SLASH: + if (rv2 == 0) + { + rtype = UND; + break; + } + if (rtype == UNS) + rv1 /= (unsigned long) rv2; + else + rv1 /= rv2; + break; + case PCT: + if (rv2 == 0) + { + rtype = UND; + break; + } + if (rtype == UNS) + rv1 %= (unsigned long) rv2; + else + rv1 %= rv2; + break; + case COLON: + if (op[-1] != QUEST) + error(ERROR, "Bad ?: in #if/endif"); + else + { + op--; + if ((--vp)->val == 0) + v1 = v2; + rtype = v1.type; + rv1 = v1.val; + } + break; + + case DEFINED: + case ARCHITECTURE: + break; + + default: + error(ERROR, "Eval botch (unknown operator)"); + return 1; + } +/*lint +e574 +e644 */ + v1.val = rv1; + v1.type = rtype; + *vp++ = v1; + } + return 0; +} + +struct value + tokval(Token * tp) +{ + struct value v; + Nlist *np; + int i, base; + unsigned long n; + uchar *p, c; + + v.type = SGN; + v.val = 0; + switch (tp->type) + { + + case NAME: + v.val = 0; + break; + + case NAME1: + if ((np = lookup(tp, 0)) != NULL && np->flag & (ISDEFINED | ISMAC)) + v.val = 1; + break; + + case NAME2: + if ((np = lookup(tp, 0)) != NULL && np->flag & (ISARCHITECTURE)) + v.val = 1; + break; + + case NUMBER: + n = 0; + base = 10; + p = tp->t; + c = p[tp->len]; + p[tp->len] = '\0'; + if (*p == '0') + { + base = 8; + if (p[1] == 'x' || p[1] == 'X') + { + base = 16; + p++; + } + p++; + } + for (;; p++) + { + if ((i = digit(*p)) < 0) + break; + if (i >= base) + error(WARNING, + "Bad digit in number %t", tp); + n *= base; + n += i; + } + if (n >= 0x80000000 && base != 10) + v.type = UNS; + for (; *p; p++) + { + if (*p == 'u' || *p == 'U') + v.type = UNS; + else + if (*p == 'l' || *p == 'L') + ; + else + { + error(ERROR, + "Bad number %t in #if/#elsif", tp); + break; + } + } + v.val = n; + tp->t[tp->len] = c; + break; + + case CCON: + n = 0; + p = tp->t; + if (*p == 'L') + { + p += 1; + error(WARNING, "Wide char constant value undefined"); + } + p += 1; + if (*p == '\\') + { + p += 1; + if ((i = digit(*p)) >= 0 && i <= 7) + { + n = i; + p += 1; + if ((i = digit(*p)) >= 0 && i <= 7) + { + p += 1; + n <<= 3; + n += i; + if ((i = digit(*p)) >= 0 && i <= 7) + { + p += 1; + n <<= 3; + n += i; + } + } + } + else + if (*p == 'x') + { + p += 1; + while ((i = digit(*p)) >= 0 && i <= 15) + { + p += 1; + n <<= 4; + n += i; + } + } + else + { + static char cvcon[] + = "b\bf\fn\nr\rt\tv\v''\"\"??\\\\"; + + for (i = 0; i < (int)sizeof(cvcon); i += 2) + { + if (*p == cvcon[i]) + { + n = cvcon[i + 1]; + break; + } + } + p += 1; + if (i >= (int)sizeof(cvcon)) + error(WARNING, + "Undefined escape in character constant"); + } + } + else + if (*p == '\'') + error(ERROR, "Empty character constant"); + else + n = *p++; + if (*p != '\'') + error(WARNING, "Multibyte character constant undefined"); + else + if (n > 127) + error(WARNING, "Character constant taken as not signed"); + v.val = n; + break; + + case STRING: + error(ERROR, "String in #if/#elsif"); + break; + } + return v; +} + +int + digit(int i) +{ + if ('0' <= i && i <= '9') + i -= '0'; + else + if ('a' <= i && i <= 'f') + i -= 'a' - 10; + else + if ('A' <= i && i <= 'F') + i -= 'A' - 10; + else + i = -1; + return i; +} diff --git a/idlc/source/preproc/include.c b/idlc/source/preproc/include.c new file mode 100644 index 000000000000..88a619905b64 --- /dev/null +++ b/idlc/source/preproc/include.c @@ -0,0 +1,256 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__)) +# include <io.h> +#else +# include <unistd.h> +#endif +#ifdef _MSC_VER +# define _POSIX_ +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> + +#ifdef __hpux +# define _HPUX_SOURCE +#endif +#ifdef SCO +#define _IBCS2 +#endif +#include <limits.h> + +#include "cpp.h" + +Includelist includelist[NINCLUDE]; +Wraplist wraplist[NINCLUDE]; + +void + doinclude(Tokenrow * trp, int depth, int import) +{ +#ifdef OS2 + char fname[_MAX_PATH], iname[_MAX_PATH]; +#else + char fname[PATH_MAX], iname[PATH_MAX]; +#endif + Includelist *ip; + int angled, len, fd, i; + + trp->tp += 1; + if (trp->tp >= trp->lp) + goto syntax; + if (trp->tp->type != STRING && trp->tp->type != LT) + { + len = trp->tp - trp->bp; + expandrow(trp, "<include>"); + trp->tp = trp->bp + len; + } + if (trp->tp->type == STRING) + { + len = trp->tp->len - 2; + if (len > (int)sizeof(fname) - 1) + len = sizeof(fname) - 1; + strncpy(fname, (char *) trp->tp->t + 1, len); + angled = 0; + } + else + if (trp->tp->type == LT) + { + len = 0; + trp->tp++; + while (trp->tp->type != GT) + { + if (trp->tp > trp->lp || len + trp->tp->len + 2 >= sizeof(fname)) + goto syntax; + strncpy(fname + len, (char *) trp->tp->t, trp->tp->len); + len += trp->tp->len; + trp->tp++; + } + angled = 1; + } + else + goto syntax; + trp->tp += 2; + if (trp->tp < trp->lp || len == 0) + goto syntax; + fname[len] = '\0'; + if (fname[0] == '/') + { + fd = open(fname, O_RDONLY); + strcpy(iname, fname); + } + else + for (fd = -1, i = (depth < 0) ? (NINCLUDE - 1) : (depth - 1); i >= 0; i--) + { + ip = &includelist[i]; + if (ip->file == NULL || ip->deleted || (angled && ip->always == 0)) + continue; + if (strlen(fname) + strlen(ip->file) + 2 > sizeof(iname)) + continue; + strcpy(iname, ip->file); + strcat(iname, "/"); + strcat(iname, fname); + if ((fd = open(iname, O_RDONLY)) >= 0) + break; + } + if (fd >= 0) + { + if (++incdepth > NINC ) + error(FATAL, "#%s too deeply nested", import ? "import" : "include"); + if (Xflag) + genimport(fname, angled, iname, import); + if (Iflag) + error(INFO, "Open %s file [%s]", import ? "import" : "include", iname ); + + for (i = NINCLUDE - 1; i >= 0; i--) + { + if ((wraplist[i].file != NULL) && + (strncmp(wraplist[i].file, iname, strlen(wraplist[i].file)) == 0)) + break; + } + + setsource((char *) newstring((uchar *) iname, strlen(iname), 0), i, fd, NULL, (i >= 0) ? 1 : 0); + + if (!Pflag) + genline(); + } + else + { + trp->tp = trp->bp + 2; + error(ERROR, "Could not find %s file %r", import ? "import" : "include", trp); + } + return; +syntax: + error(ERROR, "Syntax error in #%s", import ? "import" : "include"); + return; +} + +/* + * Generate a line directive for cursource + */ +void + genline(void) +{ + static Token ta = {UNCLASS, 0, 0, 0, NULL }; + static Tokenrow tr = {&ta, &ta, &ta + 1, 1}; + uchar *p; + + ta.t = p = (uchar *) outptr; + strcpy((char *) p, "#line "); + p += sizeof("#line ") - 1; + p = (uchar *) outnum((char *) p, cursource->line); + *p++ = ' '; + *p++ = '"'; + if (cursource->filename[0] != '/' && wd[0]) + { + strcpy((char *) p, wd); + p += strlen(wd); + *p++ = '/'; + } + strcpy((char *) p, cursource->filename); + p += strlen((char *) p); + *p++ = '"'; + *p++ = '\n'; + ta.len = (char *) p - outptr; + outptr = (char *) p; + tr.tp = tr.bp; + puttokens(&tr); +} + +/* + * Generate a pragma import/include directive + */ +void + genimport(char *fname, int angled, char *iname, int import) +{ + static Token ta = {UNCLASS, 0, 0, 0, NULL }; + static Tokenrow tr = {&ta, &ta, &ta + 1, 1}; + uchar *p; + + ta.t = p = (uchar *) outptr; + + if (import) + strcpy((char *) p, "#pragma import"); + else + strcpy((char *) p, "#pragma include"); + + p += strlen((char *) p); + + *p++ = '('; + + *p++ = angled ? '<' : '"'; + strcpy((char *) p, fname); + p += strlen(fname); + *p++ = angled ? '>' : '"'; + + *p++ = ','; + + *p++ = '"'; + strcpy((char *) p, iname); + p += strlen(iname); + *p++ = '"'; + + *p++ = ')'; + *p++ = '\n'; + + ta.len = (char *) p - outptr; + outptr = (char *) p; + tr.tp = tr.bp; + puttokens(&tr); +} + +/* + * Generate a extern C directive + */ +void + genwrap(int end) +{ + static Token ta = {UNCLASS, 0, 0, 0, NULL}; + static Tokenrow tr = {&ta, &ta, &ta + 1, 1}; + uchar *p; + + if (Cplusplus) + { + ta.t = p = (uchar *) outptr; + + if (! end) + strcpy((char *) p, "extern \"C\" {"); + else + strcpy((char *) p, "}"); + + p += strlen((char *) p); + + *p++ = '\n'; + + ta.len = (char *) p - outptr; + outptr = (char *) p; + tr.tp = tr.bp; + puttokens(&tr); + } +} + diff --git a/idlc/source/preproc/lex.c b/idlc/source/preproc/lex.c new file mode 100644 index 000000000000..fd6d00792984 --- /dev/null +++ b/idlc/source/preproc/lex.c @@ -0,0 +1,695 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__)) +#include <io.h> +#else +#include <unistd.h> +#endif +#include "cpp.h" + +/* + * lexical FSM encoding + * when in state state, and one of the characters + * in ch arrives, enter nextstate. + * States >= S_SELF are either final, or at least require special action. + * In 'fsm' there is a line for each state X charset X nextstate. + * List chars that overwrite previous entries later (e.g. C_ALPH + * can be overridden by '_' by a later entry; and C_XX is the + * the universal set, and should always be first. + * States above S_SELF are represented in the big table as negative values. + * S_SELF and S_SELFB encode the resulting token type in the upper bits. + * These actions differ in that S_SELF doesn't have a lookahead char, + * S_SELFB does. + * + * The encoding is blown out into a big table for time-efficiency. + * Entries have + * nextstate: 6 bits; ?\ marker: 1 bit; tokentype: 9 bits. + */ + +#define MAXSTATE 32 +#define ACT(tok,act) ((tok<<7)+act) +#define QBSBIT 0100 +#define GETACT(st) ((st>>7)&0x1ff) + +/* character classes */ +#define C_WS 1 +#define C_ALPH 2 +#define C_NUM 3 +#define C_EOF 4 +#define C_XX 5 + +enum state +{ + START = 0, NUM1, NUM2, NUM3, ID1, ST1, ST2, ST3, COM1, COM2, COM3, COM4, + CC1, CC2, WS1, PLUS1, MINUS1, STAR1, SLASH1, PCT1, SHARP1, + CIRC1, GT1, GT2, LT1, LT2, OR1, AND1, ASG1, NOT1, DOTS1, + S_SELF = MAXSTATE, S_SELFB, S_EOF, S_NL, S_EOFSTR, + S_STNL, S_COMNL, S_EOFCOM, S_COMMENT, S_EOB, S_WS, S_NAME +}; + +int tottok; +int tokkind[256]; +struct fsm +{ + int state; /* if in this state */ + uchar ch[4]; /* and see one of these characters */ + int nextstate; /* enter this state if +ve */ +}; + + /*const*/ struct fsm fsm[] = { + /* start state */ + { START, {C_XX}, ACT(UNCLASS, S_SELF) }, + { START, {' ', '\t', '\v'}, WS1 }, + { START, {C_NUM}, NUM1 }, + { START, {'.'}, NUM3 }, + { START, {C_ALPH}, ID1 }, + { START, {'L'}, ST1 }, + { START, {'"'}, ST2 }, + { START, {'\''}, CC1 }, + { START, {'/'}, COM1 }, + { START, {EOFC}, S_EOF }, + { START, {'\n'}, S_NL }, + { START, {'-'}, MINUS1 }, + { START, {'+'}, PLUS1 }, + { START, {'<'}, LT1 }, + { START, {'>'}, GT1 }, + { START, {'='}, ASG1 }, + { START, {'!'}, NOT1 }, + { START, {'&'}, AND1 }, + { START, {'|'}, OR1 }, + { START, {'#'}, SHARP1 }, + { START, {'%'}, PCT1 }, + { START, {'['}, ACT(SBRA, S_SELF) }, + { START, {']'}, ACT(SKET, S_SELF) }, + { START, {'('}, ACT(LP, S_SELF) }, + { START, {')'}, ACT(RP, S_SELF) }, + { START, {'*'}, STAR1 }, + { START, {','}, ACT(COMMA, S_SELF) }, + { START, {'?'}, ACT(QUEST, S_SELF) }, + { START, {':'}, ACT(COLON, S_SELF) }, + { START, {';'}, ACT(SEMIC, S_SELF) }, + { START, {'{'}, ACT(CBRA, S_SELF) }, + { START, {'}'}, ACT(CKET, S_SELF) }, + { START, {'~'}, ACT(TILDE, S_SELF) }, + { START, {'^'}, CIRC1 }, + + /* saw a digit */ + { NUM1, {C_XX}, ACT(NUMBER, S_SELFB) }, + { NUM1, {C_NUM, C_ALPH, '.'}, NUM1 }, + { NUM1, {'E', 'e'}, NUM2 }, + { NUM1, {'_'}, ACT(NUMBER, S_SELFB) }, + + /* saw possible start of exponent, digits-e */ + { NUM2, {C_XX}, ACT(NUMBER, S_SELFB) }, + { NUM2, {'+', '-'}, NUM1 }, + { NUM2, {C_NUM, C_ALPH}, NUM1 }, + { NUM2, {'_'}, ACT(NUMBER, S_SELFB) }, + + /* saw a '.', which could be a number or an operator */ + { NUM3, {C_XX}, ACT(DOT, S_SELFB) }, + { NUM3, {'.'}, DOTS1 }, + { NUM3, {C_NUM}, NUM1 }, + + { DOTS1, {C_XX}, ACT(UNCLASS, S_SELFB) }, + { DOTS1, {C_NUM}, NUM1 }, + { DOTS1, {'.'}, ACT(ELLIPS, S_SELF) }, + + /* saw a letter or _ */ + { ID1, {C_XX}, ACT(NAME, S_NAME) }, + { ID1, {C_ALPH, C_NUM}, ID1 }, + + /* saw L (start of wide string?) */ + { ST1, {C_XX}, ACT(NAME, S_NAME) }, + { ST1, {C_ALPH, C_NUM}, ID1 }, + { ST1, {'"'}, ST2 }, + { ST1, {'\''}, CC1 }, + + /* saw " beginning string */ + { ST2, {C_XX}, ST2 }, + { ST2, {'"'}, ACT(STRING, S_SELF) }, + { ST2, {'\\'}, ST3 }, + { ST2, {'\n'}, S_STNL }, + { ST2, {EOFC}, S_EOFSTR }, + + /* saw \ in string */ + { ST3, {C_XX}, ST2 }, + { ST3, {'\n'}, S_STNL }, + { ST3, {EOFC}, S_EOFSTR }, + + /* saw ' beginning character const */ + { CC1, {C_XX}, CC1 }, + { CC1, {'\''}, ACT(CCON, S_SELF) }, + { CC1, {'\\'}, CC2 }, + { CC1, {'\n'}, S_STNL }, + { CC1, {EOFC}, S_EOFSTR }, + + /* saw \ in ccon */ + { CC2, {C_XX}, CC1 }, + { CC2, {'\n'}, S_STNL }, + { CC2, {EOFC}, S_EOFSTR }, + + /* saw /, perhaps start of comment */ + { COM1, {C_XX}, ACT(SLASH, S_SELFB) }, + { COM1, {'='}, ACT(ASSLASH, S_SELF) }, + { COM1, {'*'}, COM2 }, + { COM1, {'/'}, COM4 }, + + /* saw / followed by *, start of comment */ + { COM2, {C_XX}, COM2 }, + { COM2, {'\n'}, S_COMNL }, + { COM2, {'*'}, COM3 }, + { COM2, {EOFC}, S_EOFCOM }, + + /* saw the * possibly ending a comment */ + { COM3, {C_XX}, COM2 }, + { COM3, {'\n'}, S_COMNL }, + { COM3, {'*'}, COM3 }, + { COM3, {'/'}, S_COMMENT }, + + /* // comment */ + { COM4, {C_XX}, COM4 }, + { COM4, {'\n'}, S_COMMENT }, + /* { COM4, {'\n'}, S_NL }, */ + { COM4, {EOFC}, S_EOFCOM }, + + /* saw white space, eat it up */ + { WS1, {C_XX}, S_WS }, + { WS1, {'\t', '\v', ' '}, WS1 }, + + /* saw -, check --, -=, -> */ + { MINUS1, {C_XX}, ACT(MINUS, S_SELFB) }, + { MINUS1, {'-'}, ACT(MMINUS, S_SELF) }, + { MINUS1, {'='}, ACT(ASMINUS, S_SELF) }, + { MINUS1, {'>'}, ACT(ARROW, S_SELF) }, + + /* saw +, check ++, += */ + { PLUS1, {C_XX}, ACT(PLUS, S_SELFB) }, + { PLUS1, {'+'}, ACT(PPLUS, S_SELF) }, + { PLUS1, {'='}, ACT(ASPLUS, S_SELF) }, + + /* saw <, check <<, <<=, <= */ + { LT1, {C_XX}, ACT(LT, S_SELFB) }, + { LT1, {'<'}, LT2 }, + { LT1, {'='}, ACT(LEQ, S_SELF) }, + { LT2, {C_XX}, ACT(LSH, S_SELFB) }, + { LT2, {'='}, ACT(ASLSH, S_SELF) }, + + /* saw >, check >>, >>=, >= */ + { GT1, {C_XX}, ACT(GT, S_SELFB) }, + { GT1, {'>'}, GT2 }, + { GT1, {'='}, ACT(GEQ, S_SELF) }, + { GT2, {C_XX}, ACT(RSH, S_SELFB) }, + { GT2, {'='}, ACT(ASRSH, S_SELF) }, + + /* = */ + { ASG1, {C_XX}, ACT(ASGN, S_SELFB) }, + { ASG1, {'='}, ACT(EQ, S_SELF) }, + + /* ! */ + { NOT1, {C_XX}, ACT(NOT, S_SELFB) }, + { NOT1, {'='}, ACT(NEQ, S_SELF) }, + + /* & */ + { AND1, {C_XX}, ACT(AND, S_SELFB) }, + { AND1, {'&'}, ACT(LAND, S_SELF) }, + { AND1, {'='}, ACT(ASAND, S_SELF) }, + + /* | */ + { OR1, {C_XX}, ACT(OR, S_SELFB) }, + { OR1, {'|'}, ACT(LOR, S_SELF) }, + { OR1, {'='}, ACT(ASOR, S_SELF) }, + + /* # */ + { SHARP1, {C_XX}, ACT(SHARP, S_SELFB) }, + { SHARP1, {'#'}, ACT(DSHARP, S_SELF) }, + + /* % */ + { PCT1, {C_XX}, ACT(PCT, S_SELFB) }, + { PCT1, {'='}, ACT(ASPCT, S_SELF) }, + + /* * */ + { STAR1, {C_XX}, ACT(STAR, S_SELFB) }, + { STAR1, {'='}, ACT(ASSTAR, S_SELF) }, + + /* ^ */ + { CIRC1, {C_XX}, ACT(CIRC, S_SELFB) }, + { CIRC1, {'='}, ACT(ASCIRC, S_SELF) }, + + { -1, {'\0'}, S_SELF } +}; + +/* first index is char, second is state */ +/* increase #states to power of 2 to encourage use of shift */ +short bigfsm[256][MAXSTATE]; + +void + expandlex(void) +{ + /* const */ struct fsm *fp; + int i, j, nstate; + + for (fp = fsm; fp->state >= 0; fp++) + { + for (i = 0; fp->ch[i]; i++) + { + nstate = fp->nextstate; + if (nstate >= S_SELF) + nstate = ~nstate; + switch (fp->ch[i]) + { + + case C_XX: /* random characters */ + for (j = 0; j < 256; j++) + bigfsm[j][fp->state] = (short) nstate; + continue; + case C_ALPH: + for (j = 0; j <= 256; j++) + if (('a' <= j && j <= 'z') || ('A' <= j && j <= 'Z') + || j == '_') + bigfsm[j][fp->state] = (short) nstate; + continue; + case C_NUM: + for (j = '0'; j <= '9'; j++) + bigfsm[j][fp->state] = (short) nstate; + continue; + default: + bigfsm[fp->ch[i]][fp->state] = (short) nstate; + } + } + } + + /* + * install special cases for ? (trigraphs), \ (splicing), runes, and + * EOB + */ + for (i = 0; i < MAXSTATE; i++) + { + for (j = 0; j < 0xFF; j++) + if (j == '?' || j == '\\' || j == '\n' || j == '\r') + { + if (bigfsm[j][i] > 0) + bigfsm[j][i] = ~bigfsm[j][i]; + bigfsm[j][i] &= ~QBSBIT; + } + bigfsm[EOB][i] = ~S_EOB; + if (bigfsm[EOFC][i] >= 0) + bigfsm[EOFC][i] = ~S_EOF; + } +} + +/* + * fill in a row of tokens from input, terminated by NL or END + * First token is put at trp->lp. + * Reset is non-zero when the input buffer can be "rewound." + * The value is a flag indicating that possible macros have + * been seen in the row. + */ +int + gettokens(Tokenrow * trp, int reset) +{ + register int c, state, oldstate; + register uchar *ip; + register Token *tp, *maxp; + int runelen; + Source *s = cursource; + int nmac = 0; + + tp = trp->lp; + ip = s->inp; + if (reset) + { + s->lineinc = 0; + if (ip >= s->inl) + { /* nothing in buffer */ + s->inl = s->inb; + fillbuf(s); + ip = s->inp = s->inb; + } + else + if (ip >= s->inb + (3 * INS / 4)) + { + memmove(s->inb, ip, 4 + s->inl - ip); + s->inl = s->inb + (s->inl - ip); + ip = s->inp = s->inb; + } + } + maxp = &trp->bp[trp->max]; + runelen = 1; + for (;;) + { +continue2: + if (tp >= maxp) + { + trp->lp = tp; + tp = growtokenrow(trp); + maxp = &trp->bp[trp->max]; + } + tp->type = UNCLASS; + tp->t = ip; + tp->wslen = 0; + tp->flag = 0; + state = START; + for (;;) + { + oldstate = state; + + c = *ip; + + if ((state = bigfsm[c][state]) >= 0) + { + ip += runelen; + runelen = 1; + continue; + } + state = ~state; + reswitch: + switch (state & 0177) + { + case S_SELF: + ip += runelen; + runelen = 1; + case S_SELFB: + tp->type = (unsigned char) GETACT(state); + tp->len = ip - tp->t; + tp++; + goto continue2; + + case S_NAME: /* like S_SELFB but with nmac check */ + tp->type = NAME; + tp->len = ip - tp->t; + nmac |= quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0); + tp++; + goto continue2; + + case S_WS: + tp->wslen = ip - tp->t; + tp->t = ip; + state = START; + continue; + + default: + if ((state & QBSBIT) == 0) + { + ip += runelen; + runelen = 1; + continue; + } + state &= ~QBSBIT; + s->inp = ip; + + if (c == '\n') + { + while (s->inp + 1 >= s->inl && fillbuf(s) != EOF); + + if (s->inp[1] == '\r') + { + memmove(s->inp + 1, s->inp + 2, s->inl - s->inp + 2); + s->inl -= 1; + } + + goto reswitch; + } + + if (c == '\r') + { + while (s->inp + 1 >= s->inl && fillbuf(s) != EOF); + + if (s->inp[1] == '\n') + { + memmove(s->inp, s->inp + 1, s->inl - s->inp + 1); + s->inl -= 1; + } + else + *s->inp = '\n'; + + state = oldstate; + continue; + } + + if (c == '?') + { /* check trigraph */ + if (trigraph(s)) + { + state = oldstate; + continue; + } + goto reswitch; + } + if (c == '\\') + { /* line-folding */ + if (foldline(s)) + { + s->lineinc++; + state = oldstate; + continue; + } + goto reswitch; + } + error(WARNING, "Lexical botch in cpp"); + ip += runelen; + runelen = 1; + continue; + + case S_EOB: + s->inp = ip; + fillbuf(cursource); + state = oldstate; + continue; + + case S_EOF: + tp->type = END; + tp->len = 0; + s->inp = ip; + if (tp != trp->bp && (tp - 1)->type != NL && cursource->fd != -1) + error(WARNING, "No newline at end of file"); + trp->lp = tp + 1; + return nmac; + + case S_STNL: + error(ERROR, "Unterminated string or char const"); + case S_NL: + tp->t = ip; + tp->type = NL; + tp->len = 1; + tp->wslen = 0; + s->lineinc++; + s->inp = ip + 1; + trp->lp = tp + 1; + return nmac; + + case S_EOFSTR: + error(FATAL, "EOF in string or char constant"); + break; + + case S_COMNL: + s->lineinc++; + state = COM2; + ip += runelen; + runelen = 1; + continue; + + case S_EOFCOM: + error(WARNING, "EOF inside comment"); + --ip; + case S_COMMENT: + if (!Cflag) + { + tp->t = ++ip; + tp->t[-1] = ' '; + tp->wslen = 1; + state = START; + continue; + } + else + { + runelen = 1; + /* s->lineinc = 0; */ + tp->type = COMMENT; + tp->flag |= XTWS; + } + } + break; + } + ip += runelen; + runelen = 1; + tp->len = ip - tp->t; + tp++; + } +} + +/* have seen ?; handle the trigraph it starts (if any) else 0 */ +int + trigraph(Source * s) +{ + uchar c; + + while (s->inp + 2 >= s->inl && fillbuf(s) != EOF); + ; + if (s->inp[1] != '?') + return 0; + c = 0; + switch (s->inp[2]) + { + case '=': + c = '#'; + break; + case '(': + c = '['; + break; + case '/': + c = '\\'; + break; + case ')': + c = ']'; + break; + case '\'': + c = '^'; + break; + case '<': + c = '{'; + break; + case '!': + c = '|'; + break; + case '>': + c = '}'; + break; + case '-': + c = '~'; + break; + } + if (c) + { + *s->inp = c; + memmove(s->inp + 1, s->inp + 3, s->inl - s->inp + 2); + s->inl -= 2; + } + return c; +} + +int + foldline(Source * s) +{ + int n = 1; + + while (s->inp + 2 >= s->inl && fillbuf(s) != EOF); + + /* skip DOS line ends */ + if (((s->inp[n] == '\r') && (s->inp[n+1] == '\n')) || + ((s->inp[n] == '\n') && (s->inp[n+1] == '\r'))) + n++; + + if ((s->inp[n] == '\n') || (s->inp[n] == '\r')) + { + memmove(s->inp, s->inp + n + 1, s->inl - s->inp + n + 2); + s->inl -= n + 1; + return 1; + } + return 0; +} + +int + fillbuf(Source * s) +{ + int n; + + if (s->fd < 0 || (n = read(s->fd, (char *) s->inl, INS / 8)) <= 0) + n = 0; + s->inl += n; + s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOB; + if (n == 0) + { + s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC; + return EOF; + } + return 0; +} + +/* + * Push down to new source of characters. + * If fd>0 and str==NULL, then from a file `name'; + * if fd==-1 and str, then from the string. + */ +Source * + setsource(char *name, int path, int fd, char *str, int wrap) +{ + Source *s = new(Source); + int len; + + s->line = 1; + s->lineinc = 0; + s->fd = fd; + s->filename = name; + s->next = cursource; + s->ifdepth = 0; + s->pathdepth = path; + s->wrap = wrap; + + cursource = s; + + if (s->wrap) + genwrap(0); + + /* slop at right for EOB */ + if (str) + { + len = strlen(str); + s->inb = domalloc(len + 4); + s->inp = s->inb; + strncpy((char *) s->inp, str, len); + } + else + { + s->inb = domalloc(INS + 4); + s->inp = s->inb; + len = 0; + } + s->inl = s->inp + len; + s->inl[0] = s->inl[1] = EOB; + + return s; +} + +void + unsetsource(void) +{ + Source *s = cursource; + + if (s->wrap) + genwrap(1); + + if (s->fd >= 0) + { + close(s->fd); + dofree(s->inb); + } + cursource = s->next; + dofree(s); +} diff --git a/idlc/source/preproc/macro.c b/idlc/source/preproc/macro.c new file mode 100644 index 000000000000..7f0697994c4c --- /dev/null +++ b/idlc/source/preproc/macro.c @@ -0,0 +1,700 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#ifdef _MSC_VER +# define _POSIX_ +#endif +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __hpux +# define _HPUX_SOURCE +#endif +#ifdef SCO +# define _IBCS2 +#endif +#include <limits.h> + +#include "cpp.h" + +#define NCONCAT 16384 + +/* + * do a macro definition. tp points to the name being defined in the line + */ +void + dodefine(Tokenrow * trp) +{ + Token *tp; + Nlist *np; + Source *s; + Tokenrow *def, *args; +#ifdef OS2 + static uchar location[(_MAX_PATH + 8) * NINC], *cp; +#else + static uchar location[(PATH_MAX + 8) * NINC], *cp; +#endif + tp = trp->tp + 1; + if (tp >= trp->lp || tp->type != NAME) + { + error(ERROR, "#defined token is not a name"); + return; + } + np = lookup(tp, 1); + if (np->flag & ISUNCHANGE) + { + error(ERROR, "#defined token %t can't be redefined", tp); + return; + } + /* collect arguments */ + tp += 1; + args = NULL; + if (tp < trp->lp && tp->type == LP && tp->wslen == 0) + { + /* macro with args */ + int narg = 0; + + tp += 1; + args = new(Tokenrow); + maketokenrow(2, args); + if (tp->type != RP) + { + int err = 0; + + for (;;) + { + Token *atp; + + if (tp->type != NAME) + { + err++; + break; + } + if (narg >= args->max) + growtokenrow(args); + for (atp = args->bp; atp < args->lp; atp++) + if (atp->len == tp->len + && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0) + error(ERROR, "Duplicate macro argument"); + *args->lp++ = *tp; + narg++; + tp += 1; + if (tp->type == RP) + break; + if (tp->type != COMMA) + { + err++; + break; + } + tp += 1; + } + if (err) + { + error(ERROR, "Syntax error in macro parameters"); + return; + } + } + tp += 1; + } + trp->tp = tp; + if (((trp->lp) - 1)->type == NL) + trp->lp -= 1; + def = normtokenrow(trp); + if (np->flag & ISDEFINED) + { + if (comparetokens(def, np->vp) + || (np->ap == NULL) != (args == NULL) + || (np->ap && comparetokens(args, np->ap))) + error(ERROR, "Macro redefinition of %t (already defined at %s)", trp->bp + 2, np->loc); + } + if (args) + { + Tokenrow *tap; + + tap = normtokenrow(args); + dofree(args->bp); + args = tap; + } + np->ap = args; + np->vp = def; + np->flag |= ISDEFINED; + + /* build location string of macro definition */ + for (cp = location, s = cursource; s; s = s->next) + if (*s->filename) + { + if (cp != location) + *cp++ = ' '; + sprintf((char *)cp, "%s:%d", s->filename, s->line); + cp += strlen((char *)cp); + } + + np->loc = newstring(location, strlen((char *)location), 0); + + if (Mflag) + { + if (np->ap) + error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp); + else + error(INFO, "Macro definition of %s [%r]", np->name, np->vp); + } +} + +/* + * Definition received via -D or -U + */ +void + doadefine(Tokenrow * trp, int type) +{ + Nlist *np; + static uchar onestr[2] = "1"; + static Token onetoken[1] = {{NUMBER, 0, 0, 1, onestr}}; + static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1}; + + trp->tp = trp->bp; + if (type == 'U') + { + if (trp->lp - trp->tp != 2 || trp->tp->type != NAME) + goto syntax; + if ((np = lookup(trp->tp, 0)) == NULL) + return; + np->flag &= ~ISDEFINED; + return; + } + + if (type == 'A') + { + if (trp->tp >= trp->lp || trp->tp->type != NAME) + goto syntax; + trp->tp->type = ARCHITECTURE; + np = lookup(trp->tp, 1); + np->flag |= ISARCHITECTURE; + trp->tp += 1; + if (trp->tp >= trp->lp || trp->tp->type == END) + { + np->vp = &onetr; + return; + } + else + error(FATAL, "Illegal -A argument %r", trp); + } + + if (trp->tp >= trp->lp || trp->tp->type != NAME) + goto syntax; + np = lookup(trp->tp, 1); + np->flag |= ISDEFINED; + trp->tp += 1; + if (trp->tp >= trp->lp || trp->tp->type == END) + { + np->vp = &onetr; + return; + } + if (trp->tp->type != ASGN) + goto syntax; + trp->tp += 1; + if ((trp->lp - 1)->type == END) + trp->lp -= 1; + np->vp = normtokenrow(trp); + return; +syntax: + error(FATAL, "Illegal -D or -U argument %r", trp); +} + +/* + * Do macro expansion in a row of tokens. + * Flag is NULL if more input can be gathered. + */ +void + expandrow(Tokenrow * trp, char *flag) +{ + Token *tp; + Nlist *np; + + if (flag) + setsource(flag, -1, -1, "", 0); + for (tp = trp->tp; tp < trp->lp;) + { + if (tp->type != NAME + || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0 + || (np = lookup(tp, 0)) == NULL + || (np->flag & (ISDEFINED | ISMAC)) == 0 + || (np->flag & ISACTIVE) != 0) + { + tp++; + continue; + } + trp->tp = tp; + if (np->val == KDEFINED) + { + tp->type = DEFINED; + if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) + (tp + 1)->type = NAME1; + else + if ((tp + 3) < trp->lp && (tp + 1)->type == LP + && (tp + 2)->type == NAME && (tp + 3)->type == RP) + (tp + 2)->type = NAME1; + else + error(ERROR, "Incorrect syntax for `defined'"); + tp++; + continue; + } + else + if (np->val == KMACHINE) + { + if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP)) + { + tp->type = ARCHITECTURE; + if ((tp + 1) < trp->lp && (tp + 1)->type == NAME) + (tp + 1)->type = NAME2; + else + if ((tp + 3) < trp->lp && (tp + 1)->type == LP + && (tp + 2)->type == NAME && (tp + 3)->type == RP) + (tp + 2)->type = NAME2; + else + error(ERROR, "Incorrect syntax for `#machine'"); + } + tp++; + continue; + } + + if (np->flag & ISMAC) + builtin(trp, np->val); + else + expand(trp, np); + tp = trp->tp; + } + if (flag) + unsetsource(); +} + +/* + * Expand the macro whose name is np, at token trp->tp, in the tokenrow. + * Return trp->tp at the first token next to be expanded + * (ordinarily the beginning of the expansion) + */ +void + expand(Tokenrow * trp, Nlist * np) +{ + Tokenrow ntr; + int ntokc, narg, i; + Tokenrow *atr[NARG + 1]; + + if (Mflag == 2) + { + if (np->ap) + error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap); + else + error(INFO, "Macro expansion of %t with %s", trp->tp, np->name); + } + + copytokenrow(&ntr, np->vp); /* copy macro value */ + if (np->ap == NULL) /* parameterless */ + ntokc = 1; + else + { + ntokc = gatherargs(trp, atr, &narg); + if (narg < 0) + { /* not actually a call (no '(') */ + trp->tp++; + return; + } + if (narg != rowlen(np->ap)) + { + error(ERROR, "Disagreement in number of macro arguments"); + trp->tp += ntokc; + return; + } + substargs(np, &ntr, atr); /* put args into replacement */ + for (i = 0; i < narg; i++) + { + dofree(atr[i]->bp); + dofree(atr[i]); + } + } + + np->flag |= ISACTIVE; + + doconcat(&ntr); /* execute ## operators */ + ntr.tp = ntr.bp; + makespace(&ntr, trp->tp); + expandrow(&ntr, "<expand>"); + insertrow(trp, ntokc, &ntr); + dofree(ntr.bp); + + np->flag &= ~ISACTIVE; + + return; +} + +/* + * Gather an arglist, starting in trp with tp pointing at the macro name. + * Return total number of tokens passed, stash number of args found. + * trp->tp is not changed relative to the tokenrow. + */ +int + gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg) +{ + int parens = 1; + int ntok = 0; + Token *bp, *lp; + Tokenrow ttr; + int ntokp; + int needspace; + + *narg = -1; /* means that there is no macro + * call */ + /* look for the ( */ + for (;;) + { + trp->tp++; + ntok++; + if (trp->tp >= trp->lp) + { + gettokens(trp, 0); + if ((trp->lp - 1)->type == END) + { + trp->lp -= 1; + trp->tp -= ntok; + return ntok; + } + } + if (trp->tp->type == LP) + break; + if (trp->tp->type != NL) + return ntok; + } + *narg = 0; + ntok++; + ntokp = ntok; + trp->tp++; + /* search for the terminating ), possibly extending the row */ + needspace = 0; + while (parens > 0) + { + if (trp->tp >= trp->lp) + gettokens(trp, 0); + if (needspace) + { + needspace = 0; + /* makespace(trp); [rh] */ + } + if (trp->tp->type == END) + { + trp->lp -= 1; + trp->tp -= ntok; + error(ERROR, "EOF in macro arglist"); + return ntok; + } + if (trp->tp->type == NL) + { + trp->tp += 1; + adjustrow(trp, -1); + trp->tp -= 1; + /* makespace(trp); [rh] */ + needspace = 1; + continue; + } + if (trp->tp->type == LP) + parens++; + else + if (trp->tp->type == RP) + parens--; + trp->tp++; + ntok++; + } + trp->tp -= ntok; + /* Now trp->tp won't move underneath us */ + lp = bp = trp->tp + ntokp; + for (; parens >= 0; lp++) + { + if (lp->type == LP) + { + parens++; + continue; + } + if (lp->type == RP) + parens--; + if (lp->type == DSHARP) + lp->type = DSHARP1; /* ## not special in arg */ + if ((lp->type == COMMA && parens == 0) + || (parens < 0 && (lp - 1)->type != LP)) + { + if (*narg >= NARG - 1) + error(FATAL, "Sorry, too many macro arguments"); + ttr.bp = ttr.tp = bp; + ttr.lp = lp; + atr[(*narg)++] = normtokenrow(&ttr); + bp = lp + 1; + } + } + return ntok; +} + +/* + * substitute the argument list into the replacement string + * This would be simple except for ## and # + */ +void + substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr) +{ + Tokenrow tatr; + Token *tp; + int ntok, argno; + + for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;) + { + if (rtr->tp->type == SHARP) + { /* string operator */ + tp = rtr->tp; + rtr->tp += 1; + if ((argno = lookuparg(np, rtr->tp)) < 0) + { + error(ERROR, "# not followed by macro parameter"); + continue; + } + ntok = 1 + (rtr->tp - tp); + rtr->tp = tp; + insertrow(rtr, ntok, stringify(atr[argno])); + continue; + } + if (rtr->tp->type == NAME + && (argno = lookuparg(np, rtr->tp)) >= 0) + { + if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP) + || (rtr->tp != rtr->bp && (rtr->tp - 1)->type == DSHARP)) + { + copytokenrow(&tatr, atr[argno]); + makespace(&tatr, rtr->tp); + insertrow(rtr, 1, &tatr); + dofree(tatr.bp); + } + else + { + copytokenrow(&tatr, atr[argno]); + makespace(&tatr, rtr->tp); + expandrow(&tatr, "<macro>"); + insertrow(rtr, 1, &tatr); + dofree(tatr.bp); + } + continue; + } + rtr->tp++; + } +} + +/* + * Evaluate the ## operators in a tokenrow + */ +void + doconcat(Tokenrow * trp) +{ + Token *ltp, *ntp; + Tokenrow ntr; + int len; + + for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++) + { + if (trp->tp->type == DSHARP1) + trp->tp->type = DSHARP; + else + if (trp->tp->type == DSHARP) + { + int i; + char tt[NCONCAT]; + + ltp = trp->tp - 1; + ntp = trp->tp + 1; + + if (ltp < trp->bp || ntp >= trp->lp) + { + error(ERROR, "## occurs at border of replacement"); + continue; + } + + ntp = ltp; + i = 1; + len = 0; + + do + { + if (len + ntp->len + ntp->wslen > sizeof(tt)) + { + error(ERROR, "## string concatination buffer overrun"); + break; + } + + strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen, + ntp->len + ntp->wslen); + len += ntp->len + ntp->wslen; + + ntp = trp->tp + i; + i++; + } + while (ntp < trp->lp); + + tt[len] = '\0'; + setsource("<##>", -1, -1, tt, 0); + maketokenrow(3, &ntr); + gettokens(&ntr, 1); + unsetsource(); + if (ntr.bp->type == UNCLASS) + error(WARNING, "Bad token %r produced by ##", &ntr); + doconcat(&ntr); + trp->tp = ltp; + makespace(&ntr, ltp); + insertrow(trp, ntp - ltp, &ntr); + dofree(ntr.bp); + trp->tp--; + } + } +} + +/* + * tp is a potential parameter name of macro mac; + * look it up in mac's arglist, and if found, return the + * corresponding index in the argname array. Return -1 if not found. + */ +int + lookuparg(Nlist * mac, Token * tp) +{ + Token *ap; + + if (tp->type != NAME || mac->ap == NULL) + return -1; + for (ap = mac->ap->bp; ap < mac->ap->lp; ap++) + { + if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0) + return ap - mac->ap->bp; + } + return -1; +} + +/* + * Return a quoted version of the tokenrow (from # arg) + */ +#define STRLEN 512 +Tokenrow * + stringify(Tokenrow * vp) +{ + static Token t = {STRING, 0, 0, 0, NULL}; + static Tokenrow tr = {&t, &t, &t + 1, 1}; + Token *tp; + uchar s[STRLEN]; + uchar *sp = s, *cp; + int i, instring; + + *sp++ = '"'; + for (tp = vp->bp; tp < vp->lp; tp++) + { + instring = tp->type == STRING || tp->type == CCON; + if (sp + 2 * tp->len >= &s[STRLEN - 10]) + { + error(ERROR, "Stringified macro arg is too long"); + break; + } + for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++) + { + if (instring && (*cp == '"' || *cp == '\\')) + *sp++ = '\\'; + *sp++ = *cp++; + } + } + *sp++ = '"'; + *sp = '\0'; + sp = s; + t.len = strlen((char *) sp); + t.t = newstring(sp, t.len, 0); + return &tr; +} + +/* + * expand a builtin name + */ +void + builtin(Tokenrow * trp, int biname) +{ + char *op; + Token *tp; + Source *s; + + tp = trp->tp; + trp->tp++; + /* need to find the real source */ + s = cursource; + while (s && s->fd == -1) + s = s->next; + if (s == NULL) + s = cursource; + /* most are strings */ + tp->type = STRING; + if (tp->wslen) + { + *outptr++ = ' '; + tp->wslen = 1; + } + op = outptr; + *op++ = '"'; + switch (biname) + { + + case KLINENO: + tp->type = NUMBER; + op = outnum(op - 1, s->line); + break; + + case KFILE: + { + char *src = s->filename; + + while ((*op++ = *src++) != 0) + if (src[-1] == '\\') + *op++ = '\\'; + op--; + break; + } + + case KDATE: + strncpy(op, curtime + 4, 7); + strncpy(op + 7, curtime + 20, 4); + op += 11; + break; + + case KTIME: + strncpy(op, curtime + 11, 8); + op += 8; + break; + + default: + error(ERROR, "cpp botch: unknown internal macro"); + return; + } + if (tp->type == STRING) + *op++ = '"'; + tp->t = (uchar *) outptr; + tp->len = op - outptr; + outptr = op; +} diff --git a/idlc/source/preproc/makefile.mk b/idlc/source/preproc/makefile.mk new file mode 100644 index 000000000000..e6aa457e8b3d --- /dev/null +++ b/idlc/source/preproc/makefile.mk @@ -0,0 +1,75 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/.. + +PRJNAME=idlc +TARGET=idlcpp +TARGETTYPE=CUI + +# --- Settings ----------------------------------------------------- + +NO_DEFAULT_STL=TRUE +LIBSALCPPRT=$(0) + +.INCLUDE : settings.mk + +# --- Files -------------------------------------------------------- + +OBJFILES= \ + $(OBJ)$/cpp.obj \ + $(OBJ)$/eval.obj \ + $(OBJ)$/include.obj \ + $(OBJ)$/lex.obj \ + $(OBJ)$/macro.obj \ + $(OBJ)$/nlist.obj \ + $(OBJ)$/tokens.obj \ + $(OBJ)$/unix.obj + +# --- CPP ------------------------------------------------------- + +APP1TARGET= $(TARGET) +APP1RPATH=SDK + +.IF "$(GUI)" != "UNX" +.IF "$(COM)" != "GCC" +APP1OBJS=$(OBJ)$/cpp.obj +.ENDIF +.ENDIF + +APP1LIBS= $(LB)$/idlcpp.lib + +.IF "$(HAVE_GETOPT)" != "YES" +.IF "$(GUI)" == "WNT" +APP1STDLIBS=gnu_getopt.lib +.ENDIF +.ENDIF + +# --- Targets ------------------------------------------------------ + +.INCLUDE : target.mk + diff --git a/idlc/source/preproc/nlist.c b/idlc/source/preproc/nlist.c new file mode 100644 index 000000000000..f41313c22aac --- /dev/null +++ b/idlc/source/preproc/nlist.c @@ -0,0 +1,143 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "cpp.h" + +extern int Cplusplus; +Nlist *kwdefined; +char wd[128]; + +/* + ER: Tabelle extra gross gemacht, da es anscheinend ein Problem mit der + der Verkettung gibt, irgendwann irgendwo wird mal ein nlist->next + ueberschrieben, was in eineme SIGSEGV resultiert. + Den GDB mit watchpoint hab ich aber nach 2 Tagen abgebrochen.. + so loeppt's jedenfalls erstmal.. + */ +#define NLSIZE 15000 + +static Nlist *nlist[NLSIZE]; + +struct kwtab +{ + char *kw; + int val; + int flag; +} kwtab[] = + +{ + { "if", KIF, ISKW }, + { "ifdef", KIFDEF, ISKW }, + { "ifndef", KIFNDEF, ISKW }, + { "elif", KELIF, ISKW }, + { "else", KELSE, ISKW }, + { "endif", KENDIF, ISKW }, + { "include", KINCLUDE, ISKW }, + { "include_next", KINCLUDENEXT, ISKW }, + { "import", KIMPORT, ISKW }, + { "define", KDEFINE, ISKW }, + { "undef", KUNDEF, ISKW }, + { "line", KLINE, ISKW }, + { "error", KERROR, ISKW }, + { "pragma", KPRAGMA, ISKW }, + { "ident", KIDENT, ISKW }, + { "eval", KEVAL, ISKW }, + { "defined", KDEFINED, ISDEFINED + ISUNCHANGE }, + { "machine", KMACHINE, ISDEFINED + ISUNCHANGE }, + { "__LINE__", KLINENO, ISMAC + ISUNCHANGE }, + { "__FILE__", KFILE, ISMAC + ISUNCHANGE }, + { "__DATE__", KDATE, ISMAC + ISUNCHANGE }, + { "__TIME__", KTIME, ISMAC + ISUNCHANGE }, + { "__STDC__", KSTDC, ISUNCHANGE }, + { NULL, 0, 0 } +}; + +unsigned long namebit[077 + 1]; + +void + setup_kwtab(void) +{ + struct kwtab *kp; + Nlist *np; + Token t; + static Token deftoken[1] = {{NAME, 0, 0, 7, (uchar *) "defined"}}; + static Tokenrow deftr = {deftoken, deftoken, deftoken + 1, 1}; + + for (kp = kwtab; kp->kw; kp++) + { + t.t = (uchar *) kp->kw; + t.len = strlen(kp->kw); + np = lookup(&t, 1); + np->flag = (char) kp->flag; + np->val = (char) kp->val; + if (np->val == KDEFINED) + { + kwdefined = np; + np->val = NAME; + np->vp = &deftr; + np->ap = 0; + } + } +} + +Nlist * + lookup(Token * tp, int install) +{ + unsigned int h; + Nlist *np; + uchar *cp, *cpe; + + h = 0; + for (cp = tp->t, cpe = cp + tp->len; cp < cpe;) + h += *cp++; + h %= NLSIZE; + np = nlist[h]; + while (np) + { + if (*tp->t == *np->name && tp->len == (unsigned int)np->len + && strncmp((char *)tp->t, (char *)np->name, tp->len) == 0) + return np; + np = np->next; + } + if (install) + { + np = new(Nlist); + np->vp = NULL; + np->ap = NULL; + np->flag = 0; + np->val = 0; + np->len = tp->len; + np->name = newstring(tp->t, tp->len, 0); + np->next = nlist[h]; + nlist[h] = np; + quickset(tp->t[0], tp->len > 1 ? tp->t[1] : 0); + return np; + } + return NULL; +} diff --git a/idlc/source/preproc/tokens.c b/idlc/source/preproc/tokens.c new file mode 100644 index 000000000000..23ab88a5a9e3 --- /dev/null +++ b/idlc/source/preproc/tokens.c @@ -0,0 +1,534 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__)) +#include <io.h> +#else +#include <unistd.h> +#endif +#include "cpp.h" + + +static char wbuf[4 * OBS]; +static char *wbp = wbuf; +static int EBCDIC_ExternTokenDetected = 0; +static int EBCDIC_StartTokenDetected = 0; + +unsigned char toLatin1[256] = +{ + 0x00, 0x01, 0x02, 0x03, 0x9c, 0x09, 0x86, 0x7f, 0x97, 0x8d, + 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0x9d, 0x0a, 0x08, 0x87, 0x18, 0x19, 0x92, 0x8f, 0x1c, 0x1d, + 0x1e, 0x1f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x17, 0x1b, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, 0x90, 0x91, + 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, 0x98, 0x99, 0x9a, 0x9b, + 0x14, 0x15, 0x9e, 0x1a, 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, + 0xe3, 0xe5, 0xe7, 0xf1, 0xa2, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, + 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, 0xec, 0xdf, + 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x5e, 0x2d, 0x2f, 0xc2, 0xc4, + 0xc0, 0xc1, 0xc3, 0xc5, 0xc7, 0xd1, 0xa6, 0x2c, 0x25, 0x5f, + 0x3e, 0x3f, 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, + 0xcc, 0x60, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, + 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, 0xb0, 0x6a, 0x6b, 0x6c, + 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, + 0xc6, 0xa4, 0xb5, 0x7e, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0x5b, 0xde, 0xae, 0xac, 0xa3, + 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, 0xbd, 0xbe, 0xdd, 0xa8, + 0xaf, 0x5d, 0xb4, 0xd7, 0x7b, 0x41, 0x42, 0x43, 0x44, 0x45, + 0x46, 0x47, 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, + 0x7d, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, + 0xb9, 0xfb, 0xfc, 0xf9, 0xfa, 0xff, 0x5c, 0xf7, 0x53, 0x54, + 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, + 0xd3, 0xd5, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xb3, 0xdb, 0xdc, 0xd9, 0xda, 0x9f +}; + +#define MASK "\\x%x" + +int + memcpy_EBCDIC( char * pwbuf, uchar *p, int len ) +{ + int currpos = 0; + int processedchars = 0; + + if( len == 0 ) + return 0; + + if( len == 1 ) + { + *pwbuf = *p; + return 1; + } + + /* copy spaces until " or ' */ + while( (p[ processedchars ] != '\"') && (p[ processedchars ] != '\'') ) + pwbuf[ currpos++ ] = p[ processedchars++ ]; + + /* copy first " or ' */ + pwbuf[ currpos++ ] = p[ processedchars++ ]; + + /* convert all characters until " or ' */ + while( processedchars < (len - 1) ) + { + if( p[ processedchars ] == '\\' ) + { + switch( p[ ++processedchars ] ) + { + case 'n': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\n'] ); + processedchars++; + break; + + case 't': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\t'] ); + processedchars++; + break; + + case 'v': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\v'] ); + processedchars++; + break; + + case 'b': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\b'] ); + processedchars++; + break; + + case 'r': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\r'] ); + processedchars++; + break; + + case 'f': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\f'] ); + processedchars++; + break; + + case 'a': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\a'] ); + processedchars++; + break; + + case '\\': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\\'] ); + processedchars++; + break; + + case '?': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\?'] ); + processedchars++; + break; + + case '\'': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\''] ); + processedchars++; + break; + + case '"': + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1['\"'] ); + processedchars++; + break; + + /* octal coded character? -> copy */ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + { + int startpos = currpos; + + pwbuf[ currpos++ ] = '\\'; + + while( p[ processedchars ] >= '0' && p[ processedchars ] <= '7' && (currpos < startpos + 4) ) + pwbuf[ currpos++ ] = (unsigned char)p[ processedchars++ ]; + break; + } + + /* hex coded character? -> copy */ + case 'x': + case 'X': + { + int startpos = currpos; + + pwbuf[ currpos++ ] = '\\'; + pwbuf[ currpos++ ] = 'x'; + processedchars++; + + while( isxdigit( p[ processedchars ] ) && (currpos < startpos + 4) ) + pwbuf[ currpos++ ] = (unsigned char)p[ processedchars++ ]; + break; + } + + } + } + else + currpos += sprintf( &pwbuf[ currpos ], MASK, toLatin1[p[ processedchars++ ]] ); + + } + + /* copy last " or ' */ + pwbuf[ currpos++ ] = p[ processedchars ]; + + return currpos; +} + +void + maketokenrow(int size, Tokenrow * trp) +{ + trp->max = size; + if (size > 0) + trp->bp = (Token *) domalloc(size * sizeof(Token)); + else + trp->bp = NULL; + trp->tp = trp->bp; + trp->lp = trp->bp; +} + +Token * + growtokenrow(Tokenrow * trp) +{ + int ncur = trp->tp - trp->bp; + int nlast = trp->lp - trp->bp; + + trp->max = 3 * trp->max / 2 + 1; + trp->bp = (Token *) realloc(trp->bp, trp->max * sizeof(Token)); + trp->lp = &trp->bp[nlast]; + trp->tp = &trp->bp[ncur]; + return trp->lp; +} + +/* + * Compare a row of tokens, ignoring the content of WS; return !=0 if different + */ +int + comparetokens(Tokenrow * tr1, Tokenrow * tr2) +{ + Token *tp1, *tp2; + + tp1 = tr1->tp; + tp2 = tr2->tp; + if (tr1->lp - tp1 != tr2->lp - tp2) + return 1; + for (; tp1 < tr1->lp; tp1++, tp2++) + { + if (tp1->type != tp2->type + || (tp1->wslen == 0) != (tp2->wslen == 0) + || tp1->len != tp2->len + || strncmp((char *) tp1->t, (char *) tp2->t, tp1->len) != 0) + return 1; + } + return 0; +} + +/* + * replace ntok tokens starting at dtr->tp with the contents of str. + * tp ends up pointing just beyond the replacement. + * Canonical whitespace is assured on each side. + */ +void + insertrow(Tokenrow * dtr, int ntok, Tokenrow * str) +{ + int nrtok = rowlen(str); + + dtr->tp += ntok; + adjustrow(dtr, nrtok - ntok); + dtr->tp -= ntok; + movetokenrow(dtr, str); + dtr->tp += nrtok; +} + +/* + * make sure there is WS before trp->tp, if tokens might merge in the output + */ +void + makespace(Tokenrow * trp, Token * ntp) +{ + uchar *tt; + Token *tp = trp->tp; + + if (tp >= trp->lp) + return; + + if (ntp->wslen) + { + tt = newstring(tp->t, tp->len, ntp->wslen); + strncpy((char *)tt, (char *)ntp->t - ntp->wslen, ntp->wslen); + tp->t = tt + ntp->wslen; + tp->wslen = ntp->wslen; + tp->flag |= XPWS; + } +} + +/* + * Copy an entire tokenrow into another, at tp. + * It is assumed that there is enough space. + * Not strictly conforming. + */ +void + movetokenrow(Tokenrow * dtr, Tokenrow * str) +{ + int nby; + + /* nby = sizeof(Token) * (str->lp - str->bp); */ + nby = (char *) str->lp - (char *) str->bp; + memmove(dtr->tp, str->bp, nby); +} + +/* + * Move the tokens in a row, starting at tr->tp, rightward by nt tokens; + * nt may be negative (left move). + * The row may need to be grown. + * Non-strictly conforming because of the (char *), but easily fixed + */ +void + adjustrow(Tokenrow * trp, int nt) +{ + int nby, size; + + if (nt == 0) + return; + size = (trp->lp - trp->bp) + nt; + while (size > trp->max) + growtokenrow(trp); + /* nby = sizeof(Token) * (trp->lp - trp->tp); */ + nby = (char *) trp->lp - (char *) trp->tp; + if (nby) + memmove(trp->tp + nt, trp->tp, nby); + trp->lp += nt; +} + +/* + * Copy a row of tokens into the destination holder, allocating + * the space for the contents. Return the destination. + */ +Tokenrow * + copytokenrow(Tokenrow * dtr, Tokenrow * str) +{ + int len = rowlen(str); + + maketokenrow(len, dtr); + movetokenrow(dtr, str); + dtr->lp += len; + return dtr; +} + +/* + * Produce a copy of a row of tokens. Start at trp->tp. + * The value strings are copied as well. The first token + * has WS available. + */ +Tokenrow * + normtokenrow(Tokenrow * trp) +{ + Token *tp; + Tokenrow *ntrp = new(Tokenrow); + int len; + + len = trp->lp - trp->tp; + if (len <= 0) + len = 1; + maketokenrow(len, ntrp); + for (tp = trp->tp; tp < trp->lp; tp++) + { + *ntrp->lp = *tp; + if (tp->len) + { + ntrp->lp->t = newstring(tp->t, tp->len, 1); + *ntrp->lp->t++ = ' '; + if (tp->wslen) + ntrp->lp->wslen = 1; + } + ntrp->lp++; + } + if (ntrp->lp > ntrp->bp) + ntrp->bp->wslen = 0; + return ntrp; +} + +/* + * Debugging + */ +void + peektokens(Tokenrow * trp, char *str) +{ + Token *tp; + + tp = trp->tp; + flushout(); + if (str) + fprintf(stderr, "%s ", str); + if (tp < trp->bp || tp > trp->lp) + fprintf(stderr, "(tp offset %ld) ", (long)(tp - trp->bp)); + for (tp = trp->bp; tp < trp->lp && tp < trp->bp + 32; tp++) + { + if (tp->type != NL) + { + int c = tp->t[tp->len]; + + tp->t[tp->len] = 0; + fprintf(stderr, "%s", tp->t); + tp->t[tp->len] = (uchar) c; + } + fprintf(stderr, tp == trp->tp ? "{%x*} " : "{%x} ", tp->type); + } + fprintf(stderr, "\n"); + fflush(stderr); +} + +void + puttokens(Tokenrow * trp) +{ + Token *tp; + int len; + uchar *p; + + if (Vflag) + peektokens(trp, ""); + tp = trp->bp; + for (; tp < trp->lp; tp++) + { + if (tp->type != NL) + { + len = tp->len + tp->wslen; + p = tp->t - tp->wslen; + + /* EBCDIC to ANSI conversion requested? */ + if( Aflag ) + { + /* keyword __ToLatin1__ found? -> do conversion! */ + if( EBCDIC_StartTokenDetected ) + { + /* previous token was 'extern'? -> don't convert current token! */ + if( EBCDIC_ExternTokenDetected ) + { + EBCDIC_ExternTokenDetected = 0; + memcpy(wbp, p, len); + } + else + { + /* current token is keyword 'extern'? -> don't convert following token! */ + if( (tp->wslen == 0) && (strncmp( (char*)p, "extern", len ) == 0) ) + { + EBCDIC_ExternTokenDetected = 1; + memcpy(wbp, p, len); + } + else + { + /* token is string or char? -> process EBCDIC to ANSI conversion */ + if ((tp->type == STRING) || (tp->type == CCON)) + len = memcpy_EBCDIC(wbp, p, len); + else + memcpy(wbp, p, len); + } + } + } + else + /* keyword __ToLatin1__ found? -> don't copy keyword and start conversion */ + if( (tp->type == NAME) && (strncmp( (char*)p, "__ToLatin1__", len) == 0) ) + { + EBCDIC_StartTokenDetected = 1; + len = 0; + } + else + memcpy(wbp, p, len); + } + else + memcpy(wbp, p, len); + + wbp += len; + } + else + *wbp++ = '\n'; + + if (wbp >= &wbuf[OBS]) + { + if (write(1, wbuf, OBS) != OBS) + error(ERROR, "short write!"); + if (wbp > &wbuf[OBS]) + memcpy(wbuf, wbuf + OBS, wbp - &wbuf[OBS]); + wbp -= OBS; + } + } + trp->tp = tp; + if (cursource->fd == 0) + flushout(); +} + +void + flushout(void) +{ + if (wbp > wbuf) + { + if (write(1, wbuf, wbp - wbuf) != wbp - wbuf) + error(ERROR, "short write!"); + wbp = wbuf; + } +} + +/* + * turn a row into just a newline + */ +void + setempty(Tokenrow * trp) +{ + trp->tp = trp->bp; + trp->lp = trp->bp + 1; + *trp->bp = nltoken; +} + +/* + * generate a number + */ +char * + outnum(char *p, int n) +{ + if (n >= 10) + p = outnum(p, n / 10); + *p++ = (char) (n % 10 + '0'); + return p; +} + +/* + * allocate and initialize a new string from s, of length l, at offset o + * Null terminated. + */ +uchar * + newstring(uchar * s, int l, int o) +{ + uchar *ns = (uchar *) domalloc(l + o + 1); + + ns[l + o] = '\0'; + return (uchar *) strncpy((char *) ns + o, (char *) s, l) - o; +} diff --git a/idlc/source/preproc/unix.c b/idlc/source/preproc/unix.c new file mode 100644 index 000000000000..4997e317e697 --- /dev/null +++ b/idlc/source/preproc/unix.c @@ -0,0 +1,247 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ +#include <stdio.h> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#if (defined(_WIN32) || defined(_MSDOS) || defined(__IBMC__)) +#include <io.h> +#include <sys/stat.h> +#include <external/glibc/getopt.h> +#else +#include <unistd.h> +#endif + +#include "cpp.h" + +extern char rcsid[]; + +int Pflag = 0; /* print no line information */ +int Iflag = 0; /* print includes */ +int Mflag = 0; /* print macor expansion */ +int Aflag = 0; /* translate character sets */ +int Xflag = 0; /* print pragma for include/import */ +int Vflag = 0; /* verbose flag */ +int Cflag = 0; /* do not remove any comments */ +int Cplusplus = 0; + +extern void setup_kwtab(void); + +void + setup(int argc, char **argv) +{ + int c, fd, i, n; + char *fp, *dp; + Tokenrow tr; + + setup_kwtab(); + while ((c = getopt(argc, argv, "NOPV:I:D:U:F:A:X:u:l:+")) != -1) + switch (c) + { + case 'N': + for (i = 0; i < NINCLUDE; i++) + if (includelist[i].always == 1) + includelist[i].deleted = 1; + break; + + case 'I': + for (i = NINCLUDE - 2; i >= 0; i--) + { + if (includelist[i].file == NULL) + { + includelist[i].always = 1; + includelist[i].file = optarg; + break; + } + } + if (i < 0) + error(FATAL, "Too many -I directives"); + break; + + case 'D': + case 'U': + case 'A': + setsource("<cmdarg>", -1, -1, optarg, 0); + maketokenrow(3, &tr); + gettokens(&tr, 1); + doadefine(&tr, c); + unsetsource(); + break; + + case 'P': /* Lineinfo */ + Pflag++; + break; + + case 'V': + for (n = 0; (c = optarg[n]) != '\0'; n++) + switch (c) + { + case 'i': + Iflag++; + break; + + case 'm': + Mflag = 1; + break; + + case 'x': + Mflag = 2; + break; + + case 't': + Vflag++; + break; + + case 'v': + fprintf(stderr, "%s %s\n", argv[0], rcsid); + break; + + default: + error(WARNING, "Unknown verbose option %c", c); + } + break; + + case 'X': + for (n = 0; (c = optarg[n]) != '\0'; n++) + switch (c) + { + case 'a': + Aflag++; + break; + + case 'i': + Xflag++; + break; + + case 'c': + Cflag++; + break; + + case 'w': + dp = &optarg[n + 1]; + n += strlen(dp); + while (isspace(*dp)) dp++; + + for (i = NINCLUDE - 1; i >= 0; i--) + { + if (wraplist[i].file == NULL) + { + wraplist[i].file = dp; + break; + } + } + if (i < 0) + error(WARNING, "Too many -Xw directives"); + break; + + default: + error(WARNING, "Unknown extension option %c", c); + } + break; + + case '+': + Cplusplus++; + break; + + case 'u': /* -undef fuer GCC (dummy) */ + case 'l': /* -lang-c++ fuer GCC (dummy) */ + break; + + default: + break; + } + dp = "."; + fp = "<stdin>"; + fd = 0; + if (optind < argc) + { + if ((fp = strrchr(argv[optind], '/')) != NULL) + { + int len = fp - argv[optind]; + + dp = (char *) newstring((uchar *) argv[optind], len + 1, 0); + dp[len] = '\0'; + } + fp = (char *) newstring((uchar *) argv[optind], strlen(argv[optind]), 0); + if ((fd = open(fp, O_RDONLY)) < 0) + error(FATAL, "Can't open input file %s", fp); + } + + if (optind + 1 < argc) + { +#if defined(WNT) && (_MSC_VER >= 1400) + int fdo = creat(argv[optind + 1], _S_IREAD | _S_IWRITE ); +#else + int fdo = creat(argv[optind + 1], 0666 ); +#endif + if (fdo < 0) + error(FATAL, "Can't open output file %s", argv[optind + 1]); + + dup2(fdo, 1); + } + includelist[NINCLUDE - 1].always = 0; + includelist[NINCLUDE - 1].file = dp; + setsource(fp, -1, fd, NULL, 0); +} + + +/* memmove is defined here because some vendors don't provide it at + all and others do a terrible job (like calling malloc) */ + +#if !defined(__IBMC__) && !defined(WNT) && !defined(__GLIBC__) + +void * + memmove(void *dp, const void *sp, size_t n) +{ + unsigned char *cdp, *csp; + + if (n <= 0) + return 0; + cdp = dp; + csp = (unsigned char *) sp; + if (cdp < csp) + { + do + { + *cdp++ = *csp++; + } while (--n); + } + else + { + cdp += n; + csp += n; + do + { + *--cdp = *--csp; + } while (--n); + } + return 0; +} + +#endif diff --git a/idlc/source/scanner.ll b/idlc/source/scanner.ll new file mode 100644 index 000000000000..4125195f5916 --- /dev/null +++ b/idlc/source/scanner.ll @@ -0,0 +1,523 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +%{ +/* + * scanner.ll - Lexical scanner for IDLC 1.0 + */ + +#include <ctype.h> +#include <stdlib.h> +#include <string.h> + +#ifndef _IDLC_IDLC_HXX_ +#include <idlc/idlc.hxx> +#endif +#ifndef _IDLC_ERRORHANDLER_HXX_ +#include <idlc/errorhandler.hxx> +#endif +#ifndef _IDLC_FEHELPER_HXX_ +#include <idlc/fehelper.hxx> +#endif + +#include "attributeexceptions.hxx" + +class AstExpression; +class AstArray; +class AstMember; + +#include <parser.hxx> + +sal_Int32 beginLine = 0; +::rtl::OString docu; + +static int asciiToInteger(char const * s, sal_Int64 * sval, sal_uInt64 * uval) { + bool neg = false; + if (*s == '-') { + neg = true; + ++s; + } + unsigned int base = 10; + if (*s == '0') { + base = 8; + ++s; + if (*s == 'X' || *s == 'x') { + base = 16; + ++s; + } + } + sal_uInt64 val = 0; + for (; *s != 0; ++s) { + unsigned int n; + if (*s >= '0' && *s <= '9') { + n = *s - '0'; + } else { + switch (*s) { + case 'A': + case 'a': + n = 10; + break; + case 'B': + case 'b': + n = 11; + break; + case 'C': + case 'c': + n = 12; + break; + case 'D': + case 'd': + n = 13; + break; + case 'E': + case 'e': + n = 14; + break; + case 'F': + case 'f': + n = 15; + break; + default: + goto done; + } + } + // The following guarantees the invariant val <= SAL_MAX_UINT64 (because + // base and n are sufficiently small), *if* + // std::numeric_limits<sal_uInt64>::max() == SAL_MAX_UINT64: + sal_uInt64 nval = val * base + n; + if (nval < val) { + idlc()->error()->syntaxError( + PS_NoState, idlc()->getLineNumber(), + "integral constant too large"); + val = 0; + break; + } + val = nval; + } + done: + if (neg) { + if (val < SAL_CONST_UINT64(0x8000000000000000)) { + *sval = -static_cast< sal_Int64 >(val); + } else if (val == SAL_CONST_UINT64(0x8000000000000000)) { + *sval = SAL_MIN_INT64; + } else { + idlc()->error()->syntaxError( + PS_NoState, idlc()->getLineNumber(), + "negative integral constant too large"); + *sval = 0; + } + return IDL_INTEGER_LITERAL; + } else if (val <= static_cast< sal_uInt64 >(SAL_MAX_INT64)) { + *sval = static_cast< sal_Int64 >(val); + return IDL_INTEGER_LITERAL; + } else { + *uval = val; + return IDL_INTEGER_ULITERAL; + } +} + +static double asciiToFloat(const sal_Char *s) +{ + double d = 0.0; + double e, k; + sal_Int32 neg = 0, negexp = 0; + + if (*s == '-') + { + neg = 1; + s++; + } + while (*s >= '0' && *s <= '9') + { + d = (d * 10) + *s - '0'; + s++; + } + if (*s == '.') + { + s++; + e = 10; + while (*s >= '0' && *s <= '9') + { + d += (*s - '0') / (e * 1.0); + e *= 10; + s++; + } + } + if (*s == 'e' || *s == 'E') + { + s++; + if (*s == '-') + { + negexp = 1; + s++; + } else + { + if (*s == '+') + s++; + e = 0; + while (*s >= '0' && *s <= '9') + { + e = (e * 10) + *s - '0'; + s++; + } + if (e > 0) + { + for (k = 1; e > 0; k *= 10, e--) ; + if (negexp) + d /= k; + else + d *= k; + } + } + } + if (neg) d *= -1.0; + return d; +} + +static void idlParsePragma(sal_Char* pPragma) +{ + ::rtl::OString pragma(pPragma); + sal_Int32 index = pragma.indexOf("include"); + sal_Char* begin = pPragma + index + 8; + sal_Char* offset = begin; + while (*offset != ',') offset++; + //::rtl::OString include = pragma.copy(index + 8, offset - begin); + idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin))); +} + +static void parseLineAndFile(sal_Char* pBuf) +{ + sal_Char *r = pBuf; + sal_Char *h; + sal_Bool bIsInMain = sal_False; + + /* Skip initial '#' */ + if (*r != '#') + return; + + /* Find line number */ + for (r++; *r == ' ' || *r == '\t' || isalpha(*r); r++) ; + h = r; + for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ; + *r++ = 0; + idlc()->setLineNumber((sal_uInt32)atol(h)); + + /* Find file name, if present */ + for (; *r != '"'; r++) + { + if (*r == '\n' || *r == '\0') + return; + } + h = ++r; + for (; *r != '"'; r++) ; + *r = 0; + if (*h == '\0') + idlc()->setFileName(::rtl::OString("standard input")); + else + idlc()->setFileName(::rtl::OString(h)); + + bIsInMain = (idlc()->getFileName() == idlc()->getRealFileName()) ? sal_True : sal_False; + idlc()->setInMainfile(bIsInMain); +} + +// Suppress any warnings from generated code: +#if defined __GNUC__ +#pragma GCC system_header +#elif defined __SUNPRO_CC +#pragma disable_warn +#elif defined _MSC_VER +#pragma warning(push, 1) +/**/ +#ifdef yywrap +#undef yywrap +#define yywrap() 1 +#endif +/**/ +#endif +%} + +%option noyywrap +%option never-interactive + +%x DOCU +%x COMMENT + +DIGIT [0-9] +OCT_DIGIT [0-7] +HEX_DIGIT [a-fA-F0-9] +CAPITAL [A-Z] +ALPHA [a-zA-Z] +INT_LITERAL [1-9][0-9]* +OCT_LITERAL 0{OCT_DIGIT}* +HEX_LITERAL (0x|0X){HEX_DIGIT}* + +IDENTIFIER_NEW ({ALPHA}({ALPHA}|{DIGIT})*)|({CAPITAL}("_"?({ALPHA}|{DIGIT})+)*) +IDENTIFIER ("_"?({ALPHA}|{DIGIT})+)* + +%% + +[ \t\r]+ ; /* eat up whitespace */ +[\n] { + idlc()->incLineNumber(); +} + +attribute return IDL_ATTRIBUTE; +bound return IDL_BOUND; +case return IDL_CASE; +const return IDL_CONST; +constants return IDL_CONSTANTS; +constrained return IDL_CONSTRAINED; +default return IDL_DEFAULT; +enum return IDL_ENUM; +exception return IDL_EXCEPTION; +interface return IDL_INTERFACE; +maybeambiguous return IDL_MAYBEAMBIGUOUS; +maybedefault return IDL_MAYBEDEFAULT; +maybevoid return IDL_MAYBEVOID; +module return IDL_MODULE; +needs return IDL_NEEDS; +observes return IDL_OBSERVES; +optional return IDL_OPTIONAL; +property return IDL_PROPERTY; +raises return IDL_RAISES; +readonly return IDL_READONLY; +removable return IDL_REMOVEABLE; +service return IDL_SERVICE; +sequence return IDL_SEQUENCE; +singleton return IDL_SINGLETON; +struct return IDL_STRUCT; +switch return IDL_SWITCH; +transient return IDL_TRANSIENT; +typedef return IDL_TYPEDEF; +union return IDL_UNION; + +any return IDL_ANY; +boolean return IDL_BOOLEAN; +byte return IDL_BYTE; +char return IDL_CHAR; +double return IDL_DOUBLE; +float return IDL_FLOAT; +hyper return IDL_HYPER; +long return IDL_LONG; +short return IDL_SHORT; +string return IDL_STRING; +type return IDL_TYPE; +unsigned return IDL_UNSIGNED; +void return IDL_VOID; + +TRUE return IDL_TRUE; +True return IDL_TRUE; +FALSE return IDL_FALSE; +False return IDL_FALSE; + +in return IDL_IN; +out return IDL_OUT; +inout return IDL_INOUT; +oneway return IDL_ONEWAY; + +get return IDL_GET; +set return IDL_SET; + +published return IDL_PUBLISHED; + +"..." return IDL_ELLIPSIS; + +("-")?{INT_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{OCT_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{HEX_LITERAL}+(l|L|u|U)? { + return asciiToInteger(yytext, &yylval.ival, &yylval.uval); + } + +("-")?{DIGIT}+(e|E){1}(("+"|"-")?{DIGIT}+)+(f|F)? | +("-")?"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? | +("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? { + yylval.dval = asciiToFloat( yytext ); + return IDL_FLOATING_PT_LITERAL; + } + +{IDENTIFIER} { + yylval.sval = new ::rtl::OString(yytext); + return IDL_IDENTIFIER; + } + +\<\< { + yylval.strval = yytext; + return IDL_LEFTSHIFT; + } +\>\> { + yylval.strval = yytext; + return IDL_RIGHTSHIFT; + } +\:\: { + yylval.strval = yytext; + return IDL_SCOPESEPARATOR; + } + +"/*" { + BEGIN( COMMENT ); + docu = ::rtl::OString(); + beginLine = idlc()->getLineNumber(); + } + +"/***" { + BEGIN( COMMENT ); + docu = ::rtl::OString(); + beginLine = idlc()->getLineNumber(); + } + +<COMMENT>[^*]+ { + docu += ::rtl::OString(yytext); + } + +<COMMENT>"*"[^*/]+ { + docu += ::rtl::OString(yytext); + } + +<COMMENT>"**" { + docu += ::rtl::OString(yytext); + } + +<COMMENT>[*]+"/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + BEGIN( INITIAL ); + } + +"/**" { + BEGIN( DOCU ); + docu = ::rtl::OString(); + beginLine = idlc()->getLineNumber(); + } + +<DOCU>[^*\n]+ { + docu += ::rtl::OString(yytext); + } + +<DOCU>"\n"[ \t]*"*"{1} { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += ::rtl::OString("\n"); + } + +<DOCU>"\n" { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += ::rtl::OString(yytext); + } + +<DOCU>"*"[^*^/\n]* { + docu += ::rtl::OString(yytext); + } + +<DOCU>"\n"[ \t]*"*/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + if ( (nIndex = docu.indexOf("/*")) >= 0 || (nIndex = docu.indexOf("///")) >= 0 ) + { + if ( 0 != nIndex && + (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') ) + idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(), + "nested documentation strings are not allowed!"); + } + idlc()->setDocumentation(docu); + BEGIN( INITIAL ); + } + +<DOCU>"*/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { docu.getToken( 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 ) + { + if ( 0 != nIndex && + (docu.getStr()[nIndex - 1] != '"' && docu.getStr()[nIndex - 1] != ':') ) + idlc()->error()->syntaxError(PS_NoState, idlc()->getLineNumber(), + "nested documentation strings are not allowed!"); + } + idlc()->setDocumentation(docu); + BEGIN( INITIAL ); + } + +"//"[^/]{1}.*"\n" { + /* only a comment */ + ::rtl::OString docStr(yytext); + docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); + docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); + docStr = docStr.trim(); + idlc()->incLineNumber(); + } + +"///".*"\n" { + ::rtl::OString docStr(yytext); + docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); + docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); + docStr = docStr.trim(); + idlc()->incLineNumber(); + idlc()->setDocumentation(docStr); + } + +. return yytext[0]; + +^#[ \t]*line[ \t]*[0-9]*" ""\""[^\"]*"\""\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*" ""\""[^\"]*"\""" "[0-9]*\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*" ""\""[^\"]*"\""\n { + parseLineAndFile(yytext); +} + +^#[ \t]*[0-9]*\n { + parseLineAndFile(yytext); +} + +^#[ \t]*ident.*\n { + /* ignore cpp ident */ + idlc()->incLineNumber(); +} + +^#[ \t]*pragma[ \t].*\n { /* remember pragma */ + idlParsePragma(yytext); + idlc()->incLineNumber(); +} + +%% diff --git a/idlc/source/wrap_parser.cxx b/idlc/source/wrap_parser.cxx new file mode 100644 index 000000000000..5b9abfbf417a --- /dev/null +++ b/idlc/source/wrap_parser.cxx @@ -0,0 +1,31 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" + +#include "parser.cxx" diff --git a/idlc/source/wrap_scanner.cxx b/idlc/source/wrap_scanner.cxx new file mode 100644 index 000000000000..f87bc4591c7b --- /dev/null +++ b/idlc/source/wrap_scanner.cxx @@ -0,0 +1,31 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_idlc.hxx" + +#include "scanner.cxx" |