diff options
Diffstat (limited to '')
78 files changed, 14258 insertions, 0 deletions
diff --git a/idlc/CustomTarget_parser_test.mk b/idlc/CustomTarget_parser_test.mk new file mode 100644 index 000000000..f8c7632bd --- /dev/null +++ b/idlc/CustomTarget_parser_test.mk @@ -0,0 +1,91 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CustomTarget_CustomTarget,idlc/parser_test)) + +# this target is phony to run it every time +.PHONY : $(call gb_CustomTarget_get_target,idlc/parser_test) + +$(call gb_CustomTarget_get_target,idlc/parser_test) : \ + $(call gb_Executable_get_runtime_dependencies,idlc) \ + $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/attribute.tests \ + $(SRCDIR)/idlc/test/parser/constant.tests \ + $(SRCDIR)/idlc/test/parser/constructor.tests \ + $(SRCDIR)/idlc/test/parser/conversion.tests \ + $(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \ + $(SRCDIR)/idlc/test/parser/methodoverload.tests \ + $(SRCDIR)/idlc/test/parser/polystruct.tests \ + $(SRCDIR)/idlc/test/parser/published.tests \ + $(SRCDIR)/idlc/test/parser/struct.tests \ + $(SRCDIR)/idlc/test/parser/typedef.tests \ + | $(call gb_CustomTarget_get_workdir,idlc/parser_test)/.dir +ifneq ($(gb_SUPPRESS_TESTS),) + @true +else + $(call gb_Helper_abbreviate_dirs,( \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/attribute.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/constant.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/constructor.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/conversion.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/interfaceinheritance.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/methodoverload.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/oldstyle.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/polystruct.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/published.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/struct.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {} && \ + $(PERL) $(SRCDIR)/solenv/bin/exectest.pl \ + $(SRCDIR)/idlc/test/parser/typedef.tests \ + $(call gb_CustomTarget_get_workdir,idlc/parser_test)/in.idl 0 \ + $(call gb_Executable_get_command,idlc) \ + -O $(call gb_CustomTarget_get_workdir,idlc/parser_test) {}) \ + > $@.log 2>&1 || (cat $@.log && false)) +endif + +# vim: set noet sw=4 ts=4: diff --git a/idlc/Executable_idlc.mk b/idlc/Executable_idlc.mk new file mode 100644 index 000000000..8af0c40f1 --- /dev/null +++ b/idlc/Executable_idlc.mk @@ -0,0 +1,81 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Executable_Executable,idlc)) + +$(eval $(call gb_Executable_set_include,idlc,\ + -I$(SRCDIR)/idlc/inc \ + -I$(SRCDIR)/idlc/source \ + $$(INCLUDE) \ +)) + +$(eval $(call gb_Executable_use_externals,idlc,\ + boost_headers \ +)) + +$(eval $(call gb_Executable_use_libraries,idlc,\ + reg \ + $(if $(filter TRUE,$(DISABLE_DYNLOADING)),store) \ + sal \ + salhelper \ +)) + +$(eval $(call gb_Executable_add_grammars,idlc,\ + idlc/source/parser \ +)) + +$(eval $(call gb_Executable_add_scanners,idlc,\ + idlc/source/scanner \ +)) + +ifneq (,$(SYSTEM_UCPP)) + +$(eval $(call gb_Executable_add_defs,idlc,\ + -DSYSTEM_UCPP \ + -DUCPP=\"file://$(SYSTEM_UCPP)\" \ +)) + +ifneq ($(SYSTEM_UCPP_IS_GCC),) +$(eval $(call gb_Executable_add_defs,idlc,\ + -DSYSTEM_UCPP_IS_GCC \ +)) +endif + +endif + +$(eval $(call gb_Executable_add_exception_objects,idlc,\ + idlc/source/idlcmain \ + idlc/source/idlc \ + idlc/source/idlccompile \ + idlc/source/idlcproduce \ + idlc/source/errorhandler \ + idlc/source/options \ + idlc/source/fehelper \ + idlc/source/astdeclaration \ + idlc/source/astscope \ + idlc/source/aststack \ + idlc/source/astdump \ + idlc/source/astinterface \ + idlc/source/aststruct \ + idlc/source/aststructinstance \ + idlc/source/astoperation \ + idlc/source/astconstant \ + idlc/source/astenum \ + idlc/source/astexpression \ + idlc/source/astservice \ +)) + +# Without this, e.g. 'make clean; make CustomTarget_idlc/parser_test' may fail on Windows localized +# to something other than listed in Impl_getTextEncodingData, because osl_getThreadTextEncoding() +# returns Windows ACP, calling FullTextEncodingData ctor which loads the not-yet-built library +$(call gb_Executable_add_runtime_dependencies,idlc, \ + $(call gb_CondLibSalTextenc,$(call gb_Library_get_target,sal_textenc)) \ +) + +# vim:set noet sw=4 ts=4: diff --git a/idlc/Makefile b/idlc/Makefile new file mode 100644 index 000000000..0997e6284 --- /dev/null +++ b/idlc/Makefile @@ -0,0 +1,14 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +module_directory:=$(dir $(realpath $(firstword $(MAKEFILE_LIST)))) + +include $(module_directory)/../solenv/gbuild/partial_build.mk + +# vim: set noet sw=4 ts=4: diff --git a/idlc/Module_idlc.mk b/idlc/Module_idlc.mk new file mode 100644 index 000000000..a20d105cd --- /dev/null +++ b/idlc/Module_idlc.mk @@ -0,0 +1,25 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_Module_Module,idlc)) + +# if not cross-compiling or we need this for ODK +ifneq (,$(if $(CROSS_COMPILING),,T)$(filter ODK,$(BUILD_TYPE))) + +$(eval $(call gb_Module_add_targets,idlc,\ + Executable_idlc \ +)) + +$(eval $(call gb_Module_add_check_targets,idlc,\ + CustomTarget_parser_test \ +)) + +endif + +# vim:set noet sw=4 ts=4: diff --git a/idlc/README.md b/idlc/README.md new file mode 100644 index 000000000..621a767b3 --- /dev/null +++ b/idlc/README.md @@ -0,0 +1,7 @@ +# UNO IDL Compiler (idlc) + +Contains the UNO IDL compiler: `idlc`, depends on preprocessor: `ucpp` + +This compiler generates binary RDB fragments that can be assembled +into a RDB (UNO type library) with the `regmerge` tool, as is done +primarily in the `offapi` and `udkapi` directories. diff --git a/idlc/inc/astattribute.hxx b/idlc/inc/astattribute.hxx new file mode 100644 index 000000000..b9a799f92 --- /dev/null +++ b/idlc/inc/astattribute.hxx @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX +#define INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +#include <registry/types.hxx> +#include <rtl/ustring.hxx> + +namespace typereg { class Writer; } + +class AstAttribute final : public AstDeclaration, public AstScope { +public: + AstAttribute( + sal_uInt32 flags, AstType const * type, OString const & name, + AstScope * scope): + AstDeclaration(NT_attribute, name, scope), + AstScope(NT_attribute), m_flags(flags), m_pType(type) + {} + + AstAttribute(NodeType nodeType, sal_uInt32 flags, AstType const * pType, const OString& name, AstScope* pScope) + : AstDeclaration(nodeType, name, pScope), AstScope(nodeType) + , m_flags(flags) + , m_pType(pType) + {} + + void setExceptions( + OUString const * getDoc, DeclList const * getExc, + OUString const * setDoc, DeclList const * setExc) + { + if (getDoc != nullptr) { + m_getDocumentation = *getDoc; + } + if (getExc != nullptr) { + m_getExceptions = *getExc; + } + if (setDoc != nullptr) { + m_setDocumentation = *setDoc; + } + if (setExc != nullptr) { + m_setExceptions = *setExc; + } + } + + DeclList::size_type getGetExceptionCount() const + { return m_getExceptions.size(); } + + DeclList::size_type getSetExceptionCount() const + { return m_setExceptions.size(); } + + bool isReadonly() const + { return ((m_flags & AF_READONLY) == AF_READONLY); } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } + bool isBound() const + { return ((m_flags & AF_BOUND) == AF_BOUND); } + bool isMayBeVoid() const + { return ((m_flags & AF_MAYBEVOID) == AF_MAYBEVOID); } + bool isConstrained() const + { return ((m_flags & AF_CONSTRAINED) == AF_CONSTRAINED); } + bool isTransient() const + { return ((m_flags & AF_TRANSIENT) == AF_TRANSIENT); } + bool isMayBeAmbiguous() const + { return ((m_flags & AF_MAYBEAMBIGUOUS) == AF_MAYBEAMBIGUOUS); } + bool isMayBeDefault() const + { return ((m_flags & AF_MAYBEDEFAULT) == AF_MAYBEDEFAULT); } + bool isRemoveable() const + { return ((m_flags & AF_REMOVABLE) == AF_REMOVABLE); } + + void dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, sal_uInt16 * methodIndex) const; + +private: + void dumpExceptions( + typereg::Writer & writer, OUString const & documentation, + DeclList const & exceptions, RTMethodMode flags, + sal_uInt16 * methodIndex) const; + + const sal_uInt32 m_flags; + AstType const * m_pType; + OUString m_getDocumentation; + DeclList m_getExceptions; + OUString m_setDocumentation; + DeclList m_setExceptions; +}; + +#endif // INCLUDED_IDLC_INC_ASTATTRIBUTE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astbasetype.hxx b/idlc/inc/astbasetype.hxx new file mode 100644 index 000000000..0b488c800 --- /dev/null +++ b/idlc/inc/astbasetype.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include "asttype.hxx" +#include "astexpression.hxx" + + +class AstBaseType final : public AstType +{ +public: + AstBaseType(const ExprType type, const OString& name, AstScope* pScope) + : AstType(NT_predefined, name, pScope) + , m_exprType(type) + {} + + virtual bool isUnsigned() const override { + switch (m_exprType) { + case ET_ushort: + case ET_ulong: + case ET_uhyper: + return true; + default: + return false; + } + } + + ExprType getExprType() const + { return m_exprType; } +private: + const ExprType m_exprType; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astconstant.hxx b/idlc/inc/astconstant.hxx new file mode 100644 index 000000000..fb8b417f4 --- /dev/null +++ b/idlc/inc/astconstant.hxx @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTCONSTANT_HXX +#define INCLUDED_IDLC_INC_ASTCONSTANT_HXX + +#include "astdeclaration.hxx" +#include "astexpression.hxx" + +namespace typereg { class Writer; } + +class AstConstant final : public AstDeclaration +{ +public: + AstConstant(const ExprType type, const NodeType nodeType, + AstExpression* pExpr, const OString& name, AstScope* pScope); + AstConstant(const ExprType type, AstExpression* pExpr, + const OString& name, AstScope* pScope); + virtual ~AstConstant() override; + + AstExpression* getConstValue() + { return m_pConstValue; } + ExprType getConstValueType() const + { return m_constValueType; } + + bool dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, bool published); +private: + AstExpression* m_pConstValue; + const ExprType m_constValueType; +}; + +#endif // INCLUDED_IDLC_INC_ASTCONSTANT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astconstants.hxx b/idlc/inc/astconstants.hxx new file mode 100644 index 000000000..6add23a45 --- /dev/null +++ b/idlc/inc/astconstants.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTCONSTANTS_HXX +#define INCLUDED_IDLC_INC_ASTCONSTANTS_HXX + +#include "astmodule.hxx" + +class AstConstants final : public AstModule +{ +public: + AstConstants(const OString& name, AstScope* pScope) + : AstModule(NT_constants, name, pScope) + { + } +}; + +#endif // INCLUDED_IDLC_INC_ASTCONSTANTS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astdeclaration.hxx b/idlc/inc/astdeclaration.hxx new file mode 100644 index 000000000..0707dbc57 --- /dev/null +++ b/idlc/inc/astdeclaration.hxx @@ -0,0 +1,136 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTDECLARATION_HXX +#define INCLUDED_IDLC_INC_ASTDECLARATION_HXX + +#include "idlc.hxx" +#include <registry/registry.hxx> + +class AstScope; + +// Enum defining the different kinds of Ast nodes +enum NodeType +{ + NT_service, // Denotes a service + NT_interface_member, // Denotes an interface which is exported from object + NT_service_member, // Denotes a service which is exported from object + NT_observes, // Denotes an observed interface + NT_needs, // Denotes a needed service + NT_module, // Denotes a module + NT_root, // Denotes the root of AST + NT_interface, // Denotes an interface + NT_constants, // Denotes a constant group + NT_const, // Denotes a constant + NT_exception, // Denotes an exception + NT_attribute, // Denotes an attribute + NT_property, // Denotes a property + NT_operation, // Denotes an operation + NT_parameter, // Denotes an op. parameter + NT_struct, // Denotes either a plain struct type, or a + // polymorphic struct type template + NT_type_parameter, // Denotes a type parameter of a polymorphic struct + // type template + NT_instantiated_struct, // Denotes an instantiated polymorphic struct type + NT_member, // Denotes a member in structure, exception + NT_enum, // Denotes an enumeration + NT_enum_val, // Denotes an enum. value + NT_sequence, // Denotes an IDL sequence + NT_typedef, // Denotes a typedef + NT_predefined, // Denotes a predefined type + NT_singleton // Denotes a singleton +}; + +class AstDeclaration +{ +public: + // Constructors + AstDeclaration(NodeType type, const OString& name, AstScope* pScope); + virtual ~AstDeclaration(); + + AstDeclaration(AstDeclaration const &) = default; + AstDeclaration(AstDeclaration &&) = default; + AstDeclaration & operator =(AstDeclaration const &) = default; + AstDeclaration & operator =(AstDeclaration &&) = default; + + // Data access + const OString& getLocalName() const + { return m_localName; } + const OString& getScopedName() const + { return m_scopedName; } + const OString& getFullName() const + { return m_fullName; } + virtual const char* getRelativName() const + { return m_fullName.getStr()+1; } + AstScope* getScope() + { return m_pScope; } + const AstScope* getScope() const + { return m_pScope; } + NodeType getNodeType() const + { return m_nodeType; } + bool isInMainfile() const + { return m_bInMainFile; } + void setInMainfile(bool bInMainfile) + { m_bInMainFile = bInMainfile; } + bool isImported() const + { return m_bImported; } + void setImported(bool bImported) + { m_bImported = bImported; } + sal_Int32 getLineNumber() const + { return m_lineNumber; } + void setLineNumber(sal_Int32 lineNumber) + { m_lineNumber = lineNumber; } + const OString& getFileName() const + { return m_fileName; } + void setFileName(const OString& rFileName) + { m_fileName = rFileName; } + const OUString& getDocumentation() const + { return m_documentation; } + void setDocumentation(const OUString& rDocumentation) + { m_documentation = rDocumentation; } + + virtual bool isType() const; + + bool hasAncestor(AstDeclaration* pDecl); + + void setPublished() { m_bPublished = true; } + bool isPublished() const { return m_bPublished; } + + virtual bool dump(RegistryKey& rKey); + + bool isPredefined() const { return m_bPredefined; } + void setPredefined(bool bPredefined); + +protected: + OString m_localName; + OString m_scopedName; // full qualified name + OString m_fullName; // full qualified name with '/' as separator + AstScope* m_pScope; + NodeType m_nodeType; + bool m_bImported; // imported ? + bool m_bInMainFile; // defined in main file + bool m_bPublished; + bool m_bPredefined; + sal_Int32 m_lineNumber; // line number defined in + OString m_fileName; // fileName defined in + OUString m_documentation; // fileName defined in +}; + +#endif // INCLUDED_IDLC_INC_ASTDECLARATION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astenum.hxx b/idlc/inc/astenum.hxx new file mode 100644 index 000000000..dc89d430a --- /dev/null +++ b/idlc/inc/astenum.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTENUM_HXX +#define INCLUDED_IDLC_INC_ASTENUM_HXX + +#include "asttype.hxx" +#include "astscope.hxx" +#include "astconstant.hxx" + +class AstEnum final : public AstType, public AstScope +{ +public: + AstEnum(const OString& name, AstScope* pScope); + + virtual ~AstEnum() override; + + sal_Int32 getEnumValueCount() { return m_enumValueCount++; } + + AstConstant* checkValue(AstExpression* pExpr); + + virtual bool dump(RegistryKey& rKey) override; + +private: + sal_Int32 m_enumValueCount; +}; + +#endif // INCLUDED_IDLC_INC_ASTENUM_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astexception.hxx b/idlc/inc/astexception.hxx new file mode 100644 index 000000000..6c2d549bc --- /dev/null +++ b/idlc/inc/astexception.hxx @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTEXCEPTION_HXX +#define INCLUDED_IDLC_INC_ASTEXCEPTION_HXX + +#include "aststruct.hxx" + +class AstException final : public AstStruct +{ +public: + AstException(const OString& name, AstException const* pBaseType, AstScope* pScope) + : AstStruct(NT_exception, name, pBaseType, pScope) + { + } +}; + +#endif // INCLUDED_IDLC_INC_ASTEXCEPTION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astexpression.hxx b/idlc/inc/astexpression.hxx new file mode 100644 index 000000000..05d20baa5 --- /dev/null +++ b/idlc/inc/astexpression.hxx @@ -0,0 +1,139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTEXPRESSION_HXX +#define INCLUDED_IDLC_INC_ASTEXPRESSION_HXX + +#include <sal/config.h> + +#include <memory> + +#include "idlc.hxx" +#include <optional> + +// Enum to define all the different operators to combine expressions +enum class ExprComb +{ + Add, // '+' + Minus, // '-' + Mul, // '*' + Div, // '/' + Mod, // '%' + Or, // '|' + Xor, // '^' + And, // '&' + Left, // '<<' + Right, // '>>' + UPlus, // unary '+' + UMinus, // unary '-' + NONE, // No operator (missing) + Symbol // a symbol (function or constant name) +}; + +// Enum to define expression type +enum ExprType +{ + ET_short, // Expression value is short + ET_ushort, // Expression value is unsigned short + ET_long, // Expression value is long + ET_ulong, // Expression value is unsigned long + ET_hyper, // Expression value is hyper (64 bit) + ET_uhyper, // Expression value is unsigned hyper + ET_float, // Expression value is 32-bit float + ET_double, // Expression value is 64-bit float + ET_char, // Expression value is char + ET_byte, // Expression value is byte + ET_boolean, // Expression value is boolean + ET_string, // Expression value is char * + ET_any, // Expression value is any of above + ET_void, // Expression value is void (absent) + ET_type, // Expression value is type + ET_none // Expression value is missing +}; + +// Structure to describe value of constant expression and its type +struct AstExprValue +{ + union + { + sal_uInt8 byval; // Contains byte expression value + sal_Int16 sval; // Contains short expression value + sal_uInt16 usval; // Contains unsigned short expr value + sal_Int32 lval; // Contains long expression value + sal_uInt32 ulval; // Contains unsigned long expr value + sal_Int64 hval; // Contains hyper expression value + sal_uInt64 uhval; // Contains unsigned hyper expr value + bool bval; // Contains boolean expression value + float fval; // Contains 32-bit float expr value + double dval; // Contains 64-bit float expr value + } u; + ExprType et; +}; + +const char* exprTypeToString(ExprType t); + +class AstExpression final +{ +public: + // Constructor(s) + AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2); + + AstExpression(sal_Int32 l); + AstExpression(sal_Int32 l, ExprType et); + AstExpression(sal_Int64 h); + AstExpression(sal_uInt64 uh); + AstExpression(double d); + AstExpression(OString* scopedName); + + ~AstExpression(); + + // Data Accessors + AstExprValue* getExprValue() + { return m_exprValue.get(); } + + // Evaluation and value coercion + bool coerce(ExprType type); + + // Evaluate then store value inside this AstExpression + void evaluate(); + + // Compare LONG AstExpression values + bool compareLong(AstExpression *pExpr); + + OString toString(); +private: + // Evaluate different sets of operators + std::unique_ptr<AstExprValue> eval_bin_op(); + std::unique_ptr<AstExprValue> eval_bit_op(); + std::unique_ptr<AstExprValue> eval_un_op(); + std::unique_ptr<AstExprValue> eval_symbol(); + + ExprComb m_combOperator; + std::unique_ptr<AstExpression> + m_subExpr1; + std::unique_ptr<AstExpression> + m_subExpr2; + std::unique_ptr<AstExprValue> + m_exprValue; + std::optional<OString> + m_xSymbolicName; +}; + +#endif // INCLUDED_IDLC_INC_ASTEXPRESSION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astinterface.hxx b/idlc/inc/astinterface.hxx new file mode 100644 index 000000000..03c5f22f5 --- /dev/null +++ b/idlc/inc/astinterface.hxx @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTINTERFACE_HXX +#define INCLUDED_IDLC_INC_ASTINTERFACE_HXX + +#include "asttype.hxx" +#include "astscope.hxx" +#include "inheritedinterface.hxx" + +#include <map> +#include <vector> + +class AstInterface : public AstType + , public AstScope +{ +public: + typedef std::vector< InheritedInterface > InheritedInterfaces; + + struct DoubleMemberDeclaration { + AstDeclaration const * first; + AstDeclaration const * second; + }; + + typedef std::vector< DoubleMemberDeclaration > DoubleMemberDeclarations; + + struct DoubleDeclarations { + std::vector< AstInterface const * > interfaces; + DoubleMemberDeclarations members; + }; + + AstInterface( + const OString& name, AstInterface const * pInherits, + AstScope* pScope); + virtual ~AstInterface() override; + + AstInterface(AstInterface const &) = default; + AstInterface(AstInterface &&) = default; + AstInterface & operator =(AstInterface const &) = default; + AstInterface & operator =(AstInterface &&) = default; + + InheritedInterfaces const & getAllInheritedInterfaces() const + { return m_inheritedInterfaces; } + + bool hasMandatoryInheritedInterfaces() const + { return m_mandatoryInterfaces > 0; } + + void setDefined() { m_bIsDefined = true; } + bool isDefined() const + { return m_bIsDefined; } + + bool usesSingleInheritance() const { return m_bSingleInheritance; } + + DoubleDeclarations checkInheritedInterfaceClashes( + AstInterface const * ifc, bool optional) const; + + void addInheritedInterface( + AstType const * ifc, bool optional, + OUString const & documentation); + + DoubleMemberDeclarations checkMemberClashes( + AstDeclaration const * member) const; + + void addMember(AstDeclaration /*TODO: const*/ * member); + + void forwardDefined(AstInterface const & def); + + virtual bool dump(RegistryKey& rKey) override; + +private: + enum InterfaceKind { + INTERFACE_INDIRECT_OPTIONAL, INTERFACE_DIRECT_OPTIONAL, + INTERFACE_INDIRECT_MANDATORY, INTERFACE_DIRECT_MANDATORY }; + + struct VisibleMember { + explicit VisibleMember(AstDeclaration const * theMandatory = nullptr): + mandatory(theMandatory) {} + + typedef std::map< OString, AstDeclaration const * > Optionals; + + AstDeclaration const * mandatory; + Optionals optionals; + }; + + typedef std::map< OString, InterfaceKind > VisibleInterfaces; + typedef std::map< OString, VisibleMember > VisibleMembers; + + void checkInheritedInterfaceClashes( + DoubleDeclarations & doubleDeclarations, + std::set< OString > & seenInterfaces, AstInterface const * ifc, + bool direct, bool optional, bool mainOptional) const; + + void checkMemberClashes( + DoubleMemberDeclarations & doubleMembers, AstDeclaration const * member, + bool checkOptional) const; + + void addVisibleInterface( + AstInterface const * ifc, bool direct, bool optional); + + void addOptionalVisibleMembers(AstInterface const * ifc); + + bool increment(sal_uInt16 * counter, char const * sort) const; + + InheritedInterfaces m_inheritedInterfaces; + InheritedInterfaces::size_type m_mandatoryInterfaces; + bool m_bIsDefined; + bool m_bSingleInheritance; + VisibleInterfaces m_visibleInterfaces; + VisibleMembers m_visibleMembers; +}; + +#endif // INCLUDED_IDLC_INC_ASTINTERFACE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astinterfacemember.hxx b/idlc/inc/astinterfacemember.hxx new file mode 100644 index 000000000..0e290e187 --- /dev/null +++ b/idlc/inc/astinterfacemember.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX + +#include "astinterface.hxx" + +class AstInterfaceMember final : public AstDeclaration +{ +public: + AstInterfaceMember(const sal_uInt32 flags, AstInterface* pRealInterface, + const OString& name, AstScope* pScope) + : AstDeclaration(NT_interface_member, name, pScope) + , m_flags(flags) + , m_pRealInterface(pRealInterface) + {} + + AstInterface* getRealInterface() + { return m_pRealInterface; } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } +private: + const sal_uInt32 m_flags; + AstInterface* m_pRealInterface; +}; + +#endif // INCLUDED_IDLC_INC_ASTINTERFACEMEMBER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astmember.hxx b/idlc/inc/astmember.hxx new file mode 100644 index 000000000..43597d125 --- /dev/null +++ b/idlc/inc/astmember.hxx @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTMEMBER_HXX + +#include "astdeclaration.hxx" + +class AstScope; +class AstType; + +class AstMember: public AstDeclaration { +public: + AstMember( + AstType const * pType, OString const & name, AstScope * pScope): + AstDeclaration(NT_member, name, pScope), m_pType(pType) {} + + AstType const * getType() const { return m_pType; } + +protected: + AstMember( + NodeType type, AstType const * pType, OString const & name, + AstScope * pScope): + AstDeclaration(type, name, pScope), m_pType(pType) {} + +private: + AstType const * m_pType; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astmodule.hxx b/idlc/inc/astmodule.hxx new file mode 100644 index 000000000..6178cfbb6 --- /dev/null +++ b/idlc/inc/astmodule.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTMODULE_HXX +#define INCLUDED_IDLC_INC_ASTMODULE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +class AstModule : public AstDeclaration, public AstScope +{ +public: + AstModule(const OString& name, AstScope* pScope) + : AstDeclaration(NT_module, name, pScope) + , AstScope(NT_module) + { + } + AstModule(NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + , AstScope(type) + { + } + + virtual bool dump(RegistryKey& rKey) override; +}; + +#endif // INCLUDED_IDLC_INC_ASTMODULE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astneeds.hxx b/idlc/inc/astneeds.hxx new file mode 100644 index 000000000..13d2dbbef --- /dev/null +++ b/idlc/inc/astneeds.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTNEEDS_HXX +#define INCLUDED_IDLC_INC_ASTNEEDS_HXX + +#include "astservice.hxx" + +class AstNeeds final : public AstDeclaration +{ +public: + AstNeeds(AstService* pRealService, const OString& name, AstScope* pScope) + : AstDeclaration(NT_needs, name, pScope) + , m_pRealService(pRealService) + { + } + + AstService* getRealService() { return m_pRealService; } + +private: + AstService* m_pRealService; +}; + +#endif // INCLUDED_IDLC_INC_ASTNEEDS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astobserves.hxx b/idlc/inc/astobserves.hxx new file mode 100644 index 000000000..11bb5a677 --- /dev/null +++ b/idlc/inc/astobserves.hxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTOBSERVES_HXX +#define INCLUDED_IDLC_INC_ASTOBSERVES_HXX + +#include "astinterface.hxx" + +class AstObserves final : public AstDeclaration +{ +public: + AstObserves(AstInterface* pRealInterface, const OString& name, AstScope* pScope) + : AstDeclaration(NT_observes, name, pScope) + , m_pRealInterface(pRealInterface) + { + } + + AstInterface* getRealInterface() { return m_pRealInterface; } + +private: + AstInterface* m_pRealInterface; +}; + +#endif // INCLUDED_IDLC_INC_ASTOBSERVES_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astoperation.hxx b/idlc/inc/astoperation.hxx new file mode 100644 index 000000000..e3e0335c9 --- /dev/null +++ b/idlc/inc/astoperation.hxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTOPERATION_HXX +#define INCLUDED_IDLC_INC_ASTOPERATION_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +namespace typereg { class Writer; } + +class AstType; + +class AstOperation final : public AstDeclaration + , public AstScope +{ +public: + AstOperation(AstType const * pReturnType, const OString& name, AstScope* pScope) + : AstDeclaration(NT_operation, name, pScope) + , AstScope(NT_operation) + , m_pReturnType(pReturnType) + {} + + bool isVariadic() const; + + bool isConstructor() const { return m_pReturnType == nullptr; } + + void setExceptions(DeclList const * pExceptions); + + void dumpBlob(typereg::Writer & rBlob, sal_uInt16 index); + +private: + AstType const * m_pReturnType; + DeclList m_exceptions; +}; + +#endif // INCLUDED_IDLC_INC_ASTOPERATION_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astparameter.hxx b/idlc/inc/astparameter.hxx new file mode 100644 index 000000000..cfee34260 --- /dev/null +++ b/idlc/inc/astparameter.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTPARAMETER_HXX +#define INCLUDED_IDLC_INC_ASTPARAMETER_HXX + +#include "astmember.hxx" + +enum Direction { DIR_IN, DIR_OUT, DIR_INOUT }; + +class AstParameter final : public AstMember { +public: + AstParameter( + Direction direction, bool rest, AstType const * type, + OString const & name, AstScope * scope): + AstMember(NT_parameter, type, name, scope), m_direction(direction), + m_rest(rest) {} + + Direction getDirection() const { return m_direction; } + + bool isRest() const { return m_rest; } + +private: + Direction m_direction; + bool m_rest; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astscope.hxx b/idlc/inc/astscope.hxx new file mode 100644 index 000000000..be7b03828 --- /dev/null +++ b/idlc/inc/astscope.hxx @@ -0,0 +1,73 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSCOPE_HXX +#define INCLUDED_IDLC_INC_ASTSCOPE_HXX + +#include <sal/config.h> + +#include <string_view> +#include "idlc.hxx" +#include "astdeclaration.hxx" +#include "astexpression.hxx" + +class AstExpression; + +class AstScope +{ +public: + AstScope(NodeType nodeType); + virtual ~AstScope(); + + AstScope(AstScope const&) = default; + AstScope(AstScope&&) = default; + AstScope& operator=(AstScope const&) = default; + AstScope& operator=(AstScope&&) = default; + + NodeType getScopeNodeType() const { return m_nodeType; } + + AstDeclaration* addDeclaration(AstDeclaration* pDecl); + + sal_uInt32 nMembers() const { return static_cast<sal_uInt32>(m_declarations.size()); } + DeclList::const_iterator getIteratorBegin() const { return m_declarations.begin(); } + DeclList::const_iterator getIteratorEnd() const { return m_declarations.end(); } + sal_uInt16 getNodeCount(NodeType nType) const; + + // Name look up mechanism + AstDeclaration* lookupByName(const OString& scopedName); + // Look up the identifier 'name' specified only in the local scope + AstDeclaration* lookupByNameLocal(std::string_view name) const; + + AstDeclaration* lookupInInherited(const OString& scopedName) const; + + // Look up a predefined type by its ExprType + AstDeclaration* lookupPrimitiveType(ExprType type); + + AstDeclaration* lookupForAdd(AstDeclaration const* pDecl) const; + +protected: + AstDeclaration const* getLast() const { return m_declarations.back(); } + +private: + DeclList m_declarations; + NodeType m_nodeType; +}; + +#endif // INCLUDED_IDLC_INC_ASTSCOPE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astsequence.hxx b/idlc/inc/astsequence.hxx new file mode 100644 index 000000000..e8a2850e2 --- /dev/null +++ b/idlc/inc/astsequence.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSEQUENCE_HXX +#define INCLUDED_IDLC_INC_ASTSEQUENCE_HXX + +#include "asttype.hxx" + +class AstSequence final : public AstType +{ +public: + AstSequence(AstType const* pMemberType, AstScope* pScope) + : AstType(NT_sequence, OString::Concat("[]") + pMemberType->getScopedName(), pScope) + , m_pMemberType(pMemberType) + { + } + + AstType const* getMemberType() const { return m_pMemberType; } + + virtual bool isUnsigned() const override + { + return m_pMemberType != nullptr && m_pMemberType->isUnsigned(); + } + + virtual const char* getRelativName() const override; + +private: + AstType const* m_pMemberType; + mutable std::optional<OString> m_xRelativName; +}; + +#endif // INCLUDED_IDLC_INC_ASTSEQUENCE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astservice.hxx b/idlc/inc/astservice.hxx new file mode 100644 index 000000000..4ad769cd5 --- /dev/null +++ b/idlc/inc/astservice.hxx @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSERVICE_HXX +#define INCLUDED_IDLC_INC_ASTSERVICE_HXX + +#include "astdeclaration.hxx" +#include "astscope.hxx" + +class AstService final : public AstDeclaration + , public AstScope +{ +public: + AstService(const OString& name, AstScope* pScope) + : AstDeclaration(NT_service, name, pScope) + , AstScope(NT_service) + , m_singleInterfaceBasedService(false) + , m_defaultConstructor(false) + {} + AstService(const NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + , AstScope(type) + , m_singleInterfaceBasedService(false) + , m_defaultConstructor(false) + {} + + virtual bool dump(RegistryKey& rKey) override; + + void setSingleInterfaceBasedService() + { m_singleInterfaceBasedService = true; } + + void setDefaultConstructor(bool b) { m_defaultConstructor = b; } + + bool isSingleInterfaceBasedService() const + { return m_singleInterfaceBasedService; } + + bool checkLastConstructor() const; + +private: + bool m_singleInterfaceBasedService; + bool m_defaultConstructor; +}; + +#endif // INCLUDED_IDLC_INC_ASTSERVICE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/astservicemember.hxx b/idlc/inc/astservicemember.hxx new file mode 100644 index 000000000..380449b25 --- /dev/null +++ b/idlc/inc/astservicemember.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX +#define INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX + +#include "astservice.hxx" + +class AstServiceMember final : public AstDeclaration +{ +public: + AstServiceMember(const sal_uInt32 flags, AstService* pRealService, + const OString& name, AstScope* pScope) + : AstDeclaration(NT_service_member, name, pScope) + , m_flags(flags) + , m_pRealService(pRealService) + {} + + AstService* getRealService() + { return m_pRealService; } + bool isOptional() const + { return ((m_flags & AF_OPTIONAL) == AF_OPTIONAL); } +private: + const sal_uInt32 m_flags; + AstService* m_pRealService; +}; + +#endif // INCLUDED_IDLC_INC_ASTSERVICEMEMBER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststack.hxx b/idlc/inc/aststack.hxx new file mode 100644 index 000000000..d36bd4e48 --- /dev/null +++ b/idlc/inc/aststack.hxx @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#pragma once + +#include <sal/types.h> +#include <vector> + +class AstScope; + +class AstStack final +{ +public: + AstStack(); + ~AstStack(); + + sal_uInt32 depth() const { return m_stack.size(); } + AstScope* top(); + AstScope* bottom(); + AstScope* nextToTop(); + AstScope* topNonNull(); + AstStack* push(AstScope* pScope); + void pop(); + void clear(); + +private: + std::vector<AstScope*> m_stack; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststruct.hxx b/idlc/inc/aststruct.hxx new file mode 100644 index 000000000..5e037d1b5 --- /dev/null +++ b/idlc/inc/aststruct.hxx @@ -0,0 +1,62 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTSTRUCT_HXX +#define INCLUDED_IDLC_INC_ASTSTRUCT_HXX + +#include <sal/config.h> + +#include <string_view> + +#include "asttype.hxx" +#include "astscope.hxx" +#include "idlctypes.hxx" + +class AstStruct; + +class AstStruct : public AstType + , public AstScope +{ +public: + AstStruct( + const OString& name, + std::vector< OString > const & typeParameters, + AstStruct const* pBaseType, AstScope* pScope); + + AstStruct(const NodeType type, + const OString& name, + AstStruct const* pBaseType, + AstScope* pScope); + virtual ~AstStruct() override; + + std::size_t getTypeParameterCount() const + { return m_typeParameters.size(); } + + AstDeclaration const * findTypeParameter(std::string_view name) const; + + virtual bool isType() const override; + + virtual bool dump(RegistryKey& rKey) override; +private: + AstStruct const* m_pBaseType; + std::vector<std::unique_ptr<AstDeclaration>> m_typeParameters; +}; + +#endif // INCLUDED_IDLC_INC_ASTSTRUCT_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/aststructinstance.hxx b/idlc/inc/aststructinstance.hxx new file mode 100644 index 000000000..1357aa351 --- /dev/null +++ b/idlc/inc/aststructinstance.hxx @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_INC_ASTSTRUCTINSTANCE_HXX +#define INCLUDED_IDLC_INC_ASTSTRUCTINSTANCE_HXX + +#include "asttype.hxx" +#include "idlctypes.hxx" + +class AstScope; + +class AstStructInstance final : public AstType { +public: + AstStructInstance( + AstType const * typeTemplate, DeclList const * typeArguments, + AstScope * scope); + + AstType const * getTypeTemplate() const { return m_typeTemplate; } + + DeclList::const_iterator getTypeArgumentsBegin() const + { return m_typeArguments.begin(); } + + DeclList::const_iterator getTypeArgumentsEnd() const + { return m_typeArguments.end(); } + +private: + AstType const * m_typeTemplate; + DeclList m_typeArguments; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/asttype.hxx b/idlc/inc/asttype.hxx new file mode 100644 index 000000000..8627429cd --- /dev/null +++ b/idlc/inc/asttype.hxx @@ -0,0 +1,37 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTTYPE_HXX +#define INCLUDED_IDLC_INC_ASTTYPE_HXX + +#include "astdeclaration.hxx" + +class AstType : public AstDeclaration +{ +public: + AstType(const NodeType type, const OString& name, AstScope* pScope) + : AstDeclaration(type, name, pScope) + { + } + + virtual bool isUnsigned() const { return false; } +}; + +#endif // INCLUDED_IDLC_INC_ASTTYPE_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/asttypedef.hxx b/idlc/inc/asttypedef.hxx new file mode 100644 index 000000000..427d63307 --- /dev/null +++ b/idlc/inc/asttypedef.hxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ASTTYPEDEF_HXX +#define INCLUDED_IDLC_INC_ASTTYPEDEF_HXX + +#include "asttype.hxx" + +class AstTypeDef final : public AstType +{ +public: + AstTypeDef( + AstType const * baseType, OString const & name, AstScope * scope): + AstType(NT_typedef, name, scope), m_pBaseType(baseType) {} + + AstType const * getBaseType() const + { return m_pBaseType; } + + virtual bool isUnsigned() const override + { return m_pBaseType != nullptr && m_pBaseType->isUnsigned(); } + + virtual bool dump(RegistryKey& rKey) override; +private: + AstType const * m_pBaseType; +}; + +#endif // INCLUDED_IDLC_INC_ASTTYPEDEF_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/errorhandler.hxx b/idlc/inc/errorhandler.hxx new file mode 100644 index 000000000..9b49f5df4 --- /dev/null +++ b/idlc/inc/errorhandler.hxx @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_ERRORHANDLER_HXX +#define INCLUDED_IDLC_INC_ERRORHANDLER_HXX + +#include "astdeclaration.hxx" +#include "astexpression.hxx" +#include "astenum.hxx" + +enum class ErrorCode +{ + SyntaxError, // Syntax error in IDL input + // More details will be gleaned from examining + // the parse state + RedefScope, // Redefinition inside defining scope + CoercionFailure, // Coercion failure + ScopeConflict, // Between fwd declare and full declare + IllegalAdd, // Illegal add action + IllegalRaises, // Error in "raises" clause + CantInherit, // Cannot inherit from non-interface + IdentNotFound, // Identifier not found + CannotInheritFromForward, // Cannot inherit from fwd decl interface + ExpectedConstant, // We got something else... + Eval, // Error in evaluating expression + ForwardDeclLookup, // Tried to lookup in fwd declared intf + RecursiveType, // Illegal recursive use of type + NotAType, // Not a type + InterfaceMemberLookup, // interface is not defined or a fwd declaration not exists + ServiceMemberLookup, + DefinedAttributeFlag, + WrongAttributeKeyword, + MissingAttributeKeyword, + BadAttributeFlags, + ExpectedOptional, + MixedInheritance, + DoubleInheritance, + DoubleMember, + ConstructorParameterNotIn, + ConstructorRestParameterNotFirst, + RestParameterNotLast, + RestParameterNotAny, + MethodHasRestParameter, + ReadOnlyAttributeSetExceptions, + UnsignedTypeArgument, + WrongNumberOfTypeArguments, + InstantiatedStructTypeTypedef, + IdenticalTypeParameters, + StructTypeTemplateWithBase, + PublishedForward, + PublishedusesUnpublished, + SimilarConstructors +}; + +enum class WarningCode +{ + WrongNamingConvention // type or identifier doesn't fulfill the UNO naming convention +}; + +class ErrorHandler +{ +public: + // Report errors with varying numbers of arguments + static void error0(ErrorCode e); + static void error1(ErrorCode e, AstDeclaration const * d); + static void error2( + ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2); + static void error3(ErrorCode e, AstDeclaration const * d1, AstDeclaration const * d2, AstDeclaration const * d3); + + // Warning + static void warning0(WarningCode e, const char* warningmsg); + + // Report a syntax error in IDL input + static void syntaxError(ParseState state, sal_Int32 lineNumber, const char* errmsg); + + // Report an unsuccessful coercion attempt + static void coercionError(AstExpression *pExpr, ExprType et); + + // Report a failed name lookup attempt + static void lookupError(const OString& n); + // Report a failed name lookup attempt + static void lookupError(ErrorCode e, const OString& n, AstDeclaration const * pScope); + + + // Report a type error + static void noTypeError(AstDeclaration const * pDecl); + + static void inheritanceError(NodeType nodeType, const OString* name, AstDeclaration const * pDecl); + + static void flagError(ErrorCode e, sal_uInt32 flag); + + static void forwardLookupError(const AstDeclaration* pForward, const OString& name); + + static void constantExpected(AstDeclaration const * pDecl, const OString& name); + + static void evalError(AstExpression* pExpr); + + static bool checkPublished(AstDeclaration const * decl, bool bOptional=false); +}; + +#endif // INCLUDED_IDLC_INC_ERRORHANDLER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/fehelper.hxx b/idlc/inc/fehelper.hxx new file mode 100644 index 000000000..be401defc --- /dev/null +++ b/idlc/inc/fehelper.hxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_IDLC_INC_FEHELPER_HXX +#define INCLUDED_IDLC_INC_FEHELPER_HXX + +#include "asttype.hxx" +#include "astinterface.hxx" + +#include <vector> + +class FeDeclarator final +{ +public: + FeDeclarator(const OString& name); + ~FeDeclarator(); + const OString& getName() const + { return m_name; } + bool checkType(AstDeclaration const * pType) const; + static AstType const * compose(AstDeclaration const * pDecl); +private: + OString m_name; +}; + +typedef ::std::list< FeDeclarator* > FeDeclList; + +class FeInheritanceHeader final +{ +public: + FeInheritanceHeader( + NodeType nodeType, OString* pName, OString const * pInherits, + std::vector< OString > const * typeParameters); + + NodeType getNodeType() const + { return m_nodeType; } + OString* getName() + { return m_pName.get(); } + AstDeclaration* getInherits() + { return m_pInherits; } + + std::vector< OString > const & getTypeParameters() const + { return m_typeParameters; } + +private: + void initializeInherits(OString const * pinherits); + + NodeType m_nodeType; + std::unique_ptr<OString> m_pName; + AstDeclaration* m_pInherits; + std::vector< OString > m_typeParameters; +}; + +#endif // INCLUDED_IDLC_INC_FEHELPER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/idlc.hxx b/idlc/inc/idlc.hxx new file mode 100644 index 000000000..1be11b145 --- /dev/null +++ b/idlc/inc/idlc.hxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include "idlctypes.hxx" +#include "aststack.hxx" +#include "options.hxx" +#include <memory> +#include <string_view> + +#ifdef SAL_UNX +#define SEPARATOR '/' +#define PATH_SEPARATOR "/" +#else +#define SEPARATOR '\\' +#define PATH_SEPARATOR "\\" +#endif + +class AstInterface; +class AstModule; +class AstType; +class Options; +class ErrorHandler; + +class Idlc final +{ +public: + Idlc(Options* pOptions); + ~Idlc(); + + void init(); + + bool dumpDeps(std::string_view rDepFile, + OString const& rTarget); + + Options* getOptions() + { return m_pOptions; } + AstStack* scopes() + { return m_pScopes.get(); } + AstModule* getRoot() + { return m_pRoot.get(); } + const OString& getFileName() const + { return m_fileName; } + void setFileName(const OString& fileName) + { m_fileName = fileName; addInclude(fileName); } + const OString& getMainFileName() const + { return m_mainFileName; } + void setMainFileName(const OString& mainFileName) + { m_mainFileName = mainFileName; } + const OString& getRealFileName() const + { return m_realFileName; } + void setRealFileName(const OString& realFileName) + { m_realFileName = realFileName; } + const OString& getDocumentation() + { + m_bIsDocValid = false; + return m_documentation; + } + void setDocumentation(const OString& documentation) + { + m_documentation = documentation; + m_bIsDocValid = true; + } + OUString processDocumentation(); + bool isInMainFile() const + { return m_bIsInMainfile; } + void setInMainfile(bool bInMainfile) + { m_bIsInMainfile = bInMainfile; } + sal_uInt32 getErrorCount() const + { return m_errorCount; } + void incErrorCount() + { m_errorCount++; } + sal_uInt32 getWarningCount() const + { return m_warningCount; } + void incWarningCount() + { m_warningCount++; } + sal_uInt32 getLineNumber() const + { return m_lineNumber; } + sal_uInt32 getOffsetStart() const + { return m_offsetStart; } + sal_uInt32 getOffsetEnd() const + { return m_offsetEnd; } + void setOffset( sal_uInt32 start, sal_uInt32 end) + { m_offsetStart = start; m_offsetEnd = end; } + void setLineNumber(sal_uInt32 lineNumber) + { m_lineNumber = lineNumber; } + void incLineNumber() + { m_lineNumber++; } + ParseState getParseState() const + { return m_parseState; } + void setParseState(ParseState parseState) + { m_parseState = parseState; } + + void addInclude(const OString& inc) + { m_includes.insert(inc); } + + void setPublished(bool published) { m_published = published; } + bool isPublished() const { return m_published; } + + void reset(); +private: + Options* m_pOptions; + std::unique_ptr<AstStack> m_pScopes; + std::unique_ptr<AstModule> m_pRoot; + OString m_fileName; + OString m_mainFileName; + OString m_realFileName; + OString m_documentation; + bool m_bIsDocValid; + bool m_bGenerateDoc; + bool m_bIsInMainfile; + bool m_published; + sal_uInt32 m_errorCount; + sal_uInt32 m_warningCount; + sal_uInt32 m_lineNumber; + sal_uInt32 m_offsetStart; + sal_uInt32 m_offsetEnd; + ParseState m_parseState; + std::set< OString > m_includes; +}; + + +typedef ::std::pair< OString, OString > sPair_t; +sal_Int32 compileFile(const OString * pathname); + // a null pathname means stdin +sal_Int32 produceFile(const OString& filenameBase, + sPair_t const*const pDepFile); + // filenameBase is filename without ".idl" +void removeIfExists(std::string_view pathname); + +bool copyFile(const OString* source, const OString& target); + // a null source means stdin + +bool isFileUrl(std::string_view fileName); +OString convertToAbsoluteSystemPath(const OString& fileName); +OString convertToFileUrl(const OString& fileName); + +Idlc* idlc(); +Idlc* setIdlc(Options* pOptions); + +AstDeclaration const * resolveTypedefs(AstDeclaration const * type); + +AstDeclaration const * deconstructAndResolveTypedefs( + AstDeclaration const * type, sal_Int32 * rank); + +AstInterface const * resolveInterfaceTypedefs(AstType const * type); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/idlctypes.hxx b/idlc/inc/idlctypes.hxx new file mode 100644 index 000000000..a2dadfee1 --- /dev/null +++ b/idlc/inc/idlctypes.hxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#pragma once + +#include <stdio.h> + +#include <list> +#include <set> +#include <string> +#include <unordered_map> +#include <vector> + +#include <sal/types.h> +#include <rtl/ustring.hxx> + + +class AstDeclaration; + +typedef std::list< AstDeclaration* > DeclList; + +class AstScope; +AstDeclaration* scopeAsDecl(AstScope* pScope); +AstScope* declAsScope(AstDeclaration* pDecl); + +// flags used for attributes, properties and services +#define AF_INVALID 0x0000 +#define AF_READONLY 0x0001 +#define AF_OPTIONAL 0x0002 +#define AF_MAYBEVOID 0x0004 +#define AF_BOUND 0x0008 +#define AF_CONSTRAINED 0x0010 +#define AF_TRANSIENT 0x0020 +#define AF_MAYBEAMBIGUOUS 0x0040 +#define AF_MAYBEDEFAULT 0x0080 +#define AF_REMOVABLE 0x0100 +#define AF_ATTRIBUTE 0x0200 +#define AF_PROPERTY 0x0400 + +enum ParseState +{ + PS_NoState, + PS_TypeDeclSeen, // Seen complete typedef declaration + PS_ConstantDeclSeen, // Seen complete const declaration + PS_ExceptionDeclSeen, // Seen complete exception declaration + PS_InterfaceDeclSeen, // Seen complete interface declaration + PS_ServiceDeclSeen, // Seen complete service declaration + PS_SingletonDeclSeen, // Seen complete singleton declaration + PS_ModuleDeclSeen, // Seen complete module declaration + PS_AttributeDeclSeen, // Seen complete attribute declaration + PS_PropertyDeclSeen, // Seen complete property declaration + PS_OperationDeclSeen, // Seen complete operation declaration + PS_InterfaceInheritanceDeclSeen, // Seen complete interface inheritance decl + PS_ConstantsDeclSeen, // Seen complete constants declaration + + PS_ServiceSeen, // Seen a SERVICE keyword + PS_ServiceIDSeen, // Seen the service ID + PS_ServiceSqSeen, // '{' seen for service + PS_ServiceQsSeen, // '}' seen for service + PS_ServiceBodySeen, // Seen complete service body + PS_ServiceMemberSeen, // Seen a service member + PS_ServiceIFHeadSeen, // Seen an interface member header + PS_ServiceSHeadSeen, // Seen a service member header + + PS_SingletonSeen, // Seen a SINGLETON keyword + PS_SingletonIDSeen, // Seen the singleton ID + PS_SingletonSqSeen, // '{' seen for singleton + PS_SingletonQsSeen, // '}' seen for singleton + PS_SingletonBodySeen, // Seen complete singleton body + + PS_ModuleSeen, // Seen a MODULE keyword + PS_ModuleIDSeen, // Seen the module ID + PS_ModuleSqSeen, // '{' seen for module + PS_ModuleQsSeen, // '}' seen for module + PS_ModuleBodySeen, // Seen complete module body + + PS_ConstantsSeen, // Seen a CONSTANTS keyword + PS_ConstantsIDSeen, // Seen the constants ID + PS_ConstantsSqSeen, // '{' seen for constants + PS_ConstantsQsSeen, // '}' seen for constants + PS_ConstantsBodySeen, // Seen complete constants body + + PS_InterfaceSeen, // Seen an INTERFACE keyword + PS_InterfaceIDSeen, // Seen the interface ID + PS_InterfaceHeadSeen, // Seen the interface head + PS_InheritSpecSeen, // Seen a complete inheritance spec + PS_ForwardDeclSeen, // Forward interface decl seen + PS_InterfaceSqSeen, // '{' seen for interface + PS_InterfaceQsSeen, // '}' seen for interface + PS_InterfaceBodySeen, // Seen an interface body + PS_InheritColonSeen, // Seen ':' in inheritance list + + PS_SNListCommaSeen, // Seen ',' in list of scoped names + PS_ScopedNameSeen, // Seen a complete scoped name + PS_SN_IDSeen, // Seen an identifier as part of a scoped name + PS_ScopeDelimSeen, // Seen a scope delim as party of a scoped name + + PS_ConstSeen, // Seen a CONST keyword + PS_ConstTypeSeen, // Parsed the type of a constant + PS_ConstIDSeen, // Seen the constant ID + PS_ConstAssignSeen, // Seen the '=' + PS_ConstExprSeen, // Seen the constant value expression + + PS_TypedefSeen, // Seen a TYPEDEF keyword + PS_TypeSpecSeen, // Seen a complete type specification + PS_DeclaratorsSeen, // Seen a complete list of declarators + + PS_StructSeen, // Seen a STRUCT keyword + PS_StructHeaderSeen, // Seen struct header + PS_StructIDSeen, // Seen the struct ID + PS_StructSqSeen, // '{' seen for struct + PS_StructQsSeen, // '}' seen for struct + PS_StructBodySeen, // Seen complete body of struct decl + + PS_MemberTypeSeen, // Seen type of struct or except member + PS_MemberDeclsSeen, // Seen decls of struct or except members + PS_MemberDeclsCompleted,// Completed one struct or except member to ';' + + PS_EnumSeen, // Seen an ENUM keyword + PS_EnumIDSeen, // Seen the enum ID + PS_EnumSqSeen, // Seen '{' for enum + PS_EnumQsSeen, // Seen '}' for enum + PS_EnumBodySeen, // Seen complete enum body + PS_EnumCommaSeen, // Seen ',' in list of enumerators + + PS_SequenceSeen, // Seen a SEQUENCE keyword + PS_SequenceSqSeen, // Seen '<' for sequence + PS_SequenceQsSeen, // Seen '>' for sequence + PS_SequenceTypeSeen, // Seen type decl for sequence + + PS_FlagHeaderSeen, // Seen the attribute|property|interface member head + PS_AttrSeen, // Seen ATTRIBUTE keyword + PS_AttrTypeSeen, // Seen type decl for attribute + PS_AttrCompleted, // Seen complete attribute declaration + PS_ReadOnlySeen, // Seen READONLY keyword + PS_OptionalSeen, // Seen OPTIONAL keyword + PS_MayBeVoidSeen, // Seen MAYBEVOID yword + PS_BoundSeen, // Seen BOUND keyword + PS_ConstrainedSeen, // Seen CONSTRAINED keyword + PS_TransientSeen, // Seen TRANSIENT keyword + PS_MayBeAmbiguousSeen, // Seen MAYBEAMBIGUOUS keyword + PS_MayBeDefaultSeen, // Seen MAYBEDEFAULT keyword + PS_RemoveableSeen, // Seen REMOVABLE keyword + + PS_PropertySeen, // Seen PROPERTY keyword + PS_PropertyTypeSeen, // Seen type decl for property + PS_PropertyCompleted, // Seen complete property declaration + + PS_ExceptSeen, // Seen EXCEPTION keyword + PS_ExceptHeaderSeen, // Seen exception header keyword + PS_ExceptIDSeen, // Seen exception identifier + PS_ExceptSqSeen, // Seen '{' for exception + PS_ExceptQsSeen, // Seen '}' for exception + PS_ExceptBodySeen, // Seen complete exception body + + PS_OpTypeSeen, // Seen operation return type + PS_OpIDSeen, // Seen operation ID + PS_OpParsCompleted, // Completed operation param list + PS_OpSqSeen, // Seen '(' for operation + PS_OpQsSeen, // Seen ')' for operation + PS_OpParCommaSeen, // Seen ',' in list of op params + PS_OpParDirSeen, // Seen parameter direction + PS_OpParTypeSeen, // Seen parameter type + PS_OpParDeclSeen, // Seen parameter declaration + + PS_RaiseSeen, // Seen RAISES keyword + PS_RaiseSqSeen, // Seen '(' for RAISES + PS_RaiseQsSeen, // Seen ')' for RAISES + + PS_DeclsCommaSeen, // Seen ',' in declarators list + PS_DeclsDeclSeen // Seen complete decl in decls list +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/inheritedinterface.hxx b/idlc/inc/inheritedinterface.hxx new file mode 100644 index 000000000..16462b4da --- /dev/null +++ b/idlc/inc/inheritedinterface.hxx @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_INC_INHERITEDINTERFACE_HXX +#define INCLUDED_IDLC_INC_INHERITEDINTERFACE_HXX + +#include "idlc.hxx" + +#include <rtl/ustring.hxx> +#include <utility> + +class AstInterface; +class AstType; + +class InheritedInterface { +public: + InheritedInterface( + AstType const * theInterface, bool theOptional, + OUString theDocumentation): + interface(theInterface), optional(theOptional), + documentation(std::move(theDocumentation)) {} + + AstType const * getInterface() const { return interface; } + + AstInterface const * getResolved() const + { return resolveInterfaceTypedefs(interface); } + + bool isOptional() const { return optional; } + + const OUString& getDocumentation() const { return documentation; } + +private: + AstType const * interface; + bool optional; + OUString documentation; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/inc/options.hxx b/idlc/inc/options.hxx new file mode 100644 index 000000000..c3a0949b3 --- /dev/null +++ b/idlc/inc/options.hxx @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_INC_OPTIONS_HXX +#define INCLUDED_IDLC_INC_OPTIONS_HXX + +#include "idlctypes.hxx" +#include <utility> + +typedef std::unordered_map< OString, OString > OptionMap; + +class IllegalArgument +{ +public: + IllegalArgument(OString msg) : m_message(std::move(msg)) {} + + OString m_message; +}; + + +class Options +{ +public: + explicit Options(char const * progname); + ~Options(); + + static bool checkArgument(std::vector< std::string > & rArgs, char const * arg, size_t len); + static bool checkCommandFile(std::vector< std::string > & rArgs, char const * filename); + + /// @throws IllegalArgument + bool initOptions(std::vector< std::string > & rArgs); + /// @throws IllegalArgument + static bool badOption(char const * reason, std::string const & rArg); + bool setOption(char const * option, std::string const & rArg); + + OString prepareHelp() const; + OString prepareVersion() const; + + const OString& getProgramName() const { return m_program;} + bool isValid(const OString& option) const; + /// @throws IllegalArgument + const OString& getOption(const OString& option); + + const std::vector< OString >& getInputFiles() const { return m_inputFiles; } + bool readStdin() const { return m_stdin; } + bool verbose() const { return m_verbose; } + bool quiet() const { return m_quiet; } + +protected: + OString m_program; + std::vector< OString > m_inputFiles; + bool m_stdin; + bool m_verbose; + bool m_quiet; + OptionMap m_options; +}; + +#endif // INCLUDED_IDLC_INC_OPTIONS_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astconstant.cxx b/idlc/source/astconstant.cxx new file mode 100644 index 000000000..54d235fa3 --- /dev/null +++ b/idlc/source/astconstant.cxx @@ -0,0 +1,123 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astconstant.hxx> +#include <astscope.hxx> + +#include <registry/writer.hxx> + +AstConstant::AstConstant(const ExprType type, + const NodeType nodeType, + AstExpression* pExpr, + const OString& name, + AstScope* pScope) + : AstDeclaration(nodeType, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::AstConstant(const ExprType type, + AstExpression* pExpr, + const OString& name, + AstScope* pScope) + : AstDeclaration(NT_const, name, pScope) + , m_pConstValue(pExpr) + , m_constValueType(type) +{ +} + +AstConstant::~AstConstant() +{ + +} + +bool AstConstant::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, bool published) +{ + RTConstValue aConst; + + 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 false; + } + } + + OString name = getLocalName(); + + OUString type; + if ( getNodeType() != NT_enum_val ) + { + type = OStringToOUString(exprTypeToString(getConstValueType()), RTL_TEXTENCODING_UTF8); + } + + rBlob.setFieldData( + index, getDocumentation(), OUString(), + RTFieldAccess::CONST | (published ? RTFieldAccess::PUBLISHED : RTFieldAccess::NONE), + OStringToOUString(name, RTL_TEXTENCODING_UTF8), type, aConst); + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astdeclaration.cxx b/idlc/source/astdeclaration.cxx new file mode 100644 index 000000000..980e7dd2b --- /dev/null +++ b/idlc/source/astdeclaration.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astdeclaration.hxx> +#include <astscope.hxx> +#include <rtl/strbuf.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + +constexpr OStringLiteral sGlobal("::"); + +static OString convertName(std::string_view name) +{ + OStringBuffer nameBuffer(name.size()+1); + sal_Int32 nIndex = 0; + do + { + std::string_view token( o3tl::getToken(name, 0, ':', nIndex ) ); + if( !token.empty() ) + { + 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(false) + , m_bInMainFile(false) + , m_bPredefined(false) + , m_lineNumber(0) +{ + if ( m_pScope ) + { + AstDeclaration* pDecl = scopeAsDecl(m_pScope); + if (pDecl) + { + m_scopedName = pDecl->getScopedName(); + if (!m_scopedName.isEmpty()) + 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 = true; + } else + { + m_fileName = idlc()->getFileName(); + m_bImported = true; + } + + m_documentation = idlc()->processDocumentation(); + + m_bPublished = idlc()->isPublished(); +} + + +AstDeclaration::~AstDeclaration() +{ + +} + +void AstDeclaration::setPredefined(bool bPredefined) +{ + m_bPredefined = bPredefined; + if ( m_bPredefined ) + { + m_fileName.clear(); + m_bInMainFile = false; + } +} + +bool AstDeclaration::isType() const { + switch (m_nodeType) { + case NT_interface: + case NT_instantiated_struct: + case NT_enum: + case NT_sequence: + case NT_typedef: + case NT_predefined: + case NT_type_parameter: + return true; + + default: + OSL_ASSERT(m_nodeType != NT_struct); // see AstStruct::isType + return false; + } +} + +bool AstDeclaration::hasAncestor(AstDeclaration* pDecl) +{ + if (this == pDecl) + return true; + if ( !m_pScope ) + return false; + return scopeAsDecl(m_pScope)->hasAncestor(pDecl); +} + +bool AstDeclaration::dump(RegistryKey& rKey) +{ + AstScope* pScope = declAsScope(this); + if ( !pScope ) + return true; + + bool bRet = true; + DeclList::const_iterator iter = pScope->getIteratorBegin(); + DeclList::const_iterator end = pScope->getIteratorEnd(); + AstDeclaration* pDecl = nullptr; + 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_typedef: + case NT_service: + case NT_singleton: + bRet = pDecl->dump(rKey); + break; + default: + break; + } + } + + ++iter; + } + return bRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astdump.cxx b/idlc/source/astdump.cxx new file mode 100644 index 000000000..79613e137 --- /dev/null +++ b/idlc/source/astdump.cxx @@ -0,0 +1,420 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astmodule.hxx> +#include <asttypedef.hxx> +#include <astservice.hxx> +#include <astconstant.hxx> +#include <astattribute.hxx> +#include <astinterfacemember.hxx> +#include <astservicemember.hxx> +#include <astobserves.hxx> +#include <astneeds.hxx> +#include <astsequence.hxx> +#include <astoperation.hxx> + +#include <osl/diagnose.h> + +#include <registry/version.h> +#include <registry/writer.hxx> + +bool AstModule::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if ( getNodeType() == NT_root ) + { + localKey = rKey; + }else + { + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + 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 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(), "", typeClass, + m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_const && + pDecl->isInMainfile() ) + { + static_cast<AstConstant*>(pDecl)->dumpBlob( + aBlob, index++, + getNodeType() == NT_module && pDecl->isPublished()); + } + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 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(), "", 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("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 false; + } + } + } + if ( getNodeType() == NT_root ) + { + localKey.releaseKey(); + } + return AstDeclaration::dump(rKey); +} + +bool AstTypeDef::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + 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 false; + } + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", 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("", RegValueType::BINARY, const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 false; + } + + return true; +} + +bool AstService::dump(RegistryKey& rKey) +{ + 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.isEmpty()); + 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.isEmpty()); + superName = static_cast<AstServiceMember *>(*i)-> + getRealService()->getRelativName(); + break; + } + [[fallthrough]]; + 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( + OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8), + localKey) != RegError::NO_ERROR) { + 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 false; + } + typereg::Writer writer( + version, getDocumentation(), "", + getNodeType() == NT_singleton ? RT_TYPE_SINGLETON : RT_TYPE_SERVICE, + m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + superName.isEmpty() ? 0 : 1, properties, constructors, + references); + if (!superName.isEmpty()) { + writer.setSuperTypeName( + 0, 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(writer, constructorIndex++); + break; + + case NT_property: + static_cast<AstAttribute *>(*i)->dumpBlob(writer, propertyIndex++, nullptr); + break; + + case NT_interface_member: + { + AstInterfaceMember * decl = static_cast<AstInterfaceMember *>(*i); + writer.setReferenceData( + referenceIndex++, decl->getDocumentation(), RTReferenceType::SUPPORTS, + (decl->isOptional() ? RTFieldAccess::OPTIONAL : RTFieldAccess::INVALID), + OStringToOUString( decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_service_member: + if (getNodeType() == NT_service) + { + AstServiceMember * decl = static_cast<AstServiceMember *>(*i); + writer.setReferenceData(referenceIndex++, decl->getDocumentation(), RTReferenceType::EXPORTS, + (decl->isOptional() ? RTFieldAccess::OPTIONAL : RTFieldAccess::INVALID), + OStringToOUString(decl->getRealService()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } + break; + + case NT_observes: + { + AstObserves * decl = static_cast<AstObserves *>(*i); + writer.setReferenceData(referenceIndex++, decl->getDocumentation(), RTReferenceType::OBSERVES, + RTFieldAccess::INVALID, + OStringToOUString( decl->getRealInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + break; + } + + case NT_needs: + { + AstNeeds * decl = static_cast<AstNeeds *>(*i); + writer.setReferenceData( referenceIndex++, decl->getDocumentation(), RTReferenceType::NEEDS, + RTFieldAccess::INVALID, + 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++, "", RTMethodMode::TWOWAY, + "", "void", + 0, 0); + } + sal_uInt32 size; + void const * blob = writer.getBlob(&size); + if (localKey.setValue( + "", RegValueType::BINARY, const_cast< void * >(blob), + size) != RegError::NO_ERROR) + { + 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 false; + } + return true; +} + +void AstAttribute::dumpBlob( + typereg::Writer & rBlob, sal_uInt16 index, sal_uInt16 * methodIndex) const +{ + RTFieldAccess accessMode = RTFieldAccess::INVALID; + + if (isReadonly()) + { + accessMode |= RTFieldAccess::READONLY; + } else + { + accessMode |= RTFieldAccess::READWRITE; + } + if (isOptional()) + { + accessMode |= RTFieldAccess::OPTIONAL; + } + if (isBound()) + { + accessMode |= RTFieldAccess::BOUND; + } + if (isMayBeVoid()) + { + accessMode |= RTFieldAccess::MAYBEVOID; + } + if (isConstrained()) + { + accessMode |= RTFieldAccess::CONSTRAINED; + } + if (isTransient()) + { + accessMode |= RTFieldAccess::TRANSIENT; + } + if (isMayBeAmbiguous()) + { + accessMode |= RTFieldAccess::MAYBEAMBIGUOUS; + } + if (isMayBeDefault()) + { + accessMode |= RTFieldAccess::MAYBEDEFAULT; + } + if (isRemoveable()) + { + accessMode |= RTFieldAccess::REMOVABLE; + } + + OUString name(OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8)); + rBlob.setFieldData( + index, getDocumentation(), OUString(), accessMode, name, + OStringToOUString(m_pType->getRelativName(), RTL_TEXTENCODING_UTF8), + RTConstValue()); + dumpExceptions( + rBlob, m_getDocumentation, m_getExceptions, RTMethodMode::ATTRIBUTE_GET, + methodIndex); + dumpExceptions( + rBlob, m_setDocumentation, m_setExceptions, RTMethodMode::ATTRIBUTE_SET, + methodIndex); +} + +void AstAttribute::dumpExceptions( + typereg::Writer & writer, OUString const & documentation, + DeclList const & exceptions, RTMethodMode flags, sal_uInt16 * methodIndex) const +{ + if (exceptions.empty()) + return; + + OSL_ASSERT(methodIndex != nullptr); + sal_uInt16 idx = (*methodIndex)++; + // exceptions.size() <= SAL_MAX_UINT16 already checked in + // AstInterface::dump: + writer.setMethodData( + idx, documentation, flags, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + "void", 0, + static_cast< sal_uInt16 >(exceptions.size())); + sal_uInt16 exceptionIndex = 0; + for (auto const& elem : exceptions) + { + writer.setMethodExceptionTypeName( + idx, exceptionIndex++, + OStringToOUString( + elem->getRelativName(), RTL_TEXTENCODING_UTF8)); + } +} + +const char* AstSequence::getRelativName() const +{ + if ( !m_xRelativName ) + { + m_xRelativName = OString("[]"); + AstDeclaration const * pType = resolveTypedefs( m_pMemberType ); + *m_xRelativName += pType->getRelativName(); + } + + return m_xRelativName->getStr(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astenum.cxx b/idlc/source/astenum.cxx new file mode 100644 index 000000000..7dff49d36 --- /dev/null +++ b/idlc/source/astenum.cxx @@ -0,0 +1,105 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <algorithm> + +#include <astenum.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +AstEnum::AstEnum(const 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(); + + iter = std::find_if(iter, end, [&pExpr](AstDeclaration* pDecl) { + return static_cast<AstConstant*>(pDecl)->getConstValue()->compareLong(pExpr); }); + + if (iter != end) + return static_cast<AstConstant*>(*iter); + + if ( pExpr->getExprValue()->u.lval > m_enumValueCount ) + m_enumValueCount = pExpr->getExprValue()->u.lval + 1; + + return nullptr; +} + +bool AstEnum::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + 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 false; + } + + sal_uInt16 nConst = getNodeCount(NT_enum_val); + if ( nConst <= 0 ) + return true; + + typereg::Writer aBlob( + m_bPublished ? TYPEREG_VERSION_1 : TYPEREG_VERSION_0, + getDocumentation(), "", RT_TYPE_ENUM, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), 0, + nConst, 0, 0); + + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_enum_val ) + static_cast<AstConstant*>(pDecl)->dumpBlob(aBlob, index++, false); + + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astexpression.cxx b/idlc/source/astexpression.cxx new file mode 100644 index 000000000..1afa91dbf --- /dev/null +++ b/idlc/source/astexpression.cxx @@ -0,0 +1,1327 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astexpression.hxx> +#include <astconstant.hxx> +#include <astscope.hxx> +#include <errorhandler.hxx> + +#include <o3tl/float_int_conversion.hxx> +#include <osl/diagnose.h> + +#include <limits.h> +#include <float.h> +#include <memory> + +AstExpression::AstExpression(ExprComb c, AstExpression* pExpr1, AstExpression* pExpr2) + : m_combOperator(c) + , m_subExpr1(pExpr1) + , m_subExpr2(pExpr2) +{ +} + +AstExpression::AstExpression(sal_Int32 l) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_long; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int32 l, ExprType et) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = et; + m_exprValue->u.lval = l; +} + +AstExpression::AstExpression(sal_Int64 h) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_hyper; + m_exprValue->u.hval = h; +} + +AstExpression::AstExpression(sal_uInt64 uh) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_uhyper; + m_exprValue->u.uhval = uh; +} + +AstExpression::AstExpression(double d) + : m_combOperator(ExprComb::NONE) +{ + m_exprValue.reset(new AstExprValue); + m_exprValue->et = ET_double; + m_exprValue->u.dval = d; +} + +AstExpression::AstExpression(OString* scopedName) + : m_combOperator(ExprComb::Symbol) +{ + if (scopedName) + m_xSymbolicName = *scopedName; +} + +AstExpression::~AstExpression() {} + +/* + * 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 bool coerce_value(AstExprValue* ev, ExprType t) +{ + if (ev == nullptr) + return false; + + switch (t) + { + case ET_short: + switch (ev->et) + { + case ET_short: + return true; + case ET_ushort: + { + if (ev->u.usval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.usval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_long: + { + if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.lval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.ulval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.hval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT16) + return false; + auto tmp = static_cast<sal_Int16>(ev->u.uhval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int16>(ev->u.bval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT16) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT16))) + { + return false; + } + auto tmp = static_cast<sal_Int16>(ev->u.fval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT16) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT16))) + { + return false; + } + auto tmp = static_cast<sal_Int16>(ev->u.dval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int16>(ev->u.byval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_ushort: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.sval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_ushort: + return true; + case ET_long: + { + if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.lval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.ulval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_hyper: + { + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.hval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT16) + return false; + auto tmp = static_cast<sal_uInt16>(ev->u.uhval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_uInt16>(ev->u.bval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT16)) + { + return false; + } + auto tmp = static_cast<sal_uInt16>(ev->u.fval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT16)) + { + return false; + } + auto tmp = static_cast<sal_uInt16>(ev->u.dval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt16>(ev->u.byval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_long: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<sal_Int32>(ev->u.sval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_Int32>(ev->u.usval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_long: + return true; + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.ulval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.hval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT32) + return false; + auto tmp = static_cast<sal_Int32>(ev->u.uhval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int32>(ev->u.bval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT32) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT32))) + { + return false; + } + auto tmp = static_cast<sal_Int32>(ev->u.fval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT32) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT32))) + { + return false; + } + auto tmp = static_cast<sal_Int32>(ev->u.dval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int32>(ev->u.byval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_ulong: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.sval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_uInt32>(ev->u.usval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_long: + { + if (ev->u.lval < 0) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.lval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_ulong: + return true; + case ET_hyper: + { + if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.hval); + ev->u.lval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT32) + return false; + auto tmp = static_cast<sal_uInt32>(ev->u.uhval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_uInt32>(ev->u.bval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT32)) + { + return false; + } + auto tmp = static_cast<sal_uInt32>(ev->u.fval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT32)) + { + return false; + } + auto tmp = static_cast<sal_uInt32>(ev->u.dval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt32>(ev->u.byval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_hyper: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<sal_Int64>(ev->u.sval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_Int64>(ev->u.usval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_long: + { + auto tmp = static_cast<sal_Int64>(ev->u.lval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<sal_Int64>(ev->u.ulval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_hyper: + return true; + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_INT64) + return false; + auto tmp = static_cast<sal_Int64>(ev->u.uhval); + ev->u.hval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast<sal_Int64>(ev->u.bval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT64) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT64))) + { + return false; + } + auto tmp = static_cast<sal_Int64>(ev->u.fval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT64) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT64))) + { + return false; + } + auto tmp = static_cast<sal_Int64>(ev->u.dval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_Int64>(ev->u.byval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_uhyper: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.sval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<sal_uInt64>(ev->u.usval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_long: + { + if (ev->u.lval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.lval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<sal_uInt64>(ev->u.ulval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_hyper: + { + if (ev->u.hval < 0) + return false; + auto tmp = static_cast<sal_uInt64>(ev->u.hval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_uhyper: + return true; + case ET_boolean: + { + auto tmp = static_cast<sal_uInt64>(ev->u.bval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_float: + { + if (ev->u.fval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT64)) + { + return false; + } + auto tmp = static_cast<sal_uInt64>(ev->u.fval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_double: + { + if (ev->u.dval < 0.0 + || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT64)) + { + return false; + } + auto tmp = static_cast<sal_uInt64>(ev->u.dval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast<sal_uInt64>(ev->u.byval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_boolean: + switch (ev->et) + { + case ET_short: + ev->u.bval = ev->u.sval != 0; + ev->et = ET_boolean; + return true; + case ET_ushort: + ev->u.bval = ev->u.usval != 0; + ev->et = ET_boolean; + return true; + case ET_long: + ev->u.bval = ev->u.lval != 0; + ev->et = ET_boolean; + return true; + case ET_ulong: + ev->u.bval = ev->u.ulval != 0; + ev->et = ET_boolean; + return true; + case ET_hyper: + ev->u.bval = ev->u.hval != 0; + ev->et = ET_boolean; + return true; + case ET_uhyper: + ev->u.bval = ev->u.uhval != 0; + ev->et = ET_boolean; + return true; + case ET_boolean: + return true; + case ET_float: + ev->u.bval = ev->u.fval != 0.0; + ev->et = ET_boolean; + return true; + case ET_double: + ev->u.bval = ev->u.dval != 0.0; + ev->et = ET_boolean; + return true; + case ET_byte: + ev->u.bval = ev->u.byval != 0; + ev->et = ET_boolean; + return true; + default: + OSL_ASSERT(false); + return false; + } + case ET_float: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<float>(ev->u.sval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<float>(ev->u.usval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_long: + { + auto tmp = static_cast<float>(ev->u.lval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<float>(ev->u.ulval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_hyper: + { + auto tmp = static_cast<float>(ev->u.hval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_uhyper: + { + if (static_cast<float>(ev->u.ulval) > FLT_MAX) + return false; + auto tmp = static_cast<float>(ev->u.ulval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_boolean: + ev->u.fval = ev->u.bval ? 1.0f : 0.0f; + ev->et = ET_float; + return true; + case ET_float: + return true; + case ET_double: + { + if (static_cast<float>(ev->u.dval) > FLT_MAX + || static_cast<float>(ev->u.dval) < -FLT_MAX) + return false; + auto tmp = static_cast<float>(ev->u.dval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_byte: + { + auto tmp = static_cast<float>(ev->u.byval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_double: + switch (ev->et) + { + case ET_short: + { + auto tmp = static_cast<double>(ev->u.sval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ushort: + { + auto tmp = static_cast<double>(ev->u.usval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_long: + { + auto tmp = static_cast<double>(ev->u.lval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ulong: + { + auto tmp = static_cast<double>(ev->u.ulval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_hyper: + { + auto tmp = static_cast<double>(ev->u.hval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_uhyper: + { + if (ev->u.dval > FLT_MAX || ev->u.dval < -FLT_MAX) + return false; + auto tmp = static_cast<double>(ev->u.ulval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_boolean: + ev->u.dval = ev->u.bval ? 1.0 : 0.0; + ev->et = ET_double; + return true; + case ET_float: + { + auto tmp = static_cast<double>(ev->u.fval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_double: + return true; + case ET_byte: + { + auto tmp = static_cast<double>(ev->u.byval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + default: + OSL_ASSERT(false); + return false; + } + case ET_byte: + switch (ev->et) + { + case ET_short: + { + if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.sval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_ushort: + { + if (ev->u.usval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.usval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_long: + { + if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.lval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_ulong: + { + if (ev->u.ulval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.ulval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_hyper: + { + if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.hval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_uhyper: + { + if (ev->u.uhval > SAL_MAX_UINT8) + return false; + auto tmp = static_cast<unsigned char>(ev->u.uhval); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_boolean: + ev->u.byval = ev->u.bval ? 1 : 0; + ev->et = ET_byte; + return true; + case ET_float: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT8) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT8))) + { + return false; + } + auto tmp = static_cast<unsigned char>(static_cast<sal_Int32>(ev->u.fval)); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_double: + { + if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT8) + && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT8))) + { + return false; + } + auto tmp = static_cast<unsigned char>(static_cast<sal_Int32>(ev->u.dval)); + ev->u.byval = tmp; + ev->et = ET_byte; + return true; + } + case ET_byte: + return true; + default: + OSL_ASSERT(false); + return false; + } + default: + OSL_ASSERT(false); + return false; + } +} + +bool AstExpression::coerce(ExprType t) +{ + /* + * Is it already of the right type? + */ + if (m_exprValue != nullptr && m_exprValue->et == t) + return true; + /* + * OK, must coerce + * + * First, evaluate it, then try to coerce result type + * If already evaluated, return the result + */ + evaluate(); + if (m_exprValue == nullptr) + return false; + + if (!coerce_value(m_exprValue.get(), t)) + m_exprValue.reset(); + + return m_exprValue != nullptr; +} + +bool AstExpression::compareLong(AstExpression* pExpr) +{ + bool bRet = false; + if (m_combOperator != pExpr->m_combOperator) + return bRet; + evaluate(); + pExpr->evaluate(); + if (m_exprValue == nullptr || pExpr->getExprValue() == nullptr) + return bRet; + if (m_exprValue->et != pExpr->getExprValue()->et) + return bRet; + switch (m_exprValue->et) + { + case ET_long: + bRet = m_exprValue->u.lval == pExpr->getExprValue()->u.lval; + break; + default: + OSL_ASSERT(false); + bRet = false; + break; + } + return bRet; +} + +void AstExpression::evaluate() +{ + /* + * Already evaluated? + */ + if (m_exprValue != nullptr) + return; + /* + * OK, must evaluate operator + */ + switch (m_combOperator) + { + case ExprComb::Add: + case ExprComb::Minus: + case ExprComb::Mul: + case ExprComb::Div: + case ExprComb::Mod: + m_exprValue = eval_bin_op(); + break; + case ExprComb::Or: + case ExprComb::Xor: + case ExprComb::And: + case ExprComb::Left: + case ExprComb::Right: + m_exprValue = eval_bit_op(); + break; + case ExprComb::UPlus: + case ExprComb::UMinus: + m_exprValue = eval_un_op(); + break; + case ExprComb::Symbol: + m_exprValue = eval_symbol(); + break; + case ExprComb::NONE: + break; + } +} + +std::unique_ptr<AstExprValue> AstExpression::eval_bin_op() +{ + ExprType eType = ET_double; + + if (m_combOperator == ExprComb::Mod) + eType = ET_hyper; + + if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(eType)) + return nullptr; + m_subExpr2->evaluate(); + if (m_subExpr2->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr2->coerce(eType)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = eType; + + switch (m_combOperator) + { + case ExprComb::Mod: + if (m_subExpr2->getExprValue()->u.hval == 0) + return nullptr; + retval->u.hval + = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval; + break; + case ExprComb::Add: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Minus: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Mul: + retval->u.dval + = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval; + break; + case ExprComb::Div: + if (m_subExpr2->getExprValue()->u.dval == 0.0) + return nullptr; + retval->u.dval + = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval; + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_bit_op() +{ + if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(ET_long)) + return nullptr; + m_subExpr2->evaluate(); + if (m_subExpr2->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr2->coerce(ET_long)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = ET_long; + + switch (m_combOperator) + { + case ExprComb::Or: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Xor: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::And: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Left: + retval->u.lval = m_subExpr1->getExprValue()->u.lval + << m_subExpr2->getExprValue()->u.lval; + break; + case ExprComb::Right: + retval->u.lval + = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval; + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_un_op() +{ + if (m_subExpr1 == nullptr) + return nullptr; + m_subExpr1->evaluate(); + if (m_subExpr1->getExprValue() == nullptr) + return nullptr; + if (!m_subExpr1->coerce(ET_double)) + return nullptr; + + std::unique_ptr<AstExprValue> retval(new AstExprValue); + retval->et = ET_double; + + switch (m_combOperator) + { + case ExprComb::UPlus: + retval->u.lval = m_subExpr1->getExprValue()->u.lval; + break; + case ExprComb::UMinus: + retval->u.lval = -(m_subExpr1->getExprValue()->u.lval); + break; + default: + return nullptr; + } + + return retval; +} + +std::unique_ptr<AstExprValue> AstExpression::eval_symbol() +{ + AstScope* pScope = nullptr; + AstDeclaration* pDecl; + AstConstant* pConst; + + /* + * Is there a symbol stored? + */ + if (!m_xSymbolicName) + { + ErrorHandler::evalError(this); + return nullptr; + } + /* + * Get current scope for lookup + */ + if (idlc()->scopes()->depth() > 0) + pScope = idlc()->scopes()->topNonNull(); + if (!pScope) + { + ErrorHandler::lookupError(*m_xSymbolicName); + return nullptr; + } + /* + * Do lookup + */ + pDecl = pScope->lookupByName(*m_xSymbolicName); + if (pDecl == nullptr) + { + ErrorHandler::lookupError(*m_xSymbolicName); + return nullptr; + } + /* + * Is it a constant? + */ + if (pDecl->getNodeType() != NT_const && pDecl->getNodeType() != NT_enum_val) + { + ErrorHandler::constantExpected(pDecl, *m_xSymbolicName); + return nullptr; + } + if (!ErrorHandler::checkPublished(pDecl)) + { + return nullptr; + } + /* + * OK, now evaluate the constant we just got, to produce its value + */ + pConst = static_cast<AstConstant*>(pDecl); + pConst->getConstValue()->evaluate(); + auto const val = pConst->getConstValue()->getExprValue(); + return val == nullptr ? nullptr : std::make_unique<AstExprValue>(*val); +} + +OString AstExpression::toString() +{ + OString exprStr; + if (m_combOperator == ExprComb::Symbol) + return m_xSymbolicName ? *m_xSymbolicName : OString("<Undefined Name>"); + + if (m_exprValue) + { + switch (m_exprValue->et) + { + case ET_short: + return OString::number(m_exprValue->u.sval); + case ET_ushort: + return OString::number(m_exprValue->u.usval); + case ET_long: + return OString::number(m_exprValue->u.lval); + case ET_ulong: + return OString::number(m_exprValue->u.ulval); + case ET_hyper: + return OString::number(m_exprValue->u.hval); + case ET_uhyper: + return OString::number(m_exprValue->u.uhval); + case ET_float: + return OString::number(m_exprValue->u.fval); + case ET_double: + return OString::number(m_exprValue->u.dval); + case ET_byte: + return OString::number(m_exprValue->u.byval); + case ET_boolean: + if (m_exprValue->u.lval == 0) + return "FALSE"; + else + return "TRUE"; + default: + OSL_ASSERT(false); + return OString(); + } + } + + switch (m_combOperator) + { + case ExprComb::UPlus: + exprStr += "+"; + break; + case ExprComb::UMinus: + exprStr += "-"; + break; + default: + break; + } + if (m_subExpr1) + exprStr += m_subExpr1->toString(); + switch (m_combOperator) + { + case ExprComb::Add: + exprStr += " + "; + break; + case ExprComb::Minus: + exprStr += " - "; + break; + case ExprComb::Mul: + exprStr += " * "; + break; + case ExprComb::Div: + exprStr += " / "; + break; + case ExprComb::Mod: + exprStr += " % "; + break; + case ExprComb::Or: + exprStr += " | "; + break; + case ExprComb::Xor: + exprStr += " ^ "; + break; + case ExprComb::And: + exprStr += " & "; + break; + case ExprComb::Left: + exprStr += " << "; + break; + case ExprComb::Right: + exprStr += " >> "; + break; + default: + break; + } + + if (m_subExpr2) + exprStr += m_subExpr2->toString(); + + return exprStr; +} + +// Convert the type of an AST_Expression to a char * +const char* 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 "unknown"; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astinterface.cxx b/idlc/source/astinterface.cxx new file mode 100644 index 000000000..50e24d1fd --- /dev/null +++ b/idlc/source/astinterface.cxx @@ -0,0 +1,399 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astinterface.hxx> +#include <astattribute.hxx> +#include <astoperation.hxx> +#include <idlc.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +#include <osl/diagnose.h> + +AstInterface::AstInterface(const OString& name, + AstInterface const * pInherits, + AstScope* pScope) + : AstType(NT_interface, name, pScope) + , AstScope(NT_interface) + , m_mandatoryInterfaces(0) + , m_bIsDefined(false) + , m_bSingleInheritance(pInherits != nullptr) +{ + if (pInherits != nullptr) { + addInheritedInterface(pInherits, false, OUString()); + } +} + +AstInterface::~AstInterface() +{ +} + +AstInterface::DoubleDeclarations AstInterface::checkInheritedInterfaceClashes( + AstInterface const * ifc, bool optional) const +{ + DoubleDeclarations doubleDecls; + std::set< OString > seen; + checkInheritedInterfaceClashes( + doubleDecls, seen, ifc, true, optional, optional); + return doubleDecls; +} + +void AstInterface::addInheritedInterface( + AstType const * ifc, bool optional, OUString const & documentation) +{ + m_inheritedInterfaces.emplace_back(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.emplace(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; +} + +bool AstInterface::dump(RegistryKey& rKey) +{ + if ( !isDefined() ) + return true; + + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + 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 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); + 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; + } + } + + typereg::Writer aBlob( + version, getDocumentation(), "", RT_TYPE_INTERFACE, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), nBaseTypes, + nAttributes, nMethods, nReferences); + + sal_uInt16 superTypeIndex = 0; + sal_uInt16 referenceIndex = 0; + for (auto const& elem : m_inheritedInterfaces) + { + if (elem.isOptional()) { + aBlob.setReferenceData( + referenceIndex++, elem.getDocumentation(), RTReferenceType::SUPPORTS, + RTFieldAccess::OPTIONAL, + OStringToOUString( + elem.getInterface()->getRelativName(), + RTL_TEXTENCODING_UTF8)); + } else { + aBlob.setSuperTypeName( + superTypeIndex++, + OStringToOUString( + elem.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( + aBlob, attributeIndex++, &methodIndex); + break; + + case NT_operation: + static_cast<AstOperation *>(*i)->dumpBlob(aBlob, methodIndex++); + break; + + default: + OSL_ASSERT(false); + break; + } + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 false; + } + + return true; +} + +void AstInterface::checkInheritedInterfaceClashes( + DoubleDeclarations & doubleDeclarations, + std::set< OString > & seenInterfaces, AstInterface const * ifc, + bool direct, bool optional, bool mainOptional) const +{ + if (!(direct || optional + || seenInterfaces.insert(ifc->getScopedName()).second)) + return; + + 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) + return; + + for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + checkMemberClashes( + doubleDeclarations.members, *i, !mainOptional); + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + checkInheritedInterfaceClashes( + doubleDeclarations, seenInterfaces, elem.getResolved(), + false, elem.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()) + return; + + if (i->second.mandatory != nullptr) { + 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 (auto const& elem : i->second.optionals) + { + if (elem.second->getScopedName() != member->getScopedName()) { + DoubleMemberDeclaration d; + d.first = elem.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.emplace(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) + return; + + for (DeclList::const_iterator i(ifc->getIteratorBegin()); + i != ifc->getIteratorEnd(); ++i) + { + m_visibleMembers.emplace( + (*i)->getLocalName(), VisibleMember(*i)); + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + addVisibleInterface(elem.getResolved(), false, elem.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.emplace( + (*i)->getLocalName(), VisibleMember()).first; + } + if (visible->second.mandatory == nullptr) { + visible->second.optionals.emplace(ifc->getScopedName(), *i); + } + } + for (auto const& elem : ifc->m_inheritedInterfaces) + { + if (!elem.isOptional()) { + addOptionalVisibleMembers(elem.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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astoperation.cxx b/idlc/source/astoperation.cxx new file mode 100644 index 000000000..4dea37576 --- /dev/null +++ b/idlc/source/astoperation.cxx @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <astoperation.hxx> +#include <asttype.hxx> +#include <astbasetype.hxx> +#include <astparameter.hxx> +#include <errorhandler.hxx> + +#include <registry/writer.hxx> + +void AstOperation::setExceptions(DeclList const * pExceptions) +{ + if (pExceptions != nullptr) { + m_exceptions = *pExceptions; + } +} + +bool AstOperation::isVariadic() const { + DeclList::const_iterator i(getIteratorEnd()); + return i != getIteratorBegin() + && static_cast< AstParameter const * >(*(--i))->isRest(); +} + +void AstOperation::dumpBlob(typereg::Writer & rBlob, sal_uInt16 index) +{ + sal_uInt16 nParam = getNodeCount(NT_parameter); + sal_uInt16 nExcep = static_cast<sal_uInt16>(m_exceptions.size()); + + OUString returnTypeName; + if (m_pReturnType == nullptr) { + returnTypeName = "void"; + } else { + returnTypeName = OStringToOUString( + m_pReturnType->getRelativName(), RTL_TEXTENCODING_UTF8); + } + rBlob.setMethodData( + index, getDocumentation(), RTMethodMode::TWOWAY, + OStringToOUString(getLocalName(), RTL_TEXTENCODING_UTF8), + returnTypeName, nParam, nExcep); + + if ( nParam ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + RTParamMode paramMode; + sal_uInt16 paramIndex = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_parameter ) + { + AstParameter* pParam = static_cast<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 ) + { + sal_uInt16 exceptIndex = 0; + for (auto const& exception : m_exceptions) + { + rBlob.setMethodExceptionTypeName( + index, exceptIndex++, + OStringToOUString( + exception->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astscope.cxx b/idlc/source/astscope.cxx new file mode 100644 index 000000000..f8309a766 --- /dev/null +++ b/idlc/source/astscope.cxx @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <algorithm> +#include <string_view> + +#include <astscope.hxx> +#include <astbasetype.hxx> +#include <astinterface.hxx> +#include <errorhandler.hxx> +#include <o3tl/string_view.hxx> +#include <osl/diagnose.h> + + +static bool isGlobal(std::string_view scopedName) +{ + return scopedName.empty() || o3tl::starts_with(scopedName, ":"); +} + +AstScope::AstScope(NodeType nodeType) + : m_nodeType(nodeType) +{ + +} + +AstScope::~AstScope() +{ + +} + +AstDeclaration* AstScope::addDeclaration(AstDeclaration* pDecl) +{ + AstDeclaration* pDeclaration = nullptr; + + if ((pDeclaration = lookupForAdd(pDecl)) != nullptr) + { + if ( pDecl->hasAncestor(pDeclaration) ) + { + ErrorHandler::error2(ErrorCode::RedefScope, pDecl, pDeclaration); + return nullptr; + } + if ( (pDecl->getNodeType() == pDeclaration->getNodeType()) && + (pDecl->getNodeType() == NT_sequence + || pDecl->getNodeType() == NT_instantiated_struct) ) + { + return pDeclaration; + } + if ( (pDeclaration->getNodeType() == NT_interface) + && (pDecl->getNodeType() == NT_interface) + && !(static_cast<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; + } + + ErrorHandler::error2(ErrorCode::RedefScope, scopeAsDecl(this), pDecl); + return nullptr; + } + + m_declarations.push_back(pDecl); + return pDecl; +} + +sal_uInt16 AstScope::getNodeCount(NodeType nodeType) const +{ + return static_cast<sal_uInt16>(std::count_if(getIteratorBegin(), getIteratorEnd(), + [&nodeType](const AstDeclaration* pDecl) { return pDecl->getNodeType() == nodeType; })); +} + +AstDeclaration* AstScope::lookupByName(const OString& scopedName) +{ + AstDeclaration* pDecl = nullptr; + AstScope* pScope = nullptr; + if (scopedName.isEmpty()) + return nullptr; + + // If name starts with "::" start look up in global scope + if ( isGlobal(scopedName) ) + { + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return nullptr; + + 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; + bool bFindFirstScope = true; + pDecl = lookupByNameLocal(firstScope); + if ( !pDecl ) + { + bFindFirstScope = 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 = nullptr; + + // Special case for scope which is an interface. We + // have to look in the inherited interfaces as well. + if ( !pDecl && m_nodeType == NT_interface ) + pDecl = lookupInInherited(scopedName); + } + } + + if ( !bFindFirstScope || (firstScope == scopedName) ) + return pDecl; + + sal_Int32 i = 0; + sal_Int32 nOffset = 2; + do + { + pScope = declAsScope(pDecl); + if( pScope ) + { + pDecl = pScope->lookupByNameLocal(o3tl::getToken(scopedName, 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().isEmpty() ) + { + pScope = pDecl->getScope(); + if ( pScope ) + pDecl = pScope->lookupByName(scopedName); + } else + { + pDecl = nullptr; + } + } + + return pDecl; +} + +AstDeclaration* AstScope::lookupByNameLocal(std::string_view name) const +{ + for (auto const& declaration : m_declarations) + { + if ( declaration->getLocalName() == name ) + return declaration; + } + return nullptr; +} + +AstDeclaration* AstScope::lookupInInherited(const OString& scopedName) const +{ + const AstInterface* pInterface = dynamic_cast<const AstInterface*>(this); + + if ( !pInterface ) + return nullptr; + + // Can't look in an interface which was not yet defined + if ( !pInterface->getScope() ) + { + ErrorHandler::forwardLookupError(pInterface, scopedName); + } + + // OK, loop through inherited interfaces. Stop when you find it + for (auto const& elem : pInterface->getAllInheritedInterfaces()) + { + AstInterface const * resolved = elem.getResolved(); + AstDeclaration* pDecl = resolved->lookupByNameLocal(scopedName); + if ( pDecl ) + return pDecl; + pDecl = resolved->lookupInInherited(scopedName); + if ( pDecl ) + return pDecl; + } + // Not found + return nullptr; +} + +AstDeclaration* AstScope::lookupPrimitiveType(ExprType type) +{ + AstDeclaration* pDecl = nullptr; + AstScope* pScope = nullptr; + OString typeName; + pDecl = scopeAsDecl(this); + if ( !pDecl ) + return nullptr; + 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) ) + { + AstBaseType* pBaseType = static_cast<AstBaseType*>(pDecl); + + if ( pBaseType->getExprType() == type ) + return pDecl; + } + + return nullptr; +} + +AstDeclaration* AstScope::lookupForAdd(AstDeclaration const * pDecl) const +{ + if ( !pDecl ) + return nullptr; + + AstDeclaration* pRetDecl = lookupByNameLocal(pDecl->getLocalName()); + + return pRetDecl; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/astservice.cxx b/idlc/source/astservice.cxx new file mode 100644 index 000000000..c90ded6b4 --- /dev/null +++ b/idlc/source/astservice.cxx @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <sal/config.h> + +#include <astmember.hxx> +#include <astoperation.hxx> +#include <astservice.hxx> +#include <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()) { + return std::equal(ctor->getIteratorBegin(), ctor->getIteratorEnd(), last->getIteratorBegin(), + [](AstDeclaration* a, AstDeclaration* b) { + sal_Int32 r1; + AstDeclaration const * t1 = deconstructAndResolveTypedefs(static_cast< AstMember * >(a)->getType(), &r1); + sal_Int32 r2; + AstDeclaration const * t2 = deconstructAndResolveTypedefs(static_cast< AstMember * >(b)->getType(), &r2); + return r1 == r2 && t1->getScopedName() == t2->getScopedName(); + }); + } + } + } + return false; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststack.cxx b/idlc/source/aststack.cxx new file mode 100644 index 000000000..fcddc810d --- /dev/null +++ b/idlc/source/aststack.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <rtl/alloc.h> +#include <aststack.hxx> +#include <astscope.hxx> + +AstStack::AstStack() {} + +AstStack::~AstStack() +{ + for (AstScope* p : m_stack) + delete p; +} + +AstScope* AstStack::top() +{ + if (m_stack.empty()) + return nullptr; + return m_stack.back(); +} + +AstScope* AstStack::bottom() +{ + if (m_stack.empty()) + return nullptr; + return m_stack.front(); +} + +AstScope* AstStack::nextToTop() +{ + if (m_stack.size() < 2) + return nullptr; + + return m_stack[m_stack.size() - 2]; +} + +AstScope* AstStack::topNonNull() +{ + for (sal_uInt32 i = m_stack.size(); i > 0; i--) + { + if (m_stack[i - 1]) + return m_stack[i - 1]; + } + return nullptr; +} + +AstStack* AstStack::push(AstScope* pScope) +{ + m_stack.push_back(pScope); + return this; +} + +void AstStack::pop() +{ + if (m_stack.empty()) + return; + m_stack.pop_back(); +} + +void AstStack::clear() { m_stack.clear(); } + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststruct.cxx b/idlc/source/aststruct.cxx new file mode 100644 index 000000000..00ac33021 --- /dev/null +++ b/idlc/source/aststruct.cxx @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <aststruct.hxx> +#include <astmember.hxx> + +#include <registry/version.h> +#include <registry/writer.hxx> + +AstStruct::AstStruct( + const OString& name, std::vector< OString > const & typeParameters, + AstStruct const* pBaseType, AstScope* pScope) + : AstType(NT_struct, name, pScope) + , AstScope(NT_struct) + , m_pBaseType(pBaseType) +{ + for (auto const& elem : typeParameters) + { + m_typeParameters.emplace_back( + new AstType(NT_type_parameter, elem, nullptr)); + } +} + +AstStruct::AstStruct(const NodeType type, + const OString& name, + AstStruct const* pBaseType, + AstScope* pScope) + : AstType(type, name, pScope) + , AstScope(type) + , m_pBaseType(pBaseType) +{ +} + +AstStruct::~AstStruct() +{ +} + +AstDeclaration const * AstStruct::findTypeParameter(std::string_view name) + const +{ + for (auto const& elem : m_typeParameters) + { + if (elem->getLocalName() == name) { + return elem.get(); + } + } + return nullptr; +} + +bool AstStruct::isType() const { + return getNodeType() == NT_struct + ? getTypeParameterCount() == 0 : AstDeclaration::isType(); +} + +bool AstStruct::dump(RegistryKey& rKey) +{ + RegistryKey localKey; + if (rKey.createKey( OStringToOUString(getFullName(), RTL_TEXTENCODING_UTF8 ), localKey) != RegError::NO_ERROR) + { + 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 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; + + typereg::Writer aBlob( + (m_typeParameters.empty() && !m_bPublished + ? TYPEREG_VERSION_0 : TYPEREG_VERSION_1), + getDocumentation(), "", typeClass, m_bPublished, + OStringToOUString(getRelativName(), RTL_TEXTENCODING_UTF8), + m_pBaseType == nullptr ? 0 : 1, nMember, 0, + static_cast< sal_uInt16 >(m_typeParameters.size())); + if (m_pBaseType != nullptr) { + aBlob.setSuperTypeName( + 0, + OStringToOUString( + m_pBaseType->getRelativName(), RTL_TEXTENCODING_UTF8)); + } + + if ( nMember > 0 ) + { + DeclList::const_iterator iter = getIteratorBegin(); + DeclList::const_iterator end = getIteratorEnd(); + AstMember* pMember = nullptr; + sal_uInt16 index = 0; + while ( iter != end ) + { + AstDeclaration* pDecl = *iter; + if ( pDecl->getNodeType() == NT_member ) + { + pMember = static_cast<AstMember*>(pDecl); + RTFieldAccess flags = RTFieldAccess::READWRITE; + OString typeName; + if (pMember->getType()->getNodeType() == NT_type_parameter) { + flags |= RTFieldAccess::PARAMETERIZED_TYPE; + typeName = pMember->getType()->getLocalName(); + } else { + typeName = pMember->getType()->getRelativName(); + } + aBlob.setFieldData( + index++, pMember->getDocumentation(), "", flags, + OStringToOUString( + pMember->getLocalName(), RTL_TEXTENCODING_UTF8), + OStringToOUString(typeName, RTL_TEXTENCODING_UTF8), + RTConstValue()); + } + ++iter; + } + } + + sal_uInt16 index = 0; + for (auto const& elem : m_typeParameters) + { + aBlob.setReferenceData( + index++, "", RTReferenceType::TYPE_PARAMETER, RTFieldAccess::INVALID, + OStringToOUString( + elem->getLocalName(), RTL_TEXTENCODING_UTF8)); + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast<RegValue>(pBlob), aBlobSize) != RegError::NO_ERROR) + { + 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 false; + } + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/aststructinstance.cxx b/idlc/source/aststructinstance.cxx new file mode 100644 index 000000000..878745793 --- /dev/null +++ b/idlc/source/aststructinstance.cxx @@ -0,0 +1,63 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <aststructinstance.hxx> + +#include <asttype.hxx> +#include <idlctypes.hxx> + +#include <rtl/strbuf.hxx> +#include <rtl/string.hxx> + +namespace { + +OString createName( + AstType const * typeTemplate, DeclList const * typeArguments) +{ + OStringBuffer buf(64); + buf.append(typeTemplate->getScopedName()); + if (typeArguments != nullptr) { + buf.append('<'); + for (DeclList::const_iterator i(typeArguments->begin()); + i != typeArguments->end(); ++i) + { + if (i != typeArguments->begin()) { + buf.append(','); + } + if (*i != nullptr) { + 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) +{} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/attributeexceptions.hxx b/idlc/source/attributeexceptions.hxx new file mode 100644 index 000000000..82ce1cf19 --- /dev/null +++ b/idlc/source/attributeexceptions.hxx @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_IDLC_SOURCE_ATTRIBUTEEXCEPTIONS_HXX +#define INCLUDED_IDLC_SOURCE_ATTRIBUTEEXCEPTIONS_HXX + +#include <rtl/ustring.hxx> + +struct AttributeExceptions +{ + struct Part + { + OUString const* documentation; + DeclList const* exceptions; + }; + Part get; + Part set; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/errorhandler.cxx b/idlc/source/errorhandler.cxx new file mode 100644 index 000000000..aa2de56bc --- /dev/null +++ b/idlc/source/errorhandler.cxx @@ -0,0 +1,583 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <errorhandler.hxx> +#include <astinterface.hxx> + +static const char* errorCodeToMessage(ErrorCode eCode) +{ + switch (eCode) + { + case ErrorCode::SyntaxError: + return ""; + case ErrorCode::RedefScope: + return "illegal redefinition in scope "; + case ErrorCode::CoercionFailure: + return "coercion failure "; + case ErrorCode::ScopeConflict: + return "definition scope is different than fwd declare scope, "; + case ErrorCode::IllegalAdd: + return "illegal add operation, "; + case ErrorCode::IllegalRaises: + return "non-exception type in raises(..) clause, "; + case ErrorCode::CantInherit: + return "cannot inherit "; + case ErrorCode::IdentNotFound: + return "error in lookup of symbol: "; + case ErrorCode::CannotInheritFromForward: + return ""; + case ErrorCode::ExpectedConstant: + return "constant expected: "; + case ErrorCode::Eval: + return "expression evaluation error: "; + case ErrorCode::ForwardDeclLookup: + return ""; + case ErrorCode::RecursiveType: + return "illegal recursive use of type: "; + case ErrorCode::NotAType: + return "specified symbol is not a type: "; + case ErrorCode::InterfaceMemberLookup: + return "error in lookup of symbol, expected interface is not defined and no forward exists: "; + case ErrorCode::ServiceMemberLookup: + return "error in lookup of symbol, expected service is not defined: "; + case ErrorCode::DefinedAttributeFlag: + return "flag is already set: "; + case ErrorCode::WrongAttributeKeyword: + return "keyword not allowed: "; + case ErrorCode::MissingAttributeKeyword: + return "missing keyword: "; + case ErrorCode::BadAttributeFlags: + return + "the 'attribute' flag is mandatory, and only the 'bound' and" + " 'readonly' optional flags are accepted: "; + case ErrorCode::ExpectedOptional: + return "only the 'optional' flag is accepted: "; + case ErrorCode::MixedInheritance: + return "interface inheritance declarations cannot appear in both an" + " interface's header and its body"; + case ErrorCode::DoubleInheritance: + return + "interface is (directly or indirectly) inherited more than once: "; + case ErrorCode::DoubleMember: + return + "member is (directly or indirectly) declared more than once: "; + case ErrorCode::ConstructorParameterNotIn: + return + "a service constructor parameter may not be an out or inout" + " parameter"; + case ErrorCode::ConstructorRestParameterNotFirst: + return + "no parameters may precede a rest parameter in a service" + " constructor"; + case ErrorCode::RestParameterNotLast: + return "no parameters may follow a rest parameter"; + case ErrorCode::RestParameterNotAny: + return "a rest parameter must be of type any"; + case ErrorCode::MethodHasRestParameter: + return "a rest parameter may not be used on an interface method"; + case ErrorCode::ReadOnlyAttributeSetExceptions: + return "a readonly attribute may not have a setter raises clause"; + case ErrorCode::UnsignedTypeArgument: + return "an unsigned type cannot be used as a type argument"; + case ErrorCode::WrongNumberOfTypeArguments: + return + "the number of given type arguments does not match the expected" + " number of type parameters"; + case ErrorCode::InstantiatedStructTypeTypedef: + return + "an instantiated polymorphic struct type cannot be used in a" + " typedef"; + case ErrorCode::IdenticalTypeParameters: + return "two type parameters have the same name"; + case ErrorCode::StructTypeTemplateWithBase: + return "a polymorphic struct type template may not have a base type"; + case ErrorCode::PublishedForward: + return + "a published forward declaration of an interface type cannot be" + " followed by an unpublished declaration of that type"; + case ErrorCode::PublishedusesUnpublished: + return + "an unpublished entity cannot be used in the declaration of a" + " published entity: "; + case ErrorCode::SimilarConstructors: + return "two constructors have identical lists of parameter types"; + } + return "unknown error"; +} + +static const char* warningCodeToMessage(WarningCode wCode) +{ + switch (wCode) + { + case WarningCode::WrongNamingConvention: + return "type or identifier doesn't fulfill the UNO naming convention: "; + } + return "unknown warning"; +} + +static const 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 service 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 a 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_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_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_MayBeAmbiguousSeen: + return "Illegal syntax after MAYBEAMBIGUOUS keyword"; + case PS_MayBeDefaultSeen: + return "Illegal syntax after MAYBEDEFAULT keyword"; + case PS_RemoveableSeen: + return "Illegal syntax after REMOVABLE 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_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_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_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_REMOVABLE) == AF_REMOVABLE ) + flagStr += "'removable'"; + if ( (flag & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + flagStr += "'attribute'"; + if ( (flag & AF_PROPERTY) == AF_PROPERTY ) + flagStr += "'property'"; + if ( flagStr.isEmpty() ) + flagStr += "'unknown'"; + + return flagStr; +} + +static void errorHeader(ErrorCode eCode, sal_Int32 lineNumber, sal_uInt32 start, sal_uInt32 end) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s:%" SAL_PRIdINT64 " [%" SAL_PRIdINT64 ":%" SAL_PRIdINT64 "] : %s", file.getStr(), + sal_Int64(lineNumber), + sal_Int64(start), + sal_Int64(end), + errorCodeToMessage(eCode)); +} + +static void errorHeader(ErrorCode eCode, sal_uInt32 lineNumber) +{ + errorHeader(eCode, lineNumber, + idlc()->getOffsetStart(), idlc()->getOffsetEnd()); +} + +static void errorHeader(ErrorCode eCode) +{ + errorHeader(eCode, idlc()->getLineNumber(), + idlc()->getOffsetStart(), idlc()->getOffsetEnd()); +} + +static void warningHeader(WarningCode wCode) +{ + OString file; + if ( idlc()->getFileName() == idlc()->getRealFileName() ) + file = idlc()->getMainFileName(); + else + file = idlc()->getFileName(); + + fprintf(stderr, "%s(%" SAL_PRIdINT64 ") : WARNING, %s", file.getStr(), + sal_Int64(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 const * d1, AstDeclaration const * d2, AstDeclaration const * 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 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 char* errmsg) +{ + errorHeader(ErrorCode::SyntaxError, lineNumber); + fprintf(stderr, "%s: %s\n", parseStateToMessage(ps), errmsg); + idlc()->incErrorCount(); +} + +void ErrorHandler::coercionError(AstExpression *pExpr, ExprType et) +{ + errorHeader(ErrorCode::CoercionFailure); + fprintf(stderr, "'%s' to '%s'\n", pExpr->toString().getStr(), + exprTypeToString(et)); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(const OString& n) +{ + errorHeader(ErrorCode::IdentNotFound); + fprintf(stderr, "'%s'\n", n.getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::lookupError(ErrorCode e, const OString& n, AstDeclaration const * 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(ErrorCode::NotAType); + 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 const * pDecl) +{ + if ( nodeType == NT_interface && + (pDecl->getNodeType() == NT_interface) && + !(static_cast<AstInterface const *>(pDecl)->isDefined()) ) + { + errorHeader(ErrorCode::CannotInheritFromForward); + fprintf(stderr, "interface '%s' cannot inherit from forward declared interface '%s'\n", + name->getStr(), pDecl->getScopedName().getStr()); + } else + { + errorHeader(ErrorCode::CantInherit); + fprintf(stderr, "%s '%s' from '%s'\n", + nodeTypeName(nodeType), name->getStr(), + pDecl->getScopedName().getStr()); + } + idlc()->incErrorCount(); +} + +void ErrorHandler::forwardLookupError(const AstDeclaration* pForward, + const OString& name) +{ + errorHeader(ErrorCode::ForwardDeclLookup); + 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 const * pDecl, + const OString& name) +{ + errorHeader(ErrorCode::ExpectedConstant); + fprintf(stderr, "'%s' is bound to '%s'\n", name.getStr(), pDecl->getScopedName().getStr()); + idlc()->incErrorCount(); +} + +void ErrorHandler::evalError(AstExpression* pExpr) +{ + errorHeader(ErrorCode::Eval); + fprintf(stderr, "'%s'\n", pExpr->toString().getStr()); + idlc()->incErrorCount(); +} + +bool ErrorHandler::checkPublished(AstDeclaration const * decl, bool bOptional) { + if (idlc()->isPublished() && !decl->isPublished() && !bOptional) { + error1(ErrorCode::PublishedusesUnpublished, decl); + return false; + } else { + return true; + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/fehelper.cxx b/idlc/source/fehelper.cxx new file mode 100644 index 000000000..607f5a145 --- /dev/null +++ b/idlc/source/fehelper.cxx @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <fehelper.hxx> +#include <errorhandler.hxx> +#include <idlc.hxx> + +FeDeclarator::FeDeclarator(const OString& name) + : m_name(name) +{ +} + +FeDeclarator::~FeDeclarator() +{ +} + +bool FeDeclarator::checkType(AstDeclaration const * type) const +{ + OString tmp(m_name); + sal_Int32 count = m_name.lastIndexOf( ':' ); + if( count != -1 ) + tmp = m_name.copy( count+1 ); + + return tmp != type->getLocalName(); +} + +AstType const * FeDeclarator::compose(AstDeclaration const * pDecl) +{ + if ( pDecl == nullptr ) + { + return nullptr; + } + if ( !pDecl->isType() ) + { + ErrorHandler::noTypeError(pDecl); + return nullptr; + } + return static_cast<const AstType*>(pDecl); +} + +FeInheritanceHeader::FeInheritanceHeader( + NodeType nodeType, OString* pName, OString const * pInherits, + std::vector< OString > const * typeParameters) + : m_nodeType(nodeType) + , m_pName(pName) + , m_pInherits(nullptr) +{ + if (typeParameters != nullptr) { + m_typeParameters = *typeParameters; + } + initializeInherits(pInherits); +} + +void FeInheritanceHeader::initializeInherits(OString const * pInherits) +{ + if ( !pInherits ) + return; + + 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 ( ErrorHandler::checkPublished( pDecl ) ) + { + m_pInherits = pDecl; + } + } + else + { + ErrorHandler::inheritanceError( + getNodeType(), getName(), pDecl); + } + } + else + { + ErrorHandler::lookupError(*pInherits); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlc.cxx b/idlc/source/idlc.cxx new file mode 100644 index 000000000..ca47b34fe --- /dev/null +++ b/idlc/source/idlc.cxx @@ -0,0 +1,400 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <idlc.hxx> +#include <errorhandler.hxx> +#include <astscope.hxx> +#include <astmodule.hxx> +#include <astservice.hxx> +#include <astconstants.hxx> +#include <astexception.hxx> +#include <astenum.hxx> +#include <astinterface.hxx> +#include <astoperation.hxx> +#include <astbasetype.hxx> +#include <astdeclaration.hxx> +#include <astparameter.hxx> +#include <astsequence.hxx> +#include <asttype.hxx> +#include <asttypedef.hxx> + +#include <osl/diagnose.h> +#include <osl/file.hxx> +#include <osl/thread.h> + +#include <algorithm> + +AstDeclaration* scopeAsDecl(AstScope* pScope) +{ + if (pScope == nullptr) return nullptr; + + switch( pScope->getScopeNodeType() ) + { + case NT_service: + case NT_singleton: + return static_cast<AstService*>(pScope); + case NT_module: + case NT_root: + return static_cast<AstModule*>(pScope); + case NT_constants: + return static_cast<AstConstants*>(pScope); + case NT_interface: + return static_cast<AstInterface*>(pScope); + case NT_operation: + return static_cast<AstOperation*>(pScope); + case NT_exception: + return static_cast<AstException*>(pScope); + case NT_struct: + return static_cast<AstStruct*>(pScope); + case NT_enum: + return static_cast<AstEnum*>(pScope); + default: + return nullptr; + } +} + +AstScope* declAsScope(AstDeclaration* pDecl) +{ + if (pDecl == nullptr) return nullptr; + + switch(pDecl->getNodeType()) + { + case NT_interface: + return static_cast<AstInterface*>(pDecl); + case NT_service: + case NT_singleton: + return static_cast<AstService*>(pDecl); + case NT_module: + case NT_root: + return static_cast<AstModule*>(pDecl); + case NT_constants: + return static_cast<AstConstants*>(pDecl); + case NT_exception: + return static_cast<AstException*>(pDecl); + case NT_struct: + return static_cast<AstStruct*>(pDecl); + case NT_enum: + return static_cast<AstEnum*>(pDecl); + case NT_operation: + return static_cast<AstOperation*>(pDecl); + default: + return nullptr; + } +} + +static void predefineXInterface(AstModule* pRoot) +{ + // define the modules com::sun::star::uno + AstModule* pParentScope = pRoot; + AstModule* pModule = new AstModule("com", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("sun", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("star", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + pModule = new AstModule("uno", pParentScope); + pModule->setPredefined(true); + pParentScope->addDeclaration(pModule); + pParentScope = pModule; + + // define XInterface + AstInterface* pInterface = new AstInterface("XInterface", nullptr, pParentScope); + pInterface->setDefined(); + pInterface->setPredefined(true); + pInterface->setPublished(); + pParentScope->addDeclaration(pInterface); + + // define XInterface::queryInterface + AstOperation* pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_any)), + "queryInterface", pInterface); + AstParameter* pParam = new AstParameter(DIR_IN, false, + static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_type)), + "aType", pOp); + pOp->addDeclaration(pParam); + pInterface->addMember(pOp); + + // define XInterface::acquire + pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)), + "acquire", pInterface); + pInterface->addMember(pOp); + + // define XInterface::release + pOp = new AstOperation(static_cast<AstType*>(pRoot->lookupPrimitiveType(ET_void)), + "release", pInterface); + pInterface->addMember(pOp); +} + +static void initializePredefinedTypes(AstModule* pRoot) +{ + if ( !pRoot ) + return; + + AstBaseType* pPredefined = new AstBaseType(ET_long, "long", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ulong, "unsigned long", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_hyper, "hyper", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_uhyper, "unsigned hyper", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_short, "short", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_ushort, "unsigned short", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_float, "float", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_double, "double", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_char, "char", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_byte, "byte", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_any, "any", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_string, "string", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_type, "type", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_boolean, "boolean", pRoot); + pRoot->addDeclaration(pPredefined); + + pPredefined = new AstBaseType(ET_void, "void", pRoot); + pRoot->addDeclaration(pPredefined); +} + +Idlc::Idlc(Options* pOptions) + : m_pOptions(pOptions) + , m_bIsDocValid(false) + , m_bIsInMainfile(true) + , m_published(false) + , m_errorCount(0) + , m_warningCount(0) + , m_lineNumber(0) + , m_offsetStart(0) + , m_offsetEnd(0) + , m_parseState(PS_NoState) +{ + m_pScopes.reset( new AstStack() ); + // init root object after construction + m_pRoot = nullptr; + m_bGenerateDoc = m_pOptions->isValid("-C"); +} + +Idlc::~Idlc() +{ +} + +void Idlc::init() +{ + m_pRoot.reset(new AstModule(NT_root, OString(), nullptr)); + + // push the root node on the stack + m_pScopes->push(m_pRoot.get()); + initializePredefinedTypes(m_pRoot.get()); + predefineXInterface(m_pRoot.get()); +} + +void Idlc::reset() +{ + m_bIsDocValid = false; + m_bIsInMainfile = true; + m_published = false; + + m_errorCount = 0; + m_warningCount = 0; + m_lineNumber = 0; + m_parseState = PS_NoState; + + m_fileName.clear(); + m_mainFileName.clear(); + m_realFileName.clear(); + m_documentation.clear(); + + m_pScopes->clear(); + m_pRoot.reset( new AstModule(NT_root, OString(), nullptr) ); + + // push the root node on the stack + m_pScopes->push(m_pRoot.get()); + initializePredefinedTypes(m_pRoot.get()); + + m_includes.clear(); +} + +OUString Idlc::processDocumentation() +{ + OUString doc; + if (m_bIsDocValid) { + OString raw(getDocumentation()); + if (m_bGenerateDoc) { + doc = OStringToOUString(raw, RTL_TEXTENCODING_UTF8); + } else if (raw.indexOf("@deprecated") != -1) { + //TODO: this check is somewhat crude + doc = "@deprecated"; + } + } + return doc; +} + +static void lcl_writeString(::osl::File & rFile, ::osl::FileBase::RC & o_rRC, + OString const& rString) +{ + if (::osl::FileBase::E_None == o_rRC) { + sal_uInt64 nWritten(0); + o_rRC = rFile.write(rString.getStr(), rString.getLength(), nWritten); + if (static_cast<sal_uInt64>(rString.getLength()) != nWritten) { + o_rRC = ::osl::FileBase::E_INVAL; //? + } + } +} + +namespace { + +struct WriteDep +{ + ::osl::File& m_rFile; + ::osl::FileBase::RC & m_rRC; + explicit WriteDep(::osl::File & rFile, ::osl::FileBase::RC & rRC) + : m_rFile(rFile), m_rRC(rRC) { } + void operator() (OString const& rEntry) + { + lcl_writeString(m_rFile, m_rRC, " \\\n "); + lcl_writeString(m_rFile, m_rRC, rEntry); + } +}; + +// write a dummy target for one included file, so the incremental build does +// not break with "No rule to make target" if the included file is removed +struct WriteDummy +{ + ::osl::File& m_rFile; + ::osl::FileBase::RC & m_rRC; + explicit WriteDummy(::osl::File & rFile, ::osl::FileBase::RC & rRC) + : m_rFile(rFile), m_rRC(rRC) { } + void operator() (OString const& rEntry) + { + lcl_writeString(m_rFile, m_rRC, rEntry); + lcl_writeString(m_rFile, m_rRC, ":\n\n"); + } +}; + +} + +bool +Idlc::dumpDeps(std::string_view rDepFile, OString const& rTarget) +{ + ::osl::File depFile( + OStringToOUString(rDepFile, osl_getThreadTextEncoding())); + ::osl::FileBase::RC rc = + depFile.open(osl_File_OpenFlag_Write | osl_File_OpenFlag_Create); + if (::osl::FileBase::E_None != rc) { + return false; + } + lcl_writeString(depFile, rc, rTarget); + if (::osl::FileBase::E_None != rc) { + return false; + } + lcl_writeString(depFile, rc, " :"); + if (::osl::FileBase::E_None != rc) { + return false; + } + m_includes.erase(getRealFileName()); // eeek, that is a temp file... + ::std::for_each(m_includes.begin(), m_includes.end(), + WriteDep(depFile, rc)); + lcl_writeString(depFile, rc, "\n\n"); + ::std::for_each(m_includes.begin(), m_includes.end(), + WriteDummy(depFile, rc)); + if (::osl::FileBase::E_None != rc) { + return false; + } + rc = depFile.close(); + return ::osl::FileBase::E_None == rc; +} + +static Idlc* pStaticIdlc = nullptr; + +Idlc* idlc() +{ + return pStaticIdlc; +} + +Idlc* setIdlc(Options* pOptions) +{ + delete pStaticIdlc; + pStaticIdlc = new Idlc(pOptions); + pStaticIdlc->init(); + return pStaticIdlc; +} + +AstDeclaration const * resolveTypedefs(AstDeclaration const * type) { + if (type != nullptr) { + 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 == nullptr) { + return nullptr; + } + 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); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlccompile.cxx b/idlc/source/idlccompile.cxx new file mode 100644 index 000000000..5aec20912 --- /dev/null +++ b/idlc/source/idlccompile.cxx @@ -0,0 +1,394 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <idlc.hxx> +#include <rtl/alloc.h> +#include <rtl/ustring.hxx> +#include <rtl/strbuf.hxx> +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <osl/process.h> +#include <osl/diagnose.h> +#include <osl/thread.h> +#include <osl/file.hxx> + +#if defined(_WIN32) +#include <io.h> +#endif + +#ifdef SAL_UNX +#include <errno.h> +#include <unistd.h> +#include <sys/wait.h> +#endif + +#include <string.h> + +using namespace ::osl; + +extern int yyparse(); +extern FILE* yyin; +extern int yydebug; + +static char tmpFilePattern[512]; + +bool isFileUrl(std::string_view fileName) +{ + return o3tl::starts_with(fileName, "file://"); +} + +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; +} + +static OString makeTempName(const OString& prefix) +{ + OUString uTmpPath; + OString tmpPath; + + if ( osl_getEnvironment(OUString("TMP").pData, &uTmpPath.pData) != osl_Process_E_None ) + { + if ( osl_getEnvironment(OUString("TEMP").pData, &uTmpPath.pData) != osl_Process_E_None ) + { +#if defined(_WIN32) + tmpPath = OString("c:\\temp"); +#else + tmpPath = OString("/tmp"); +#endif + } + } + + if ( !uTmpPath.isEmpty() ) + tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8); + +#if defined(_WIN32) || defined(SAL_UNX) + + OSL_ASSERT( sizeof(tmpFilePattern) > + o3tl::make_unsigned( tmpPath.getLength() + + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR ) + + prefix.getLength() + + RTL_CONSTASCII_LENGTH( "XXXXXX") ) ); + + tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0'; + strncpy(tmpFilePattern, tmpPath.getStr(), 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 + // coverity[secure_temp] - https://communities.coverity.com/thread/3179 + int nDescriptor = mkstemp(tmpFilePattern); + if( -1 == nDescriptor ) + { + fprintf(stderr, "idlc: mkstemp(\"%s\") failed: %s\n", tmpFilePattern, strerror(errno)); + exit( 1 ); + } + // the file shall later be reopened by stdio functions + close( nDescriptor ); +#else + (void) mktemp(tmpFilePattern); +#endif +#endif + + return tmpFilePattern; +} + +bool copyFile(const OString* source, const OString& target) +{ + bool bRet = true; + + FILE* pSource = source == nullptr ? stdin : fopen(source->getStr(), "rb"); + if ( !pSource ) + return false; + + FILE* pTarget = fopen(target.getStr(), "wb"); + if ( !pTarget ) + { + fclose(pSource); + return false; + } + + size_t const totalSize = 512; + char pBuffer[totalSize + 1]; + + while ( !feof(pSource) ) + { + size_t readSize = fread(pBuffer, 1, totalSize, pSource); + if ( readSize > 0 && !ferror(pSource) ) + { + if ( (fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) ) + { + if (source != nullptr) { + fclose(pSource); + } + fclose(pTarget); + return false; + } + } + } + + if (source != nullptr) { + fclose(pSource); + } + if ( fclose(pTarget) ) + bRet = false; + + return bRet; +} + +sal_Int32 compileFile(const OString * pathname) +{ + // preprocess input file + OString tmpFile = makeTempName("idli_"); + OString preprocFile = makeTempName("idlf_"); + + OString fileName; + if (pathname == nullptr) { + 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 == nullptr ? "" : "file ", fileName.getStr(), + tmpFile.getStr()); + exit(99); + } + + idlc()->setFileName(fileName); + idlc()->setMainFileName(fileName); + idlc()->setRealFileName(tmpFile); + + ::std::vector< OUString> lCppArgs; + lCppArgs.emplace_back("-DIDL"); + lCppArgs.emplace_back("-C"); +#ifdef SYSTEM_UCPP_IS_GCC + // -nostdinc Do not search the standard system directories for header files + lCppArgs.emplace_back("-nostdinc"); + // with gcc cpp, even when not explicitly including anything, /usr/include/stdc-predef.h + // gets inserted without -nostdinc +#else + // -zI Do not use the standard (compile-time) include path. + lCppArgs.emplace_back("-zI"); +#endif + + Options* pOptions = idlc()->getOptions(); + + OString filePath; + sal_Int32 index = fileName.lastIndexOf(SEPARATOR); + + if ( index > 0) + { + filePath = fileName.copy(0, index); + + if ( !filePath.isEmpty() ) + { + OString cppArgs = "-I" + filePath; + lCppArgs.push_back(OStringToOUString( + cppArgs.replace('\\', '/'), + RTL_TEXTENCODING_UTF8)); + } + } + + if ( pOptions->isValid("-D") ) + { + OString dOpt = pOptions->getOption("-D"); + sal_Int32 nIndex = 0; + do + { + std::string_view token = o3tl::getToken(dOpt, 0, ' ', nIndex ); + if (token.size()) + lCppArgs.push_back("-D" + OStringToOUString(token, RTL_TEXTENCODING_UTF8)); + } while( nIndex != -1 ); + } + + if ( pOptions->isValid("-I") ) + { + OString incOpt = pOptions->getOption("-I"); + sal_Int32 nIndex = 0; + do + { + std::string_view token = o3tl::getToken(incOpt, 0, ' ', nIndex ); + if (token.size()) + lCppArgs.push_back("-I" + OStringToOUString(token, RTL_TEXTENCODING_UTF8)); + } while( nIndex != -1 ); + } + + lCppArgs.emplace_back("-o"); + + lCppArgs.push_back(OStringToOUString(preprocFile, RTL_TEXTENCODING_UTF8)); + + lCppArgs.push_back(OStringToOUString(tmpFile, RTL_TEXTENCODING_UTF8)); + + OUString cpp; + OUString startDir; +#ifndef SYSTEM_UCPP + if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) { + OSL_ASSERT(false); + } + + sal_Int32 idx= cpp.lastIndexOf("idlc"); + cpp = cpp.copy(0, idx); + +#if defined(_WIN32) + cpp += "ucpp.exe"; +#else + cpp += "ucpp"; +#endif +#else // SYSTEM_UCPP + cpp = OUString(UCPP); +#endif + oslProcess hProcess = nullptr; + oslProcessError procError = osl_Process_E_None; + + const int nCmdArgs = lCppArgs.size(); + std::unique_ptr<rtl_uString*[]> pCmdArgs(new rtl_uString*[nCmdArgs]); + + int i = 0; + for (auto const& elem : lCppArgs) + { + pCmdArgs[i++] = elem.pData; + } + + procError = osl_executeProcess( cpp.pData, pCmdArgs.get(), nCmdArgs, osl_Process_WAIT, + nullptr, startDir.pData, nullptr, 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 == nullptr ? "" : "file ", fileName.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 ( pOptions->isValid("-E") ) + { + if (unlink(preprocFile.getStr()) != 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 == nullptr) + { + 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; + + yyparse(); + sal_Int32 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; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlcmain.cxx b/idlc/source/idlcmain.cxx new file mode 100644 index 000000000..742dc4e81 --- /dev/null +++ b/idlc/source/idlcmain.cxx @@ -0,0 +1,164 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <idlc.hxx> +#include <sal/main.h> + +#include <string.h> + +SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv) +{ + std::vector< std::string > args; + for (int i = 1; i < argc; i++) + { + if (!Options::checkArgument (args, argv[i], strlen(argv[i]))) + return 1; + } + + Options options(argv[0]); + sal_Int32 nErrors = 0; + + try + { + if (!options.initOptions(args)) + return 0; + + setIdlc(&options); + + if (options.readStdin()) { + if ( !options.quiet() ) + fprintf( + stdout, "%s: Compiling stdin\n", + options.getProgramName().getStr()); + nErrors = compileFile(nullptr); + 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.endsWith("/")) { + outputUrl += "/"; + } + outputUrl += "stdin.urd"; + } else { + outputUrl = convertToFileUrl("stdin.urd"); + } + if (nErrors > 0) { + removeIfExists(outputUrl); + } else { + nErrors = produceFile(outputUrl, nullptr); + } + idlc()->reset(); + } + std::vector< OString > const & files = options.getInputFiles(); + if ( options.verbose() ) + { + fprintf( stdout, "%s: compiling %i source files ... \n", + options.getProgramName().getStr(), static_cast<int>(files.size()) ); + fflush( stdout ); + } + for (auto const& elem : files) + { + if (nErrors) + break; + OString sysFileName( convertToAbsoluteSystemPath(elem) ); + + if ( !options.quiet() ) + fprintf(stdout, "Compiling: %s\n", elem.getStr()); + nErrors = compileFile(&sysFileName); + + if ( idlc()->getWarningCount() && !options.quiet() ) + fprintf(stdout, "%s: detected %" SAL_PRIdINT64 " warnings compiling file '%s'\n", + options.getProgramName().getStr(), + sal_Int64(idlc()->getWarningCount()), + elem.getStr()); + + // prepare output file name + OString const strippedFileName( + sysFileName.copy(sysFileName.lastIndexOf(SEPARATOR) + 1)); + OString outputFile; + if ( options.isValid("-O") ) + { + outputFile = options.getOption("-O"); + if (!outputFile.endsWith("/")) { + outputFile += "/"; + } + outputFile += strippedFileName.replaceAt( + strippedFileName.getLength() -3 , 3, "urd"); + } else { + outputFile = + sysFileName.replaceAt(sysFileName.getLength() -3 , 3, "urd"); + } + OString const outputFileUrl = convertToFileUrl(outputFile); + + OString depFileUrl; + if (options.isValid("-M")) { + depFileUrl = convertToFileUrl(options.getOption("-M")); + if (!depFileUrl.endsWith("/")) { + depFileUrl += "/"; + } + depFileUrl += strippedFileName.replaceAt( + strippedFileName.getLength() -3 , 3, "d"); + } + + if ( nErrors ) { + if (options.isValid("-M")) { + removeIfExists(depFileUrl); + } + removeIfExists(outputFileUrl); + } else { + sPair_t const pair(depFileUrl, outputFile); + nErrors = produceFile(outputFileUrl, + (options.isValid("-M")) ? &pair : nullptr); + } + + idlc()->reset(); + } + + if ( nErrors > 0 ) + { + fprintf(stderr, "%s: detected %" SAL_PRIdINT64 " errors%s", + options.getProgramName().getStr(), + sal_Int64(nErrors), + options.prepareVersion().getStr()); + } else + { + if ( options.verbose() ) + fprintf(stdout, "%s: returned successful%s", + options.getProgramName().getStr(), + options.prepareVersion().getStr()); + } + } catch(const IllegalArgument& e) + { + fprintf(stderr, "Illegal argument: %s\n%s", + e.m_message.getStr(), + options.prepareVersion().getStr()); + return 99; + } + + return nErrors; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/idlcproduce.cxx b/idlc/source/idlcproduce.cxx new file mode 100644 index 000000000..2592fe0de --- /dev/null +++ b/idlc/source/idlcproduce.cxx @@ -0,0 +1,242 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <idlc.hxx> +#include <astmodule.hxx> +#include <rtl/strbuf.hxx> +#include <osl/file.hxx> +#include <osl/thread.h> +#include <o3tl/string_view.hxx> + +#if defined(_WIN32) +#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 ::osl; + +static std::list< OString > gaCreatedDirectories; + +static bool checkOutputPath(const OString& completeName) +{ + OString sysPathName = convertToAbsoluteSystemPath(completeName); + OStringBuffer buffer(sysPathName.getLength()+16); + + if ( sysPathName.indexOf( SEPARATOR ) == -1 ) + return true; + + sal_Int32 nIndex = 0; + std::string_view token(o3tl::getToken(sysPathName, 0, SEPARATOR, nIndex)); + if (o3tl::starts_with(token, "..") + || (token.size() >= 2 && token[1] == ':') + || o3tl::starts_with(token, ".")) + { + buffer.append(token); + buffer.append(SEPARATOR); + } + else + nIndex = 0; + + do + { + buffer.append(o3tl::getToken(sysPathName, 0, SEPARATOR, nIndex)); + + if ( !buffer.isEmpty() && nIndex != -1 ) + { +#if defined(SAL_UNX) + if (mkdir(buffer.getStr(), 0777) == -1) +#else + if (mkdir(buffer.getStr()) == -1) +#endif + { + if (errno == ENOENT) + { + fprintf(stderr, "%s: cannot create directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), buffer.getStr()); + return false; + } + } + else + { + gaCreatedDirectories.push_front(buffer.getStr()); + } + } + buffer.append(SEPARATOR); + } while( nIndex != -1 ); + return true; +} + +static bool cleanPath() +{ + for (auto const& createdDirectory : gaCreatedDirectories) + { +//#ifdef SAL_UNX +// if (rmdir((char*)createdDirectory.getStr(), 0777) == -1) +//#else + if (rmdir(createdDirectory.getStr()) == -1) +//#endif + { + fprintf(stderr, "%s: cannot remove directory '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), createdDirectory.getStr()); + return false; + } + } + gaCreatedDirectories.clear(); + return true; +} + +void removeIfExists(std::string_view pathname) +{ + osl::File::remove(OStringToOUString(pathname, RTL_TEXTENCODING_UTF8)); +} + +sal_Int32 +produceFile(const OString& regFileName, sPair_t const*const pDepFile) +{ + 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; + } + + OString depTmpName; + if (pDepFile) + { + depTmpName = pDepFile->first.replaceAt( + regFileName.getLength() -3, 3, "_idlc_"); + if ( !checkOutputPath(depTmpName) ) + { + fprintf(stderr, "%s: could not create path of dep file '%s'.\n", + pOptions->getProgramName().getStr(), pDepFile->first.getStr()); + return 1; + } + removeIfExists(depTmpName); + } + + removeIfExists(regTmpName); + OString urlRegTmpName = convertToFileUrl(regTmpName); + + Registry regFile; + if ( regFile.create(OStringToOUString(urlRegTmpName, RTL_TEXTENCODING_UTF8)) != RegError::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) != RegError::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(); + if (regFile.close() != RegError::NO_ERROR) + { + fprintf(stderr, "%s: could not close registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + } + regFile.destroy(OStringToOUString(regFileName, RTL_TEXTENCODING_UTF8)); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + rootKey.releaseKey(); + if ( regFile.close() != RegError::NO_ERROR ) + { + fprintf(stderr, "%s: could not close registry file '%s'\n", + pOptions->getProgramName().getStr(), regFileName.getStr()); + removeIfExists(regTmpName); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + + if (pDepFile && !idlc()->dumpDeps(depTmpName, pDepFile->second)) + { + fprintf(stderr, "%s: could not write dep file '%s'\n", + pOptions->getProgramName().getStr(), pDepFile->first.getStr()); + removeIfExists(depTmpName); + removeIfExists(pDepFile->first); + 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); + + if (pDepFile) + { + removeIfExists(pDepFile->first); + if ( File::move(OStringToOUString(depTmpName, osl_getThreadTextEncoding()), + OStringToOUString(pDepFile->first, osl_getThreadTextEncoding())) != FileBase::E_None ) { + fprintf(stderr, "%s: cannot rename dep file '%s' to '%s'\n", + idlc()->getOptions()->getProgramName().getStr(), + depTmpName.getStr(), pDepFile->first.getStr()); + removeIfExists(depTmpName); + removeIfExists(pDepFile->first); + removeIfExists(regFileName); + cleanPath(); + return 1; + } + removeIfExists(depTmpName); + } + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/options.cxx b/idlc/source/options.cxx new file mode 100644 index 000000000..0fd06cc9f --- /dev/null +++ b/idlc/source/options.cxx @@ -0,0 +1,424 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <string_view> + +#include <options.hxx> + +#include <osl/diagnose.h> +#include <rtl/string.hxx> +#include <rtl/strbuf.hxx> + +#include <rtl/ustring.hxx> +#include <osl/file.hxx> +#include <o3tl/char16_t2wchar_t.hxx> +#include <o3tl/string_view.hxx> + +#ifdef _WIN32 +# if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> +#endif + +#include <stdio.h> +#include <string.h> + + +Options::Options(char const * progname) + : m_program(progname), m_stdin(false), m_verbose(false), m_quiet(false) +{ +} + +Options::~Options() +{ +} + +// static +bool Options::checkArgument (std::vector< std::string > & rArgs, char const * arg, size_t len) +{ + bool result = ((arg != nullptr) && (len > 0)); + OSL_PRECOND(result, "idlc::Options::checkArgument(): invalid arguments"); + if (!result) + return false; + + switch(arg[0]) + { + case '@': + result = len > 1; + if (result) + { + // "@<cmdfile>" + result = Options::checkCommandFile (rArgs, &(arg[1])); + } + break; + case '-': + result = len > 1; + if (result) + { + // "-<option>" + switch (arg[1]) + { + case 'O': + case 'M': + case 'I': + case 'D': + { + // "-<option>[<param>] + std::string option(&(arg[0]), 2); + rArgs.push_back(option); + if (len > 2) + { + // "-<option><param>" + std::string param(&(arg[2]), len - 2); + rArgs.push_back(param); + } + break; + } + default: + // "-<option>" ([long] option, w/o param) + rArgs.emplace_back(arg, len); + break; + } + } + break; + default: + // "<param>" + rArgs.emplace_back(arg, len); + break; + } + return result; +} + +// static +bool Options::checkCommandFile (std::vector< std::string > & rArgs, char const * filename) +{ + FILE * fp = fopen(filename, "r"); + if (fp == nullptr) + { + fprintf(stderr, "ERROR: can't open command file \"%s\"\n", filename); + return false; + } + + std::string buffer; + buffer.reserve(256); + + bool quoted = false; + int c = EOF; + while ((c = fgetc(fp)) != EOF) + { + switch(c) + { + case '\"': + quoted = !quoted; + break; + case ' ': + case '\t': + case '\r': + case '\n': + if (!quoted) + { + if (!buffer.empty()) + { + // append current argument. + if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size())) + { + (void) fclose(fp); + return false; + } + buffer.clear(); + } + break; + } + [[fallthrough]]; + default: + buffer.push_back(sal::static_int_cast<char>(c)); + break; + } + } + if (!buffer.empty()) + { + // append unterminated argument. + if (!Options::checkArgument(rArgs, buffer.c_str(), buffer.size())) + { + (void) fclose(fp); + return false; + } + buffer.clear(); + } + return (fclose(fp) == 0); +} + +bool Options::badOption(char const * reason, std::string const & rArg) +{ + if (reason != nullptr) + { + OString message = OString::Concat(reason) + " option '" + rArg.c_str() + "'"; + throw IllegalArgument(message); + } + return false; +} + +bool Options::setOption(char const * option, std::string const & rArg) +{ + bool result = (0 == strcmp(option, rArg.c_str())); + if (result) + m_options[rArg.c_str()] = OString(rArg.c_str(), rArg.size()); + return result; +} + +#ifdef _WIN32 +/* Helper function to convert windows paths including spaces, brackets etc. into + a windows short Url. The ucpp preprocessor has problems with such paths and returns + with error. +*/ +static OString convertIncPathtoShortWindowsPath(const OString& incPath) { + OUString path = OStringToOUString(incPath, RTL_TEXTENCODING_UTF8); + + std::vector<sal_Unicode> vec(path.getLength() + 1); + //GetShortPathNameW only works if the file can be found! + const DWORD len = GetShortPathNameW( + o3tl::toW(path.getStr()), o3tl::toW(vec.data()), path.getLength() + 1); + + if (len > 0) + { + OUString ret(vec.data(), len); + return OUStringToOString(ret, RTL_TEXTENCODING_UTF8); + } + + return incPath; +} +#endif + +bool Options::initOptions(std::vector< std::string > & rArgs) +{ + std::vector< std::string >::const_iterator first = rArgs.begin(), last = rArgs.end(); + for (; first != last; ++first) + { + if ((*first)[0] != '-') + { + OString filename((*first).c_str(), (*first).size()); + OString tmp(filename.toAsciiLowerCase()); + if (tmp.lastIndexOf(".idl") != (tmp.getLength() - 4)) + { + throw IllegalArgument("'" + filename + "' is not a valid input file, only '*.idl' files will be accepted"); + } + m_inputFiles.push_back(filename); + continue; + } + + std::string const option(*first); + switch((*first)[1]) + { + case 'O': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + m_options["-O"] = param; + break; + } + case 'M': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + m_options["-M"] = param; + break; + } + case 'I': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param((*first).c_str(), (*first).size()); + { + // quote param token(s). + OStringBuffer buffer; + sal_Int32 k = 0; + do + { + if (!buffer.isEmpty()) + buffer.append(' '); +// buffer.append("-I\""); +#ifdef _WIN32 + OString incpath = convertIncPathtoShortWindowsPath(param.getToken(0, ';', k)); +#else + std::string_view incpath = o3tl::getToken(param, 0, ';', k); +#endif + buffer.append(incpath); +// buffer.append("\""); + } while (k != -1); + param = buffer.makeStringAndClear(); + } + if (m_options.count("-I") > 0) + { + // append param. + param = m_options["-I"] + " " + param; + } + m_options["-I"] = param; + break; + } + case 'D': + { + if ((++first == last) || ((*first)[0] == '-')) + { + return badOption("invalid", option); + } + OString param = OString::Concat("-D") + std::string_view((*first).c_str(), (*first).size()); + if (m_options.count("-D") > 0) + { + param = m_options["-D"] + " " + param; + } + m_options["-D"] = param; + break; + } + case 'C': + { + if (!setOption("-C", option)) + { + return badOption("invalid", option); + } + break; + } + case 'c': + { + if (!setOption("-cid", option)) + { + return badOption("invalid", option); + } + break; + } + case 'q': + { + if (!setOption("-quiet", option)) + { + return badOption("invalid", option); + } + m_quiet = true; + break; + } + case 'v': + { + if (!setOption("-verbose", option)) + { + return badOption("invalid", option); + } + m_verbose = true; + break; + } + case 'w': + { + if (!(setOption("-w", option) || setOption("-we", option))) + { + return badOption("invalid", option); + } + break; + } + case 'h': + case '?': + { + if (!(setOption("-h", option) || setOption("-?", option))) + { + return badOption("invalid", option); + } + { + (void) fprintf(stdout, "%s", prepareHelp().getStr()); + return false; + } + // break; // Unreachable + } + case 's': + { + if (!setOption("-stdin", option)) + { + return badOption("invalid", option); + } + m_stdin = true; + break; + } + default: + return badOption("unknown", option); + } + } + return true; +} + +OString Options::prepareHelp() const +{ + OString help = "\nusing: " + + m_program + " [-options] <file_1> ... <file_n> | @<filename> | -stdin\n" + " <file_n> = file_n specifies one or more idl files.\n" + " Only files with the extension '.idl' are valid.\n" + " @<filename> = filename specifies the name of a command file.\n" + " -stdin = read idl file from standard input.\n" + " Options:\n" + " -O<path> = path specifies the output directory.\n" + " The generated output is a registry file with\n" + " the same name as the idl input file (or 'stdin'\n" + " for -stdin).\n" + " -M<path> = path specifies the output directory for deps.\n" + " Generate GNU make dependency files with the\n" + " same name as the idl input file.\n" + " -I<path> = path specifies a directory where include\n" + " files will be searched by the preprocessor.\n" + " Multiple directories can be combined with ';'.\n" + " -D<name> = name defines a macro for the preprocessor.\n" + " -C = generate complete type information, including\n" + " documentation.\n" + " -cid = check if identifiers fulfill the UNO naming\n" + " requirements.\n" + " -quiet = no output.\n" + " -verbose = verbose output.\n" + " -w = display warning messages.\n" + " -we = treat warnings as errors.\n" + " -h|-? = print this help message and exit.\n\n" + + prepareVersion(); + + return help; +} + +OString Options::prepareVersion() const +{ + return m_program + " Version 1.1\n\n"; +} + + +bool Options::isValid(const OString& option) const +{ + return (m_options.count(option) > 0); +} + +const OString& Options::getOption(const OString& option) +{ + if (!isValid(option)) + { + throw IllegalArgument("Option is not valid or currently not set."); + } + return m_options[option]; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/parser.y b/idlc/source/parser.y new file mode 100644 index 000000000..29654c32b --- /dev/null +++ b/idlc/source/parser.y @@ -0,0 +1,2737 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/* + * parser.yy - BISON grammar for IDLC 1.0 + */ + +%{ +#include <string.h> + +#include <idlc.hxx> +#include <errorhandler.hxx> +#include <fehelper.hxx> +#include <astexpression.hxx> +#include <astconstants.hxx> +#include <astconstant.hxx> +#include <astbasetype.hxx> +#include <asttypedef.hxx> +#include <astexception.hxx> +#include <astmember.hxx> +#include <astenum.hxx> +#include <astsequence.hxx> +#include <astattribute.hxx> +#include <astoperation.hxx> +#include <astparameter.hxx> +#include <astinterfacemember.hxx> +#include <astservicemember.hxx> +#include <astobserves.hxx> +#include <astneeds.hxx> + +#include <aststructinstance.hxx> + +#include "attributeexceptions.hxx" + +#include <rtl/string.hxx> +#include <osl/diagnose.h> + +#include <algorithm> +#include <vector> + + +#define YYDEBUG 1 +#define YYERROR_VERBOSE 1 + +extern int yylex(void); +static void yyerror(char const *); + +static void checkIdentifier(OString const * 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) { + OString msg = "mismatched identifier '" + *id + "'"; + ErrorHandler::syntaxError(idlc()->getParseState(), + idlc()->getLineNumber(), + msg.getStr()); + } + else + ErrorHandler::warning0(WarningCode::WrongNamingConvention, id->getStr()); + } +} + +static void reportDoubleMemberDeclarations( + AstInterface::DoubleMemberDeclarations const & doubleMembers) +{ + for (auto const& doubleMember : doubleMembers) + { + ErrorHandler::error2(ErrorCode::DoubleMember, doubleMember.first, doubleMember.second); + } +} + +static void addInheritedInterface( + AstInterface * ifc, OString const & name, bool optional, + OUString const & documentation) +{ + AstDeclaration * decl = ifc->lookupByName(name); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (resolved != nullptr && resolved->getNodeType() == NT_interface) { + if (ErrorHandler::checkPublished(decl)) { + if (!static_cast< AstInterface const * >(resolved)->isDefined()) { + ErrorHandler::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 (auto const& elem : doubleDecls.interfaces) + { + ErrorHandler::error1( + ErrorCode::DoubleInheritance, elem); + } + reportDoubleMemberDeclarations(doubleDecls.members); + } + } + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, name, scopeAsDecl(ifc)); + } +} + +static AstDeclaration const * createNamedType( + OString const * scopedName, DeclList const * typeArgs) +{ + AstDeclaration * decl = idlc()->scopes()->topNonNull()->lookupByName( + *scopedName); + AstDeclaration const * resolved = resolveTypedefs(decl); + if (decl == nullptr) { + ErrorHandler::lookupError(*scopedName); + } else if (!ErrorHandler::checkPublished(decl)) { + decl = nullptr; + } else if (resolved->getNodeType() == NT_struct) { + if (static_cast< AstStruct const * >(resolved)->getTypeParameterCount() + != (typeArgs == nullptr ? 0 : typeArgs->size())) + { + ErrorHandler::error0(ErrorCode::WrongNumberOfTypeArguments); + decl = nullptr; + } else if (typeArgs != nullptr) { + 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 != nullptr) { + ErrorHandler::error0(ErrorCode::WrongNumberOfTypeArguments); + decl = nullptr; + } + } else { + ErrorHandler::noTypeError(decl); + decl = nullptr; + } + delete scopedName; + delete typeArgs; + return decl; +} + +static bool includes(AstDeclaration const * type1, AstDeclaration const * type2) { + OSL_ASSERT(type2 != nullptr); + if (type1 != nullptr) { + 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 _MSC_VER +#pragma warning(disable: 4702) // unreachable code +#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 */ + FeDeclarator* fdval; /* declarator value */ + FeDeclList* dlval; /* declarator list value */ + FeInheritanceHeader* ihval; /* inheritance header value */ + OString* sval; /* OString value */ + std::vector< OString > * svals; + char* strval; /* char* value */ + 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 */ + std::list< OString >* slval; /* StringList 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_CONST +%token IDL_CONSTANTS +%token IDL_CONSTRAINED +%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_REMOVABLE +%token IDL_SERVICE +%token IDL_SEQUENCE +%token IDL_SINGLETON +%token IDL_STRUCT +%token IDL_TYPEDEF +%token IDL_TRANSIENT + +%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_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 +%type <dclval> exception_name +%type <cdclval> constructed_type_spec enum_type op_type_spec +%type <cdclval> sequence_type_spec simple_type_spec struct_type +%type <cdclval> type_spec +%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 + +%type <fdval> declarator +%type <dlval> declarators at_least_one_declarator + +%type <ihval> exception_header structure_header interfaceheader + +%type <ulval> flag_header opt_attrflags opt_attrflag +%type <ulval> direction service_interface_header service_service_header + +%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); + } + | 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 = nullptr; + + if ( pScope ) + { + pModule = new AstModule(*$3, pScope); + if( AstDeclaration* 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 = static_cast<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 = nullptr; + AstDeclaration* pDecl = nullptr; + + /* + * Make a new forward interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pForward = new AstInterface(*$1, nullptr, pScope); + + pDecl = pScope->lookupByName(pForward->getScopedName()); + if ( pDecl ) + { + if ( (pDecl != pForward) && + (pDecl->getNodeType() == NT_interface) ) + { + delete pForward; + } else + { + ErrorHandler::error2(ErrorCode::RedefScope, 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 = nullptr; + AstInterface* pForward = nullptr; + + /* + * Make a new interface node and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + pInterface = new AstInterface( + *$1->getName(), + static_cast< AstInterface const * >(resolveTypedefs($1->getInherits())), pScope); + if ( AstDeclaration* pDecl = pScope->lookupByName(pInterface->getScopedName()) ) + { + /* + * See if we're defining a forward declared interface. + */ + if (pDecl->getNodeType() == NT_interface) + { + pForward = static_cast<AstInterface*>(pDecl); + if ( !pForward->isDefined() ) + { + /* + * Check if redefining in same scope + */ + if ( pForward->getScope() != pScope ) + { + if ( pForward->getScopedName() != pInterface->getScopedName() ) + { + ErrorHandler::error3(ErrorCode::ScopeConflict, + pInterface, pForward, scopeAsDecl(pScope)); + } + } + else if ( !pInterface->isPublished() + && pForward->isPublished() ) + { + ErrorHandler::error0(ErrorCode::PublishedForward); + } + /* + * 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, "::com::sun::star::uno::XInterface", false, + 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, nullptr); + delete $2; + } + ; + +inheritance_spec : + ':' + { + idlc()->setParseState(PS_InheritColonSeen); + } + scoped_name + { + $$ = $3; + } + | /* EMPTY */ + { + $$ = nullptr; + } + ; + +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); + } + declarator + { + idlc()->setParseState(PS_AttrCompleted); + if (($1 & ~(AF_BOUND | AF_READONLY)) != AF_ATTRIBUTE) { + ErrorHandler::flagError(ErrorCode::BadAttributeFlags, $1); + } + AstInterface * scope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstAttribute * attr = new AstAttribute( + $1, FeDeclarator::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 ) + ErrorHandler::flagError(ErrorCode::DefinedAttributeFlag, $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_MayBeAmbiguousSeen); + $$ = AF_MAYBEAMBIGUOUS; + } + | IDL_MAYBEDEFAULT + { + idlc()->setParseState(PS_MayBeDefaultSeen); + $$ = AF_MAYBEDEFAULT; + } + | IDL_REMOVABLE + { + idlc()->setParseState(PS_RemoveableSeen); + $$ = AF_REMOVABLE; + } + | error ']' + { + yyerror("unknown property|attribute flag"); + yyerrok; + } + ; + +opt_attribute_block: + '{' attribute_block_rest { $$ = $2; } + | /* empty */ + { + $$.get.documentation = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +attribute_block_rest: + opt_attribute_raises '}' + | error '}' + { + yyerror("bad attribute raises block"); + yyerrok; + $$.get.documentation = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +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 = nullptr; + $$.get.exceptions = nullptr; + $$.set.documentation = nullptr; + $$.set.exceptions = nullptr; + } + ; + +opt_attribute_get_raises: + attribute_get_raises + | /* empty */ { $$.documentation = nullptr; $$.exceptions = nullptr; } + ; + +attribute_get_raises: + IDL_GET raises ';' + { + $$.documentation = new OUString( + OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $2; + } + ; + +opt_attribute_set_raises: + attribute_set_raises + | /* empty */ { $$.documentation = nullptr; $$.exceptions = nullptr; } + ; + +attribute_set_raises: + IDL_SET + { + if (static_cast< AstAttribute * >(idlc()->scopes()->top())-> + isReadonly()) + { + ErrorHandler::error0(ErrorCode::ReadOnlyAttributeSetExceptions); + } + } + raises ';' + { + $$.documentation = new OUString( + OStringToOUString( + idlc()->getDocumentation(), RTL_TEXTENCODING_UTF8)); + $$.exceptions = $3; + } + ; + +operation : + op_type_spec + { + idlc()->setParseState(PS_OpTypeSeen); + } + identifier + { + idlc()->setParseState(PS_OpIDSeen); + checkIdentifier($3); + + AstInterface * pScope = static_cast< AstInterface * >( + idlc()->scopes()->top()); + AstOperation* pOp = nullptr; + + /* + * Create a node representing an operation on an interface + * and add it to its enclosing scope + */ + if ( pScope && $1 ) + { + AstType const *pType = static_cast<AstType const *>($1); + if ( !pType || (pType->getNodeType() == NT_exception) ) + { + // type ERROR + } else + { + pOp = new AstOperation(pType, *$3, pScope); + + AstInterface::DoubleMemberDeclarations doubleMembers( + pScope->checkMemberClashes(pOp)); + if (doubleMembers.empty()) { + pScope->addMember(pOp); + } else { + reportDoubleMemberDeclarations(doubleMembers); + } + } + } + delete $3; + /* + * 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 = nullptr; + /* + * Add exceptions and context to the operation + */ + if ( pScope && pScope->getScopeNodeType() == NT_operation) + { + pOp = static_cast<AstOperation*>(pScope); + + if ( pOp ) + pOp->setExceptions($11); + } + delete $11; + /* + * Done with this operation. Pop its scope from the scopes stack + */ + idlc()->scopes()->pop(); + } + ; + +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 = nullptr; + + /* + * 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 = FeDeclarator::compose($5); + if ( pType ) + { + if (pScope->isConstructor() && $2 != DIR_IN) { + ErrorHandler::error0(ErrorCode::ConstructorParameterNotIn); + } + if (pScope->isVariadic()) { + ErrorHandler::error0(ErrorCode::RestParameterNotLast); + } + if ($7) { + AstDeclaration const * type = resolveTypedefs(pType); + if (type->getNodeType() != NT_predefined + || (static_cast< AstBaseType const * >(type)-> + getExprType() != ET_any)) + { + ErrorHandler::error0(ErrorCode::RestParameterNotAny); + } + if (pScope->isConstructor()) { + if (pScope->getIteratorBegin() + != pScope->getIteratorEnd()) + { + ErrorHandler::error0( + ErrorCode::ConstructorRestParameterNotFirst); + } + } else { + ErrorHandler::error0(ErrorCode::MethodHasRestParameter); + } + } + + 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 */ + { + $$ = nullptr; + } + ; + +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 == nullptr) { + ErrorHandler::lookupError(*$1); + } else if (!ErrorHandler::checkPublished(decl)) { + decl = nullptr; + } else if (decl->getNodeType() != NT_exception) { + ErrorHandler::error1(ErrorCode::IllegalRaises, decl); + decl = nullptr; + } + 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()) { + ErrorHandler::error0(ErrorCode::MixedInheritance); + } else { + addInheritedInterface( + ifc, *$4, $1, + 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 : + 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 = nullptr; + + if ( $9 && pScope ) + { + if ( !$9->coerce($3) ) + { + ErrorHandler::coercionError($9, $3); + } else + { + pConstant = new AstConstant($3, $9, *$5, pScope); + pScope->addDeclaration(pConstant); + } + } + delete $5; + + idlc()->setParseState(PS_ConstantDeclSeen); + } + ';' {}; + ; + +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 = nullptr; + + if ( pScope ) + { + pConstants = new AstConstants(*$3, pScope); + if( AstDeclaration* pExists = pScope->lookupForAdd(pConstants) ) + { + pExists->setInMainfile(idlc()->isInMainFile()); + delete(pConstants); + pConstants = static_cast<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(ExprComb::Or, $1, $3); + } + ; + +xor_expr : + and_expr + | xor_expr '^' and_expr + { + $$ = new AstExpression(ExprComb::Xor, $1, $3); + } + ; + +and_expr : + shift_expr + | and_expr '&' shift_expr + { + $$ = new AstExpression(ExprComb::And, $1, $3); + } + ; + +shift_expr : + add_expr + | shift_expr IDL_LEFTSHIFT add_expr + { + $$ = new AstExpression(ExprComb::Left, $1, $3); + } + | shift_expr IDL_RIGHTSHIFT add_expr + { + $$ = new AstExpression(ExprComb::Right, $1, $3); + } + ; + +add_expr : + mult_expr + | add_expr '+' mult_expr + { + $$ = new AstExpression(ExprComb::Add, $1, $3); + } + | add_expr '-' mult_expr + { + $$ = new AstExpression(ExprComb::Minus, $1, $3); + } + ; + +mult_expr : + unary_expr + | mult_expr '*' unary_expr + { + $$ = new AstExpression(ExprComb::Mul, $1, $3); + } + | mult_expr '/' unary_expr + { + $$ = new AstExpression(ExprComb::Div, $1, $3); + } + | mult_expr '%' unary_expr + { + $$ = new AstExpression(ExprComb::Mod, $1, $3); + } + ; + +unary_expr : + primary_expr + | '+' primary_expr + { + $$ = new AstExpression(ExprComb::UPlus, $2, nullptr); + } + | '-' primary_expr + { + $$ = new AstExpression(ExprComb::UMinus, $2, nullptr); + } + | '~' 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); + } + ; + +const_type : + integer_type + | byte_type + | boolean_type + | floating_pt_type + | scoped_name + { + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration const * type = nullptr; + + /* + * If the constant's type is a scoped name, it must resolve + * to a scalar constant type + */ + if ( pScope ) { + type = pScope->lookupByName(*$1); + if (type) { + if (!ErrorHandler::checkPublished(type)) + { + type = nullptr; + $$ = ET_none; + } + else + { + type = resolveTypedefs(type); + if (type->getNodeType() == NT_predefined) + { + $$ = static_cast< AstBaseType const * >(type)-> + getExprType(); + } else + $$ = ET_any; + } + } 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, nullptr); + delete $5; + } + ; + +exception_dcl : + exception_header + { + idlc()->setParseState(PS_ExceptHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstException* pExcept = nullptr; + + 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 = nullptr; + FeDeclList* pList = $4; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + if ( ($1 & AF_ATTRIBUTE) == AF_ATTRIBUTE ) + ErrorHandler::flagError(ErrorCode::WrongAttributeKeyword, AF_ATTRIBUTE); + + if ( ($1 & AF_PROPERTY) != AF_PROPERTY ) + ErrorHandler::flagError(ErrorCode::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 = FeDeclarator::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 = nullptr; + AstInterfaceMember* pIMember = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + 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 ( ErrorHandler::checkPublished(pDecl, bOptional) ) + { + pIMember = new AstInterfaceMember( + $1, static_cast<AstInterface*>(pDecl), elem, pScope); + pScope->addDeclaration(pIMember); + } + } else + { + ErrorHandler::lookupError(ErrorCode::InterfaceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + delete $2; + } + | service_service_header + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstServiceMember* pSMember = nullptr; + + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + if ( static_cast< AstService * >(pDecl)->isSingleInterfaceBasedService() || (pScope->getScopeNodeType() == NT_singleton && pScope->nMembers() > 0) ) + ErrorHandler::error0(ErrorCode::IllegalAdd); + else if ( ErrorHandler::checkPublished(pDecl) ) + { + pSMember = new AstServiceMember( + $1, static_cast<AstService*>(pDecl), elem, pScope); + pScope->addDeclaration(pSMember); + } + } else + { + ErrorHandler::lookupError(ErrorCode::ServiceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + delete $2; + } + | IDL_OBSERVES + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstObserves* pObserves = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_interface) ) + { + pObserves = new AstObserves(static_cast<AstInterface*>(pDecl), elem, pScope); + pScope->addDeclaration(pObserves); + } else + { + ErrorHandler::lookupError(ErrorCode::InterfaceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + delete $2; + } + | IDL_NEEDS + at_least_one_scoped_name + ';' + { + idlc()->setParseState(PS_ServiceMemberSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstDeclaration* pDecl = nullptr; + AstNeeds* pNeeds = nullptr; + + if ( pScope->getScopeNodeType() == NT_singleton ) + { + ErrorHandler::error0(ErrorCode::IllegalAdd); + } else + { + /* + * Create a node representing a class member. + * Store it in the enclosing scope + */ + if ( pScope && $2 ) + { + for (auto const& elem : *($2)) + { + pDecl = pScope->lookupByName(elem); + if ( pDecl && (pDecl->getNodeType() == NT_service) ) + { + pNeeds = new AstNeeds(static_cast<AstService*>(pDecl), elem, pScope); + pScope->addDeclaration(pNeeds); + } else + { + ErrorHandler::lookupError(ErrorCode::ServiceMemberLookup, elem, scopeAsDecl(pScope)); + } + } + } + } + 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) ) + ErrorHandler::flagError(ErrorCode::ExpectedOptional, $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) ) + ErrorHandler::flagError(ErrorCode::ExpectedOptional, $1); + $$ = $1; + } + ; + +service_dcl : + IDL_SERVICE + { + idlc()->setParseState(PS_ServiceSeen); + } + identifier + { + idlc()->setParseState(PS_ServiceIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = nullptr; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != nullptr) + { + 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 != nullptr + && resolveTypedefs(decl)->getNodeType() == NT_interface) + { + if (ErrorHandler::checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, *$2, scopeAsDecl(scope)); + } + delete $2; + } + opt_service_body + { + AstService * s = static_cast< AstService * >(idlc()->scopes()->top()); + if (s != nullptr) { + s->setSingleInterfaceBasedService(); + 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(nullptr, *$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()) + { + ErrorHandler::error0(ErrorCode::SimilarConstructors); + } + } + ';' + ; + +singleton_dcl : + IDL_SINGLETON + { + idlc()->setParseState(PS_SingletonSeen); + } + identifier + { + idlc()->setParseState(PS_SingletonIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstService* pService = nullptr; + + /* + * Make a new service and add it to the enclosing scope + */ + if (pScope != nullptr) + { + pService = new AstService(NT_singleton, *$3, pScope); + pScope->addDeclaration(pService); + } + delete $3; + /* + * Push it on the stack + */ + idlc()->scopes()->push(pService); + } + singleton_dfn + { + /* this singleton 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 != nullptr + && resolveTypedefs(decl)->getNodeType() == NT_interface) + { + if (ErrorHandler::checkPublished(decl)) { + idlc()->scopes()->top()->addDeclaration(decl); + } + } else { + ErrorHandler::lookupError( + ErrorCode::InterfaceMemberLookup, *$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 {} + | enum_type {} + ; + +type_declarator : + type_spec + { + idlc()->setParseState(PS_TypeSpecSeen); + if ($1 != nullptr && $1->getNodeType() == NT_instantiated_struct) { + ErrorHandler::error0(ErrorCode::InstantiatedStructTypeTypedef); + } + } + at_least_one_declarator + { + idlc()->setParseState(PS_DeclaratorsSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstTypeDef* pTypeDef = nullptr; + FeDeclList* pList = $3; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + /* + * 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 = FeDeclarator::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 */ + { + $$ = nullptr; + } + ; + +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 == nullptr || scope->getScopeNodeType() != NT_struct + || (scopeAsDecl(scope)->getScopedName() + != "com::sun::star::uno::Uik")) + { + checkIdentifier($1); + } + + $$ = new FeDeclarator(*$1); + delete $1; + } + ; + +at_least_one_scoped_name : + scoped_name scoped_names + { + if ($2) + { + $2->push_front(*$1); + $$ = $2; + } else + { + std::list< OString >* pScopedNames = new std::list< OString >; + // coverity[copy_paste_error : FALSE] - this is not a cut and paste + pScopedNames->push_back(*$1); + $$ = pScopedNames; + } + delete $1; + } + ; + +scoped_names : + scoped_names + ',' + { + idlc()->setParseState(PS_SNListCommaSeen); + } + scoped_name + { + idlc()->setParseState(PS_ScopedNameSeen); + if ($1) + { + $1->push_back(*$4); + $$ = $1; + } else + { + std::list< OString >* pNames = new std::list< OString >; + pNames->push_back(*$4); + $$ = pNames; + } + delete $4; + } + | /* EMPTY */ + { + $$ = nullptr; + } + ; + +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 += "::"; + *$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); + } + | sequence_type_spec + ; + +opt_type_args: + '<' type_args '>' { $$ = $2; } + | /* empty */ { $$ = nullptr; } + ; + +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 != nullptr && static_cast< AstType const * >($1)->isUnsigned()) { + ErrorHandler::error0(ErrorCode::UnsignedTypeArgument); + } + $$ = $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; + } + ; + +constructed_type_spec : + struct_type + | enum_type + ; + +sequence_type_spec : + IDL_SEQUENCE + { + idlc()->setParseState(PS_SequenceSeen); + /* + * Push a sequence marker on scopes stack + */ + idlc()->scopes()->push(nullptr); + } + '<' + { + 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() == nullptr) + idlc()->scopes()->pop(); + /* + * Create a node representing a sequence + */ + AstScope* pScope = idlc()->scopes()->bottom(); + AstDeclaration* pDecl = nullptr; + AstDeclaration* pSeq = nullptr; + + if ( $5 ) + { + AstType const *pType = static_cast<AstType const *>($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; + $$ = nullptr; + } + ; + +struct_type : + structure_header + { + idlc()->setParseState(PS_StructHeaderSeen); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstStruct* pStruct = nullptr; + + if ( pScope ) + { + AstStruct const* pBase= static_cast< AstStruct const* >(resolveTypedefs($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 != nullptr && $6 != nullptr) { + ErrorHandler::error0(ErrorCode::StructTypeTemplateWithBase); + } + + $$ = new FeInheritanceHeader(NT_struct, $3, $6, $5); + delete $5; + delete $6; + } + ; + +opt_type_params: + '<' type_params '>' { $$ = $2; } + | /* empty */ { $$ = nullptr; } + ; + +type_params: + identifier + { + $$ = new std::vector< OString >; + $$->push_back(*$1); + delete $1; + } + | type_params ',' identifier + { + if (std::find($1->begin(), $1->end(), *$3) != $1->end()) { + ErrorHandler::error0(ErrorCode::IdenticalTypeParameters); + } + $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 = nullptr; + FeDeclList* pList = $3; + FeDeclarator* pDecl = nullptr; + AstType const * pType = nullptr; + + // !!! 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 = FeDeclarator::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 = nullptr; + AstStruct * scope = static_cast< AstStruct * >(idlc()->scopes()->top()); + if (scope != nullptr && $2 == nullptr) { + decl = scope->findTypeParameter(*$1); + } + if (decl != nullptr) { + delete $1; + delete $2; + } else { + decl = createNamedType($1, $2); + if (scope != nullptr && includes(decl, scopeAsDecl(scope))) { + ErrorHandler::error1( + ErrorCode::RecursiveType, scopeAsDecl(scope)); + decl = nullptr; + } + } + $$ = decl; + } + ; + +enum_type : + IDL_ENUM + { + idlc()->setParseState(PS_EnumSeen); + } + identifier + { + idlc()->setParseState(PS_EnumIDSeen); + checkIdentifier($3); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = nullptr; + + /* + * Create a node representing an enum and add it to its + * enclosing scope + */ + if (pScope != nullptr) + { + 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() == nullptr) + $$ = nullptr; + else + { + $$ = static_cast<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 = nullptr; + AstConstant* pEnumVal = nullptr; + + if ( pScope && pScope->getScopeNodeType() == NT_enum) + { + pEnum = static_cast<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()) ) + ErrorHandler::error1(ErrorCode::Eval, pEnum); + + pScope->addDeclaration(pEnumVal); + } + delete $1; + } + | identifier + '=' + const_expr + { + checkIdentifier($1); + + AstScope* pScope = idlc()->scopes()->topNonNull(); + AstEnum* pEnum = nullptr; + AstConstant* pEnumVal = nullptr; + + if ( $3 && pScope && pScope->getScopeNodeType() == NT_enum) + { + $3->evaluate(); + if ( $3->coerce(ET_long) ) + { + pEnum = static_cast<AstEnum*>(pScope); + if (pEnum) + { + pEnumVal = new AstConstant(ET_long , NT_enum_val, + $3, *$1, pScope); + } + if ( pEnum->checkValue(pEnumVal->getConstValue()) ) + ErrorHandler::error1(ErrorCode::Eval, pEnum); + + pScope->addDeclaration(pEnumVal); + } else + { + ErrorHandler::coercionError($3, ET_long); + delete $3; + } + } + delete $1; + } + ; + +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) +{ + ErrorHandler::syntaxError(idlc()->getParseState(), idlc()->getLineNumber(), errmsg); + idlc()->setParseState(PS_NoState); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/source/scanner.l b/idlc/source/scanner.l new file mode 100644 index 000000000..aaf74a564 --- /dev/null +++ b/idlc/source/scanner.l @@ -0,0 +1,526 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +%option yylineno + +%{ +/* + * scanner.ll - Lexical scanner for IDLC 1.0 + */ + +#include <sal/config.h> + +#include <stdlib.h> +#include <string.h> + +#include <o3tl/safeint.hxx> +#include <o3tl/string_view.hxx> +#include <rtl/character.hxx> + +#if defined _MSC_VER +#pragma warning ( push ) +// Silence warnings about redefinition of INT8_MIN etc in stdint.h +// The flex-generated workdir/LexTarget/idlc/source/scanner.cxx defines them prior to these includes +#pragma warning ( disable : 4005 ) +#endif +#include <idlc.hxx> +#if defined _MSC_VER +#pragma warning ( pop ) +#endif +#include <errorhandler.hxx> +#include <fehelper.hxx> + +#include "attributeexceptions.hxx" + + +class AstExpression; +class AstMember; + +#include <parser.hxx> + +/* handle locations */ +static int yycolumn = 1; + +#define YY_USER_ACTION idlc()->setOffset(yycolumn, yycolumn+yyleng-1); \ + yycolumn += yyleng; + +static sal_Int32 beginLine = 0; +static 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) { + ErrorHandler::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 { + ErrorHandler::syntaxError( + PS_NoState, idlc()->getLineNumber(), + "negative integral constant too large"); + *sval = 0; + } + return IDL_INTEGER_LITERAL; + } else if (val <= o3tl::make_unsigned(SAL_MAX_INT64)) { + *sval = static_cast< sal_Int64 >(val); + return IDL_INTEGER_LITERAL; + } else { + *uval = val; + return IDL_INTEGER_ULITERAL; + } +} + +static double asciiToFloat(const char *s) +{ + double d = 0.0; + double e, k; + sal_Int32 neg = 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 == '-') + { + 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--) + ; + d /= k; + } + } + } + if (neg) d *= -1.0; + return d; +} + +static void idlParsePragma(char* pPragma) +{ + OString pragma(pPragma); + sal_Int32 index = pragma.indexOf("include"); + char* begin = pPragma + index + 8; + char* offset = begin; + while (*offset != ',') offset++; + //OString include = pragma.copy(index + 8, offset - begin); + //unused// idlc()->insertInclude(pragma.copy(index + 8, (sal_Int32)(offset - begin))); +} + +static void parseLineAndFile(char* pBuf) +{ + char *r = pBuf; + char *h; + bool bIsInMain = false; + + /* Skip initial '#' */ + if (*r != '#') + return; + + /* Find line number */ + for (r++; *r == ' ' || *r == '\t' || rtl::isAsciiAlpha(static_cast<unsigned char>(*r)); r++) ; + h = r; + for (; *r != '\0' && *r != ' ' && *r != '\t'; r++) ; + *r++ = 0; + idlc()->setLineNumber(sal_uInt32(atol(h))); + yylineno = 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("standard input"); + else + idlc()->setFileName(OString(h)); + + bIsInMain = idlc()->getFileName() == idlc()->getRealFileName(); + idlc()->setInMainfile(bIsInMain); +} + +// Suppress any warnings from generated code: +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-label" +#elif defined _MSC_VER +/**/ +#ifdef yywrap +#undef yywrap +#define yywrap() 1 +#endif +/**/ +#endif +#define YY_NO_UNISTD_H +%} + +%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(); + yycolumn = 1; + yylineno++; +} + +attribute return IDL_ATTRIBUTE; +bound return IDL_BOUND; +const return IDL_CONST; +constants return IDL_CONSTANTS; +constrained return IDL_CONSTRAINED; +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_REMOVABLE; +service return IDL_SERVICE; +sequence return IDL_SEQUENCE; +singleton return IDL_SINGLETON; +struct return IDL_STRUCT; +transient return IDL_TRANSIENT; +typedef return IDL_TYPEDEF; + +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; + +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)(("+"|"-")?{DIGIT}+)?(f|F)? | +("-")?{DIGIT}*"."{DIGIT}+((e|E)("+"|"-")?{DIGIT}+)?(f|F)? { + yylval.dval = asciiToFloat( yytext ); + return IDL_FLOATING_PT_LITERAL; + } + +{IDENTIFIER} { + yylval.sval = new 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 = OString(); + beginLine = idlc()->getLineNumber(); + } + +"/***" { + BEGIN( COMMENT ); + docu = OString(); + beginLine = idlc()->getLineNumber(); + } + +<COMMENT>[^*]+ { + docu += yytext; + } + +<COMMENT>"*"[^*/]+ { + docu += yytext; + } + +<COMMENT>"**" { + docu += yytext; + } + +<COMMENT>[*]+"/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { o3tl::getToken(docu, 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + BEGIN( INITIAL ); + } + +"/**" { + BEGIN( DOCU ); + docu = OString(); + beginLine = idlc()->getLineNumber(); + } + +<DOCU>[^*\n]+ { + docu += yytext; + } + +<DOCU>"\n"[ \t]*"*"{1} { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += "\n"; + } + +<DOCU>"\n" { + idlc()->setLineNumber( idlc()->getLineNumber() + 1); + docu += yytext; + } + +<DOCU>"*"[^*^/\n]* { + docu += yytext; + } + +<DOCU>"\n"[ \t]*"*/" { + docu = docu.trim(); + sal_Int32 nIndex = 0; + int count = 0; + do { o3tl::getToken(docu, 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[nIndex - 1] != '"' && docu[nIndex - 1] != ':') ) + ErrorHandler::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 { o3tl::getToken(docu, 0, '\n', nIndex ); count++; } while( nIndex != -1 ); + idlc()->setLineNumber( beginLine + count - 1); + if ( docu.indexOf("/*") >= 0 || docu.indexOf("//") >= 0 ) + { + if ( 0 != nIndex && + (docu[nIndex - 1] != '"' && docu[nIndex - 1] != ':') ) + ErrorHandler::syntaxError(PS_NoState, idlc()->getLineNumber(), + "nested documentation strings are not allowed!"); + } + idlc()->setDocumentation(docu); + BEGIN( INITIAL ); + } + +"//"[^/]{1}.*"\n" { + /* only a comment */ + OString docStr(yytext); + docStr = docStr.copy( 0, docStr.lastIndexOf('\n') ); + docStr = docStr.copy( docStr.lastIndexOf('/')+1 ); + docStr = docStr.trim(); + idlc()->incLineNumber(); + } + +"///".*"\n" { + 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(); +} + +%% + +/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/idlc/test/const.idl b/idlc/test/const.idl new file mode 100644 index 000000000..aeb638e22 --- /dev/null +++ b/idlc/test/const.idl @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +module idlc +{ +module test +{ + const long l = 1; + const long add = 1 + 2; + const long sub = 3 - 2; + const hyper h = 123456789; + const float f7 = 3.4123; + const float f2 = 3.4123 + 10e-12; + const boolean bt = True; + const boolean bf = False; + const boolean and = bt & bf; + + /// SHORT_MAX + 1; + const short shortMax = -0x8000; + /// LONG_MAX + 1; + const unsigned long longMax = 0x80000000; + + +constants USER +{ + /// = 1 + const long FLAG1 = 0x00000001; + /// = 2 + const long FLAG2 = 0x00000002; + /// = 4 + const long FLAG3 = 0x00000004; + /// = 8 + const long FLAG4 = 0x00000008; + /// = 16 + const long FLAG5 = 0x00000010; + /// = 0 + const long FLAG6 = FLAG1 & FLAG2; + /// = 3 + const long FLAG7 = FLAG1 | FLAG2; + /// = 2 + const long FLAG8 = (FLAG1 | FLAG2) & FLAG2; + /// = 4 + const long FLAG9 = FLAG1 << 2; + /// = 32 + const long FLAG10 = (FLAG5 >> 1) << 2; + /// = 1 + const long FLAG11 = 33 % 4; + /// = 4 + const long FLAG12 = FLAG10 / 8; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/enum.idl b/idlc/test/enum.idl new file mode 100644 index 000000000..9ddbd6e76 --- /dev/null +++ b/idlc/test/enum.idl @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +module idlc +{ +module test +{ + +enum Error +{ + NONE, + FATAL, + SYSTEM, + RUNTIME +}; + +enum Warning +{ + NO, + USER = 2, + WRONGPASSWORD = 4, + IDFAILURE +}; + + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/exception.idl b/idlc/test/exception.idl new file mode 100644 index 000000000..cc15069f4 --- /dev/null +++ b/idlc/test/exception.idl @@ -0,0 +1,40 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +module idlc +{ +module test +{ + +exception BaseException +{ + string Description; +}; + +exception RuntimeException : BaseException +{ + long Id; + type Context; +}; + + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/identifiers.idl b/idlc/test/identifiers.idl new file mode 100644 index 000000000..d845b3729 --- /dev/null +++ b/idlc/test/identifiers.idl @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +struct Identifiers +{ + long onlysmallalphas; + long smallMixedAlphas; + long CapMixedAlphas; + long ONLYCAPS; + long CAPS_WITH_UNDERSCORE; + long CAPS_WITH_UNDERSCORE_11; + long CAPS_WITH_UNDERSCORE11_11TEST; + long CapMixed_Alphas_11; + long m_CapMixedAlphas_11; // should be not allowed with -cid + long small_get; //should be not allowed with -cid + long small_11; //should be not allowed with -cid + long small_11small; //should be not allowed with -cid + long mixedAlphas_11CAPS; // should be not allowed with -cid + long mixedAlphas_11mixedAlphas; // should be not allowed with -cid + long _mixedAlphas; // should be not allowed with -cid +// long _mixedAlphas_; // should be not allowed +// long CapsMixedAlphas_; // should be not allowed +// long _CapsMixedAlphas_; // should be not allowed + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/interface.idl b/idlc/test/interface.idl new file mode 100644 index 000000000..5de90a07b --- /dev/null +++ b/idlc/test/interface.idl @@ -0,0 +1,71 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <enum.idl> +#include <struct.idl> + +module idlc +{ + +module test +{ + +interface XBase +{ + [readonly, attribute] string description; + + string getDescription(); +}; + +interface XTestBaseTypes : XBase +{ + void voidFunc(); + + short shortFunc( [in] short inparam, [out] short outparam, [inout] short inoutparam); + unsigned short uShortFunc( [in] unsigned short inparam, [out] unsigned short outparam, [inout] unsigned short inoutparam); + + long longFunc( [in] long inparam, [out] long outparam, [inout] long inoutparam); + unsigned long ulongFunc( [in] unsigned long inparam, [out] unsigned long outparam, [inout] unsigned long inoutparam); + + hyper hyperFunc( [in] hyper inparam, [out] hyper outparam, [inout] hyper inoutparam); + unsigned hyper uHyperFunc( [in] unsigned hyper inparam, [out] unsigned hyper outparam, [inout] unsigned hyper inoutparam); + + float floatFunc( [in] float inparam, [out] float outparam, [inout] float inoutparam); + double doubleFunc( [in] double inparam, [out] double outparam, [inout] double inoutparam); + char charFunc( [in] char inparam, [out] char outparam, [inout] char inoutparam); + string stringFunc( [in] string inparam, [out] string outparam, [inout] string inoutparam); + byte byteFunc( [in] byte inparam, [out] byte outparam, [inout] byte inoutparam); + + type typeFunc( [in] type inparam, [out] type outparam, [inout] type inoutparam); + any anyFunc( [in] any inparam, [out] any outparam, [inout] any inoutparam); +}; + + +interface XTestComplexTypes : XBase +{ + Error enumFunc( [in] Error inparam, [out] Error outparam, [inout] Error inoutparam); + + BaseStruct structFunc( [in] ::idlc::test::BaseStruct inparam, [out] idlc::test::BaseStruct outparam, [inout] BaseStruct inoutparam); +}; + +}; + +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/parser/attribute.tests b/idlc/test/parser/attribute.tests new file mode 100644 index 000000000..dd0b85bde --- /dev/null +++ b/idlc/test/parser/attribute.tests @@ -0,0 +1,232 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "attribute.tests 1": +interface I1 { + [attribute] long a; +}; + + +EXPECT SUCCESS "attribute.tests 2": +interface I1 { + [attribute] long a {}; +}; + + +EXPECT FAILURE "attribute.tests 3": +interface I1 { + [attribute] long a { + get raises (); + }; +}; + + +EXPECT FAILURE "attribute.tests 3a": +interface I1 { + [attribute] long a { + set raises (); + }; +}; + + +EXPECT SUCCESS "attribute.tests 4": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 5": +exception E1 {}; +interface I1 { + [attribute] long a { + set raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 6": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + set raises (E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 7": +exception E1 {}; +interface I1 { + [attribute] long a { + set raises (E1); + get raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 8": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1); + get raises (E1); + }; +}; + + +EXPECT OLD-FAILURE "attribute.tests 9": +exception E1 {}; +interface I1 { + void E1(); + [attribute] long a { + get raises (E1); + }; +}; + + +EXPECT OLD-FAILURE "attribute.tests 10": +exception E1 {}; +interface I1 { + [attribute] long E1 { + get raises (E1); + }; +}; + + +EXPECT NEW-FAILURE "attribute.tests 11": +exception E1 {}; +interface I1 { + [attribute] long a { + get raises (E1,E1); + }; +}; + + +EXPECT SUCCESS "attribute.tests 12": +exception E1 {}; +interface I1 { + [attribute, readonly] long a { + get raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 13": +exception E1 {}; +interface I1 { + [attribute, readonly] long a { + set raises (E1); + }; +}; + + +EXPECT FAILURE "attribute.tests 14": +interface I1 { + [] long a; +}; + + +EXPECT SUCCESS "attribute.tests 15": +interface I1 { + [attribute] long a; +}; + + +EXPECT FAILURE "attribute.tests 16": +interface I1 { + [attribute, property] long a; +}; + + +EXPECT FAILURE "attribute.tests 17": +interface I1 { + [attribute, optional] long a; +}; + + +EXPECT FAILURE "attribute.tests 18": +interface I1 { + [attribute, maybevoid] long a; +}; + + +EXPECT FAILURE "attribute.tests 19": +interface I1 { + [attribute, constrained] long a; +}; + + +EXPECT FAILURE "attribute.tests 20": +interface I1 { + [attribute, transient] long a; +}; + + +EXPECT FAILURE "attribute.tests 21": +interface I1 { + [attribute, maybeambiguous] long a; +}; + + +EXPECT FAILURE "attribute.tests 22": +interface I1 { + [attribute, maybedefault] long a; +}; + + +EXPECT FAILURE "attribute.tests 23": +interface I1 { + [attribute, removable] long a; +}; + + +EXPECT SUCCESS "attribute.tests 24": +interface I1 { + [attribute, bound] long a; +}; + + +EXPECT SUCCESS "attribute.tests 25": +interface I1 { + [bound, attribute] long a; +}; + + +EXPECT SUCCESS "attribute.tests 26": +interface I1 { + [attribute, readonly] long a; +}; + + +EXPECT SUCCESS "attribute.tests 27": +interface I1 { + [attribute, bound, readonly] long a; +}; + + +EXPECT SUCCESS "attribute.tests 28": +exception E1 {}; +interface I1 { + [attribute, bound] long a { + get raises (E1); + set raises (E1); + }; +}; diff --git a/idlc/test/parser/constant.tests b/idlc/test/parser/constant.tests new file mode 100644 index 000000000..49183d4d1 --- /dev/null +++ b/idlc/test/parser/constant.tests @@ -0,0 +1,294 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "constant.tests 1": +constants C { + const boolean C1 = FALSE; + const byte C2 = 0; + const short C3 = 0; + const unsigned short C4 = 0; + const long C5 = 0; + const unsigned long C6 = 0; + const hyper C7 = 0; + const unsigned hyper C8 = 0; + const float C9 = 0.0; + const double C10 = 0.0; +}; + + +EXPECT FAILURE "constant.tests 2": +module m { + const boolean C1 = FALSE; + const byte C2 = 0; + const short C3 = 0; + const unsigned short C4 = 0; + const long C5 = 0; + const unsigned long C6 = 0; + const hyper C7 = 0; + const unsigned hyper C8 = 0; + const float C9 = 0.0; + const double C10 = 0.0; +}; + + +EXPECT FAILURE "constant.tests 3": +constants C { + const char C1 = 'A'; +}; + + +EXPECT FAILURE "constant.tests 4": +module m { + const char C1 = 'A'; +}; + + +EXPECT FAILURE "constant.tests 5": +constants C { + const string C1 = ""; +}; + + +EXPECT FAILURE "constant.tests 6": +module m { + const string C1 = ""; +}; + + +EXPECT SUCCESS "constant.tests 7": +constants C {}; + + +EXPECT SUCCESS "constant.tests 8": +constants C { + const byte C1 = -128; + const byte C2 = -0200; + const byte C3 = -0x80; + const byte C4 = 127; + const byte C5 = 0177; + const byte C6 = 0x7F; + const short C7 = -32768; + const short C8 = -0100000; + const short C9 = -0x8000; + const short C10 = 32767; + const short C11 = 077777; + const short C12 = 0x7FFF; + const unsigned short C13 = 0; + const unsigned short C14 = 0x0; + const unsigned short C15 = 65535; + const unsigned short C16 = 0177777; + const unsigned short C17 = 0xFFFF; + const long C18 = -2147483648; + const long C19 = -020000000000; + const long C20 = -0x80000000; + const long C21 = 2147483647; + const long C22 = 017777777777; + const long C23 = 0x7FFFFFFF; + const unsigned long C24 = 0; + const unsigned long C25 = 0x0; + const unsigned long C26 = 4294967295; + const unsigned long C27 = 037777777777; + const unsigned long C28 = 0xFFFFFFFF; + const hyper C29 = -9223372036854775808; + const hyper C30 = -01000000000000000000000; + const hyper C31 = -0x8000000000000000; + const hyper C32 = 9223372036854775807; + const hyper C33 = 0777777777777777777777; + const hyper C34 = 0x7FFFFFFFFFFFFFFF; + const unsigned hyper C35 = 0; + const unsigned hyper C36 = 0x0; + const unsigned hyper C37 = 18446744073709551615; + const unsigned hyper C38 = 01777777777777777777777; + const unsigned hyper C39 = 0xFFFFFFFFFFFFFFFF; +}; + + +EXPECT NEW-FAILURE "constant.tests 8a": +constants C { + const byte C4 = 255; + const byte C5 = 0377; + const byte C6 = 0xFF; +}; + + +EXPECT FAILURE "constant.tests 9": +constants C { const byte C1 = -129; }; + + +EXPECT FAILURE "constant.tests 10": +constants C { const byte C1 = -0201; }; + + +EXPECT FAILURE "constant.tests 11": +constants C { const byte C1 = -0x81; }; + + +EXPECT FAILURE "constant.tests 12": +constants C { const byte C1 = 256; }; + + +EXPECT FAILURE "constant.tests 13": +constants C { const byte C1 = 0400; }; + + +EXPECT FAILURE "constant.tests 14": +constants C { const byte C1 = 0x100; }; + + +EXPECT FAILURE "constant.tests 15": +constants C { const short C1 = -32769; }; + + +EXPECT FAILURE "constant.tests 16": +constants C { const short C1 = -0100001; }; + + +EXPECT FAILURE "constant.tests 17": +constants C { const short C1 = -0x8001; }; + + +EXPECT FAILURE "constant.tests 18": +constants C { const short C1 = 32768; }; + + +EXPECT FAILURE "constant.tests 19": +constants C { const short C1 = 0100000; }; + + +EXPECT FAILURE "constant.tests 20": +constants C { const short C1 = 0x8000; }; + + +EXPECT FAILURE "constant.tests 21": +constants C { const unsigned short C1 = -1; }; + + +EXPECT FAILURE "constant.tests 22": +constants C { const unsigned short C1 = -01; }; + + +EXPECT FAILURE "constant.tests 23": +constants C { const unsigned short C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 24": +constants C { const unsigned short C1 = 65536; }; + + +EXPECT FAILURE "constant.tests 25": +constants C { const unsigned short C1 = 0200000; }; + + +EXPECT FAILURE "constant.tests 26": +constants C { const unsigned short C1 = 0x10000; }; + + +EXPECT FAILURE "constant.tests 27": +constants C { const long C1 = -2147483649; }; + + +EXPECT FAILURE "constant.tests 28": +constants C { const long C1 = -020000000001; }; + + +EXPECT FAILURE "constant.tests 29": +constants C { const long C1 = -0x80000001; }; + + +EXPECT FAILURE "constant.tests 30": +constants C { const long C1 = 2147483648; }; + + +EXPECT FAILURE "constant.tests 31": +constants C { const long C1 = 020000000000; }; + + +EXPECT FAILURE "constant.tests 32": +constants C { const long C1 = 0x80000000; }; + + +EXPECT FAILURE "constant.tests 33": +constants C { const unsigned long C1 = -1; }; + + +EXPECT FAILURE "constant.tests 34": +constants C { const unsigned long C1 = -01; }; + + +EXPECT FAILURE "constant.tests 35": +constants C { const unsigned long C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 36": +constants C { const unsigned long C1 = 4294967296; }; + + +EXPECT FAILURE "constant.tests 37": +constants C { const unsigned long C1 = 040000000000; }; + + +EXPECT FAILURE "constant.tests 38": +constants C { const unsigned long C1 = 0x100000000; }; + + +EXPECT FAILURE "constant.tests 39": +constants C { const hyper C1 = -9223372036854775809; }; + + +EXPECT FAILURE "constant.tests 40": +constants C { const hyper C1 = -01000000000000000000001; }; + + +EXPECT FAILURE "constant.tests 41": +constants C { const hyper C1 = -0x8000000000000001; }; + + +EXPECT FAILURE "constant.tests 42": +constants C { const hyper C1 = 9223372036854775808; }; + + +EXPECT FAILURE "constant.tests 43": +constants C { const hyper C1 = 01000000000000000000000; }; + + +EXPECT FAILURE "constant.tests 44": +constants C { const hyper C1 = 0x8000000000000000; }; + + +EXPECT FAILURE "constant.tests 45": +constants C { const unsigned hyper C1 = -1; }; + + +EXPECT FAILURE "constant.tests 46": +constants C { const unsigned hyper C1 = -01; }; + + +EXPECT FAILURE "constant.tests 47": +constants C { const unsigned hyper C1 = -0x1; }; + + +EXPECT FAILURE "constant.tests 48": +constants C { const unsigned hyper C1 = 18446744073709551616; }; + + +EXPECT FAILURE "constant.tests 49": +constants C { const unsigned hyper C1 = 02000000000000000000000; }; + + +EXPECT FAILURE "constant.tests 50": +constants C { const unsigned hyper C1 = 0x10000000000000000; }; diff --git a/idlc/test/parser/constructor.tests b/idlc/test/parser/constructor.tests new file mode 100644 index 000000000..ce2438b98 --- /dev/null +++ b/idlc/test/parser/constructor.tests @@ -0,0 +1,190 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "constructor.tests 1": +interface X {}; +service S: X; + + +EXPECT SUCCESS "constructor.tests 2": +interface X {}; +service S: X {}; + + +EXPECT SUCCESS "constructor.tests 3": +interface X {}; +service S: X { + f(); +}; + + +EXPECT FAILURE "constructor.tests 4": +interface X {}; +service S: X { + f(); + f(); +}; + + +EXPECT FAILURE "constructor.tests 5": +interface X { + void f([in] any... p); +}; + + +EXPECT FAILURE "constructor.tests 6": +interface X { + void f([out] any... p); +}; + + +EXPECT SUCCESS "constructor.tests 7": +interface X {}; +service S: X { + f([in] any... p); +}; + + +EXPECT SUCCESS "constructor.tests 8": +interface X {}; +typedef any some; +service S: X { + f([in] some... p); +}; + + +EXPECT FAILURE "constructor.tests 9": +interface X {}; +service S: X { + f([in] long p1, [in] any... p2); +}; + + +EXPECT FAILURE "constructor.tests 10": +interface X {}; +service S: X { + f([in] any... p2, [in] long p1); +}; + + +EXPECT FAILURE "constructor.tests 11": +interface X {}; +service S: X { + f([in] long p1, [in] long... p2); +}; + + +EXPECT FAILURE "constructor.tests 12": +interface X {}; +service S: X { + f([out] long p); +}; + + +EXPECT FAILURE "constructor.tests 13": +interface X {}; +service S: X { + f([out] any... p); +}; + + +EXPECT FAILURE "constructor.tests 14": +interface X {}; +singleton S: X { + f(); +}; + + +EXPECT FAILURE "constructor.tests 15": +module com { module sun { module star { module test { + interface X {}; +service S: com::sun::star::test::X { + c1([in] long a, [in] com::sun::star::test::X b); + c2([in] long c, [in] X d); +}; +}; }; }; }; + + +EXPECT FAILURE "constructor.tests 16": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +typedef long T; +service S: com::sun::star::test::X { + c1([in] sequence<long> a); + c2([in] sequence<T> b); +}; + + +EXPECT FAILURE "constructor.tests 17": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +service S: com::sun::star::test::X { + c1([in] any... a); + c2([in] any... b); +}; + + +EXPECT SUCCESS "constructor.tests 18": +module com { module sun { module star { module test { + interface X {}; +}; }; }; }; +service S: com::sun::star::test::X { + c1([in] any... a); + c2([in] sequence<any> b); +}; + + +EXPECT SUCCESS "constructor.tests 19": +module com { module sun { module star { module test { + interface X { void m(); }; +}; }; }; }; +service S: com::sun::star::test::X { + c([in] any... a); +}; + + +EXPECT SUCCESS "constructor.tests 20": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a, [in] long b); + c2([in] long a); +}; + + +EXPECT SUCCESS "constructor.tests 21": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a); + c2([in] long a, [in] long b); +}; + + +EXPECT SUCCESS "constructor.tests 22": +module com { module sun { module star { module uno { + interface XInterface { void m(); }; +}; }; }; }; +service S: com::sun::star::uno::XInterface { + c1([in] long a, [in] short b); + c2([in] long a, [in] long b); +}; diff --git a/idlc/test/parser/conversion.tests b/idlc/test/parser/conversion.tests new file mode 100644 index 000000000..4f1d6bc7d --- /dev/null +++ b/idlc/test/parser/conversion.tests @@ -0,0 +1,79 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +EXPECT SUCCESS "conversion.tests 1": +constants C { + const byte C1 = -128.0; + const byte C2 = -127.9; + const byte C3 = 254.9; + const byte C4 = 255.0; + const short C5 = -32768.0; + const short C6 = -32767.9; + const short C7 = 32766.9; + const short C8 = 32767.0; + const unsigned short C9 = 0.0; + const unsigned short C10 = 0.1; + const unsigned short C11 = 65534.9; + const unsigned short C12 = 65535.0; + const long C13 = -2147483648.0; + const long C14 = -2147483647.9; + const long C15 = 2147483646.9; + const long C16 = 2147483647.0; + const unsigned long C17 = 0.0; + const unsigned long C18 = 0.1; + const unsigned long C19 = 4294967294.9; + const unsigned long C20 = 4294967295.0; + const hyper C21 = -9223372036854774784.0; // -0x7FFFFFFFFFFFFC00 = -0x1.FFFFFFFFFFFFFp62 + const hyper C22 = 9223372036854774784.0; // 0x7FFFFFFFFFFFFC00 = 0x1.FFFFFFFFFFFFFp62 + const unsigned hyper C23 = 0.0; + const unsigned hyper C24 = 0.1; + const unsigned hyper C25 = 18446744073709549568.0; // 0xFFFFFFFFFFFFF800 = 0x1.FFFFFFFFFFFFFp63 +}; + +EXPECT FAILURE "conversion.tests 2": +constants C { const byte C1 = -128.1; }; + +EXPECT FAILURE "conversion.tests 3": +constants C { const byte C1 = 255.1; }; + +EXPECT FAILURE "conversion.tests 4": +constants C { const short C1 = -32768.1; }; + +EXPECT FAILURE "conversion.tests 5": +constants C { const short C1 = 32767.1; }; + +EXPECT FAILURE "conversion.tests 6": +constants C { const unsigned short C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 7": +constants C { const unsigned short C1 = 65535.1; }; + +EXPECT FAILURE "conversion.tests 8": +constants C { const long C1 = -2147483648.1; }; + +EXPECT FAILURE "conversion.tests 9": +constants C { const long C1 = 2147483647.1; }; + +EXPECT FAILURE "conversion.tests 10": +constants C { const unsigned long C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 11": +constants C { const unsigned long C1 = 4294967295.1; }; + +EXPECT FAILURE "conversion.tests 12": +constants C { const hyper C1 = -9223372036854775808.0; }; // -0x8000000000000000 = -0x1p63 + +EXPECT FAILURE "conversion.tests 13": +constants C { const hyper C1 = 9223372036854775807.0; }; // 0x7FFFFFFFFFFFFFFF rounds up to 0x1p63 + +EXPECT FAILURE "conversion.tests 14": +constants C { const unsigned hyper C1 = -0.1; }; + +EXPECT FAILURE "conversion.tests 15": +constants C { const unsigned hyper C1 = 18446744073709551615.0; }; + // 0xFFFFFFFFFFFFFFFF rounds up to 0x1p64 diff --git a/idlc/test/parser/interfaceinheritance.tests b/idlc/test/parser/interfaceinheritance.tests new file mode 100644 index 000000000..f9cac4ca2 --- /dev/null +++ b/idlc/test/parser/interfaceinheritance.tests @@ -0,0 +1,279 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT FAILURE "interfaceinheritance.tests 1": +interface Base {}; +interface Derived { + interface Base; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 2": +interface Base {}; +interface Derived { + interface Base; + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 3": +interface Base {}; +interface Derived { + [optional] interface Base; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 4": +interface Base {}; +interface Derived { + [optional] interface Base; + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 5": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 6": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base2; + interface Base1; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 7": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 8": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 9": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 10": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base2; + interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 11": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 12": +interface Base1 {}; +interface Base2: Base1 {}; +interface Derived { + [optional] interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 13": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 14": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base2; + interface Base1; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 15": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 16": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 17": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 18": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base2; + interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 19": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 20": +interface Base1 {}; +interface Base2 { [optional] interface Base1; }; +interface Derived { + [optional] interface Base2; + [optional] interface Base1; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 21": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + interface Base2; + interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 22": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + [optional] interface Base2; + interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 23": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + interface Base2; + [optional] interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 24": +interface Base1 {}; +interface Base2: Base1 {}; +interface Base3: Base1 {}; +interface Derived { + [optional] interface Base2; + [optional] interface Base3; +}; + + +EXPECT SUCCESS "interfaceinheritance.tests 25": +interface Base {}; +interface Derived { + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 26": +interface Base; +interface Derived { + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 27": +interface Base; +interface Derived { + [optional] interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 28": +interface Base {}; +typedef Base Hidden; +interface Derived { + interface Base; + interface Hidden; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 29": +interface Base {}; +typedef Base Hidden; +interface Derived { + interface Hidden; + interface Base; +}; + + +EXPECT FAILURE "interfaceinheritance.tests 30": +interface Base {}; +interface Derived { + interface Base; + [optional] interface com::sun::star::uno::XInterface; +}; diff --git a/idlc/test/parser/methodoverload.tests b/idlc/test/parser/methodoverload.tests new file mode 100644 index 000000000..9a07a4b2c --- /dev/null +++ b/idlc/test/parser/methodoverload.tests @@ -0,0 +1,177 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT FAILURE "methodoverload.tests 1": +interface Derived { + void f(); + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 2": +interface Base { + void f(); +}; +interface Derived { + interface Base; + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 3": +interface Base { + void f(); +}; +interface Derived { + void f(); + interface Base; +}; + + +EXPECT FAILURE "methodoverload.tests 4": +interface Base { + void f(); +}; +interface Derived { + [optional] interface Base; + void f(); +}; + + +EXPECT FAILURE "methodoverload.tests 5": +interface Base { + void f(); +}; +interface Derived { + void f(); + [optional] interface Base; +}; + + +EXPECT FAILURE "methodoverload.tests 6": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 7": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + [optional] interface Base1; + interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 8": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + interface Base1; + [optional] interface Base2; +}; + + +EXPECT SUCCESS "methodoverload.tests 9": +interface Base1 { + void f(); +}; +interface Base2 { + void f(); +}; +interface Derived { + [optional] interface Base1; + [optional] interface Base2; +}; + + +EXPECT FAILURE "methodoverload.tests 10": +interface I { + [attribute] long a; + [attribute] short a; +}; + + +EXPECT FAILURE "methodoverload.tests 11": +interface I1 { + [attribute] long a; +}; +interface I2 { + [attribute] short a; + interface I1; +}; + + +EXPECT FAILURE "methodoverload.tests 12": +interface I { + [attribute] long a; + void a(); +}; + + +EXPECT FAILURE "methodoverload.tests 13": +interface I1 { + [attribute] long a; +} +interface I2 { + void a(); + interface I1; +}; + + +EXPECT FAILURE "methodoverload.tests 14": +interface I1 { + void a(); +} +interface I2 { + [attribute] long a; + interface I1; +}; + + +EXPECT SUCCESS "methodoverload.tests 15": +interface I { + [attribute] long a; + void geta(); + void seta(); +}; + + +EXPECT SUCCESS "methodoverload.tests 16": +interface I1 { + [attribute] long a; +}; +interface I2: I1 { + void geta(); + void seta(); +}; diff --git a/idlc/test/parser/oldstyle.tests b/idlc/test/parser/oldstyle.tests new file mode 100644 index 000000000..c6692b977 --- /dev/null +++ b/idlc/test/parser/oldstyle.tests @@ -0,0 +1,28 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +EXPECT SUCCESS "oldstyle.tests 1": +service S1 {}; +service S2 { service S1; }; + + +EXPECT FAILURE "oldstyle.tests 2": +interface X {}; +service S1: X; +service S2 { service S1; }; + + +EXPECT SUCCESS "oldstyle.tests 3": +service S1 {}; +singleton S2 { service S1; }; + + +EXPECT FAILURE "oldstyle.tests 4": +interface X {}; +service S1: X; +singleton S2 { service S1; }; diff --git a/idlc/test/parser/polystruct.tests b/idlc/test/parser/polystruct.tests new file mode 100644 index 000000000..89b0817c9 --- /dev/null +++ b/idlc/test/parser/polystruct.tests @@ -0,0 +1,251 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "polystruct.tests 1": +struct Struct<T> { T member; }; + + +EXPECT FAILURE "polystruct.tests 2": +struct Struct<T,U,T,V> { long member; }; + + +EXPECT FAILURE "polystruct.tests 3": +struct Struct<T> { long member; }; +typedef Struct Typedef; + + +EXPECT FAILURE "polystruct.tests 4": +struct Struct<T> { long member; }; +typedef Struct<long> Typedef; + + +EXPECT SUCCESS "polystruct.tests 5": +struct Struct<T> { long member; }; + + +EXPECT SUCCESS "polystruct.tests 6": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 7": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<Struct1<string> > member; }; + + +EXPECT FAILURE "polystruct.tests 8": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<int> member; }; + + +EXPECT FAILURE "polystruct.tests 9": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<long,long> member; }; + + +EXPECT FAILURE "polystruct.tests 10": +struct Struct2 { Struct1<long> member; }; + + +EXPECT FAILURE "polystruct.tests 11": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<> member; }; + + +EXPECT FAILURE "polystruct.tests 12": +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<void> member; }; + + +EXPECT FAILURE "polystruct.tests 13": +exception Exception {}; +struct Struct1<T> { T member; }; +struct Struct2 { Struct1<Exception> member; }; + + +EXPECT SUCCESS "polystruct.tests 14": +struct Struct<T> { T T; }; + + +EXPECT SUCCESS "polystruct.tests 15": +struct Struct<Struct> { Struct member; }; + + +EXPECT FAILURE "polystruct.tests 16": +struct Struct<Struct> { Struct<long> member; }; + + +EXPECT FAILURE "polystruct.tests 17": +struct Struct<Struct> { ::Struct member; }; + + +EXPECT FAILURE "polystruct.tests 18": +struct Struct<Struct> { ::Struct<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 19": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { Struct1 member; }; + + +EXPECT SUCCESS "polystruct.tests 20": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { Struct1<long> member; }; + + +EXPECT SUCCESS "polystruct.tests 21": +struct Struct1<T> { T member; }; +struct Struct2<Struct1> { ::Struct1<long> member; }; + + +EXPECT FAILURE "polystruct.tests 22": +struct Struct1 { long member1; }; +struct Struct2<T>: Struct1 { long member2; }; + + +EXPECT FAILURE "polystruct.tests 23": +struct Struct1<T> { long member1; }; +struct Struct2: Struct1<long> { long member2; }; + + +EXPECT FAILURE "polystruct.tests 24": +struct Struct1<T> { long member1; }; +struct Struct2<T>: Struct1<long> { long member2; }; + + +EXPECT FAILURE "polystruct.tests 25": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<Struct2> member; }; + + +EXPECT SUCCESS "polystruct.tests 25a": +struct Struct<T> { long member; }; +interface X { [attribute] Struct<X> member; }; + + +EXPECT FAILURE "polystruct.tests 26": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3 { Struct1<Struct2<Struct3> > member; }; + + +EXPECT SUCCESS "polystruct.tests 27": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<Struct2> > member; }; + + +EXPECT SUCCESS "polystruct.tests 28": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<sequence<Struct2> > > member; }; + + +EXPECT SUCCESS "polystruct.tests 29": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<Struct1<Struct2> > member; }; + + +EXPECT SUCCESS "polystruct.tests 30": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<Struct1<sequence<Struct2> > > member; }; + + +EXPECT SUCCESS "polystruct.tests 31": +struct Struct1<T> { long member; }; +struct Struct2 { sequence<sequence<Struct1<Struct2> > > member; }; + + +EXPECT FAILURE "polystruct.tests 32": +struct Struct<T> { Struct member; }; + + +EXPECT FAILURE "polystruct.tests 33": +struct Struct<T> { Struct<long> member; }; + + +EXPECT FAILURE "polystruct.tests 34": +struct Struct<T> { Struct<Struct> member; }; + + +EXPECT FAILURE "polystruct.tests 35": +struct Struct<T> { Struct<Struct<long> > member; }; + + +EXPECT FAILURE "polystruct.tests 36": +struct Struct1<T> { long member; }; +struct Struct2<T> { Struct1<Struct2> member; }; + + +EXPECT FAILURE "polystruct.tests 37": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3<T> { Struct1<Struct2<Struct3> > member; }; + + +EXPECT FAILURE "polystruct.tests 38": +struct Struct1<T> { long member; }; +struct Struct2<T> { Struct1<Struct2<long> > member; }; + + +EXPECT FAILURE "polystruct.tests 39": +struct Struct1<T> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3<T> { Struct1<Struct2<Struct3<long> > > member; }; + + +EXPECT FAILURE "polystruct.tests 40": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<unsigned short> member; }; + + +EXPECT FAILURE "polystruct.tests 41": +struct Struct1<T, U> { long member; }; +struct Struct2<T> { long member; }; +struct Struct3 { Struct2<Struct1<long, unsigned long> > member; }; + + +EXPECT FAILURE "polystruct.tests 42": +struct Struct<T> { long member; }; +interface X { void f([in] Struct<unsigned hyper> p); }; + + +EXPECT FAILURE "polystruct.tests 43": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<unsigned short> > member; }; + + +EXPECT SUCCESS "polystruct.tests 44": +struct Struct1<T> { long member; }; +struct Struct2 { Struct1<sequence<char> > member; }; + + +EXPECT FAILURE "polystruct.tests 45": +struct Struct1<T> { long member; }; +typedef unsigned short td; +struct Struct2 { Struct1<td> member; }; + + +EXPECT FAILURE "polystruct.tests 46": +struct Struct1<T> { long member; }; +typedef sequence<unsigned short> td; +struct Struct2 { Struct1<td> member; }; + + +EXPECT FAILURE "polystruct.tests 47": +struct Struct1<T> { long member; }; +typedef unsigned short td; +struct Struct2 { Struct1<sequence<td> > member; }; diff --git a/idlc/test/parser/published.tests b/idlc/test/parser/published.tests new file mode 100644 index 000000000..f81ef6b41 --- /dev/null +++ b/idlc/test/parser/published.tests @@ -0,0 +1,681 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "published.tests 1": +published enum Enum { VALUE }; +published struct Struct1 { long member; }; +published struct Struct2<T> { T member; }; +published exception E1 {}; +published interface I1 {}; +published typedef long Typedef; +published constants Constants { const long Constant = 1; }; +published service Service1: I1 {}; +published service Service2 { interface I1; }; +published singleton Singleton1: I1; +published singleton Singleton2 { service Service2; }; + + +EXPECT FAILURE "published.tests 2": +constants Constants { published const long C = 1; }; + + +EXPECT FAILURE "published.tests 3": +published constants Constants { published const long C = 1; }; + + +EXPECT FAILURE "published.tests 4": +published module m {}; + + +EXPECT SUCCESS "published.tests 5": +interface I1; +interface I1 {}; + + +EXPECT SUCCESS "published.tests 6": +interface I1; +published interface I1 {}; + + +EXPECT FAILURE "published.tests 7": +published interface I1; +interface I1 {}; + + +EXPECT SUCCESS "published.tests 8": +published interface I1; +published interface I1 {}; + + +EXPECT SUCCESS "published.tests 9": +struct S1 { long m1; }; +struct S2: S1 { long m2; }; + + +EXPECT FAILURE "published.tests 10": +struct S1 { long m1; }; +published struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 11": +published struct S1 { long m1; }; +struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 12": +published struct S1 { long m1; }; +published struct S2: S1 { long m2; }; + + +EXPECT SUCCESS "published.tests 13": +enum E { V }; +struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 14": +enum E { V }; +struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 15": +enum E { V }; +published struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 16": +enum E { V }; +published struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 17": +published enum E { V }; +struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT FAILURE "published.tests 18": +published enum E { V }; +struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 19": +published enum E { V }; +published struct S1<T> { T m1; }; +struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 20": +published enum E { V }; +published struct S1<T> { T m1; }; +published struct S2 { S1<E> m2; }; + + +EXPECT SUCCESS "published.tests 21": +module com { module sun { module star { module uno { +exception Exception {}; +exception E2: Exception {}; +}; }; }; }; + + +EXPECT FAILURE "published.tests 22": +module com { module sun { module star { module uno { +exception Exception {}; +published exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 23": +module com { module sun { module star { module uno { +published exception Exception {}; +exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 24": +module com { module sun { module star { module uno { +published exception Exception {}; +published exception E2: Exception {}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 25": +enum E { V }; +module com { module sun { module star { module uno { +exception Exception { E m; }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 26": +enum E { V }; +module com { module sun { module star { module uno { +published exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 27": +published enum E { V }; +module com { module sun { module star { module uno { +exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 28": +published enum E { V }; +module com { module sun { module star { module uno { +published exception Exception { E m; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 29": +interface I1 {}; +interface I2: I1 {}; + + +EXPECT FAILURE "published.tests 30": +interface I1 {}; +published interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 31": +published interface I1 {}; +interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 32": +published interface I1 {}; +published interface I2: I1 {}; + + +EXPECT SUCCESS "published.tests 33": +enum E { V }; +interface I1 { [attribute] E m; }; + + +EXPECT FAILURE "published.tests 34": +enum E { V }; +published interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 35": +published enum E { V }; +interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 36": +published enum E { V }; +published interface I1 { [attribute] E m; }; + + +EXPECT SUCCESS "published.tests 36a.1": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 { [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 36a.2": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 { + [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 36a.3": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 { [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 36a.4": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 { + [attribute] long m { get raises (Exception); }; }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 37": +enum E { V }; +interface I1 { E f(); }; + + +EXPECT FAILURE "published.tests 38": +enum E { V }; +published interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 39": +published enum E { V }; +interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 40": +published enum E { V }; +published interface I1 { E f(); }; + + +EXPECT SUCCESS "published.tests 41": +enum E { V }; +interface I1 { void f([in] E p); }; + + +EXPECT FAILURE "published.tests 42": +enum E { V }; +published interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 43": +published enum E { V }; +interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 44": +published enum E { V }; +published interface I1 { void f([in] E p); }; + + +EXPECT SUCCESS "published.tests 45": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT FAILURE "published.tests 46": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 47": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 48": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 { void f() raises (Exception); }; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 49": +interface I1 {}; +interface I2 { interface I1; }; + + +EXPECT FAILURE "published.tests 50": +interface I1 {}; +published interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 51": +published interface I1 {}; +interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 52": +published interface I1 {}; +published interface I2 { interface I1; }; + + +EXPECT SUCCESS "published.tests 57": +enum E { V }; +typedef E T; + + +EXPECT FAILURE "published.tests 58": +enum E { V }; +published typedef E T; + + +EXPECT SUCCESS "published.tests 59": +published enum E { V }; +typedef E T; + + +EXPECT SUCCESS "published.tests 60": +published enum E { V }; +published typedef E T; + + +EXPECT SUCCESS "published.tests 61": +enum E { V }; +typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 62": +enum E { V }; +typedef E T; +published struct S { T m; }; + + +EXPECT FAILURE "published.tests 63": +enum E { V }; +published typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 64": +enum E { V }; +published typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 65": +published enum E { V }; +typedef E T; +struct S { T m; }; + + +EXPECT FAILURE "published.tests 66": +published enum E { V }; +typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 67": +published enum E { V }; +published typedef E T; +struct S { T m; }; + + +EXPECT SUCCESS "published.tests 68": +published enum E { V }; +published typedef E T; +published struct S { T m; }; + + +EXPECT SUCCESS "published.tests 73": +constants Cs { + const long C1 = 1; + const long C2 = C1 + 1; +}; + + +EXPECT SUCCESS "published.tests 74": +published constants Cs { + const long C1 = 1; + const long C2 = C1 + 1; +}; + + +EXPECT SUCCESS "published.tests 83": +constants Cs1 { const long C1 = 1; }; +constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT FAILURE "published.tests 84": +constants Cs1 { const long C1 = 1; }; +published constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 85": +published constants Cs1 { const long C1 = 1; }; +constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 86": +published constants Cs1 { const long C1 = 1; }; +published constants Cs2 { const long C2 = Cs1::C1 + 1; }; + + +EXPECT SUCCESS "published.tests 87": +typedef long T; +constants Cs { const T C = 1; }; + + +EXPECT FAILURE "published.tests 88": +typedef long T; +published constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 89": +published typedef long T; +constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 90": +published typedef long T; +published constants Cs { const T C = 1; }; + + +EXPECT SUCCESS "published.tests 91": +service S1 {}; +service S2 { service S1; }; + + +EXPECT FAILURE "published.tests 92": +service S1 {}; +published service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 93": +published service S1 {}; +service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 94": +published service S1 {}; +published service S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 95": +interface I1 {}; +service S { interface I1; }; + + +EXPECT FAILURE "published.tests 96": +interface I1 {}; +published service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 97": +published interface I1 {}; +service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 98": +published interface I1 {}; +published service S { interface I1; }; + + +EXPECT SUCCESS "published.tests 99": +interface I1 {}; +service S: I1; + + +EXPECT FAILURE "published.tests 100": +interface I1 {}; +published service S: I1; + + +EXPECT SUCCESS "published.tests 101": +published interface I1 {}; +service S: I1; + + +EXPECT SUCCESS "published.tests 102": +published interface I1 {}; +published service S: I1; + + +EXPECT SUCCESS "published.tests 103": +enum E { V }; +interface I1 {}; +service S: I1 { + f([in] E p); +}; + + +EXPECT FAILURE "published.tests 104": +enum E { V }; +published interface I1 {}; +published service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 105": +published enum E { V }; +interface I1 {}; +service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 106": +published enum E { V }; +published interface I1 {}; +published service S: I1 { + f([in] E p); +}; + + +EXPECT SUCCESS "published.tests 107": +module com { module sun { module star { module uno { +exception Exception {}; +interface I1 {}; +service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT FAILURE "published.tests 108": +module com { module sun { module star { module uno { +exception Exception {}; +published interface I1 {}; +published service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 109": +module com { module sun { module star { module uno { +published exception Exception {}; +interface I1 {}; +service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 110": +module com { module sun { module star { module uno { +published exception Exception {}; +published interface I1 {}; +published service S: I1 { + f() raises (Exception); +}; +}; }; }; }; + + +EXPECT SUCCESS "published.tests 111": +service S1 {}; +singleton S2 { service S1; }; + + +EXPECT FAILURE "published.tests 112": +service S1 {}; +published singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 113": +published service S1 {}; +singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 114": +published service S1 {}; +published singleton S2 { service S1; }; + + +EXPECT SUCCESS "published.tests 115": +interface I1 {}; +singleton S: I1; + + +EXPECT FAILURE "published.tests 116": +interface I1 {}; +published singleton S: I1; + + +EXPECT SUCCESS "published.tests 117": +published interface I1 {}; +singleton S: I1; + + +EXPECT SUCCESS "published.tests 118": +published interface I1 {}; +published singleton S: I1; + + +EXPECT FAILURE "published.tests 119": +interface I1 {}; +published interface I2 { [optional] interface I1; }; + + +EXPECT FAILURE "published.tests 120": +service S1 {}; +published service S2 { [optional] service S1; }; + + +EXPECT SUCCESS "published.tests 121": +interface I {}; +published service S { [optional] interface I; }; + + +EXPECT FAILURE "published.tests 122": +interface I {}; +published service S { [optional, property] I p; }; + + +EXPECT FAILURE "published.tests 123": +interface I {}; +published service S { [optional, property] sequence<I> p; }; + + +EXPECT FAILURE "published.tests 124": +struct P<T> { T m; }; +interface I {}; +published service S { [optional, property] P<I> p; }; + + +EXPECT FAILURE "published.tests 125": +published struct P<T> { T m; }; +interface I {}; +published service S { [optional, property] P<I> p; }; + + +EXPECT FAILURE "published.tests 126": +struct P<T> { T m; }; +published interface I {}; +published service S { [optional, property] P<I> p; }; diff --git a/idlc/test/parser/struct.tests b/idlc/test/parser/struct.tests new file mode 100644 index 000000000..77d500e89 --- /dev/null +++ b/idlc/test/parser/struct.tests @@ -0,0 +1,46 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT FAILURE "struct.tests 1": +struct S { void m; }; + + +EXPECT FAILURE "struct.tests 2": +struct S { sequence<void> m; }; + + +EXPECT FAILURE "struct.tests 3": +exception E {}; +struct S { E m; }; + + +EXPECT FAILURE "struct.tests 4": +exception E {}; +struct S { sequence<E> m; }; + + +EXPECT FAILURE "struct.tests 5": +struct S { S m; }; + + +EXPECT SUCCESS "struct.tests 6": +struct S { sequence<S> m; }; + + +EXPECT SUCCESS "struct.tests 7": +struct S { sequence<sequence<S> > m; }; diff --git a/idlc/test/parser/typedef.tests b/idlc/test/parser/typedef.tests new file mode 100644 index 000000000..0eaf5d634 --- /dev/null +++ b/idlc/test/parser/typedef.tests @@ -0,0 +1,63 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +# + +EXPECT SUCCESS "typedef.tests 1": +struct Struct1 { long member1; }; +typedef Struct1 T1; +typedef T1 T2; +struct Struct2: T2 { long member2; }; + + +EXPECT FAILURE "typedef.tests 2": +typedef long T1; +typedef T1 T2; +struct Struct: T2 { long member2; }; + + +EXPECT SUCCESS "typedef.tests 3": +interface Interface1 {}; +typedef Interface1 T1; +typedef T1 T2; +interface Interface2: T2 {}; + + +EXPECT FAILURE "typedef.tests 4": +interface Interface1; +typedef Interface1 T1; +typedef T1 T2; +interface Interface2: T2 {}; + + +EXPECT FAILURE "typedef.tests 5": +typedef long T1; +typedef T1 T2; +interface Interface: T2 {}; + + +EXPECT FAILURE "typedef.tests 6": +typedef void T; + + +EXPECT FAILURE "typedef.tests 7": +exception E {}; +typedef E T; + + +EXPECT FAILURE "typdef.tests 8": +constants C {}; +typedef C T; diff --git a/idlc/test/service.idl b/idlc/test/service.idl new file mode 100644 index 000000000..79107f933 --- /dev/null +++ b/idlc/test/service.idl @@ -0,0 +1,64 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <interface.idl> + +module idlc +{ +module test +{ + +exception bla +{ +}; + +service IdlTest +{ +// [property] bla p0; + [property] short p1; + [optional, property] unsigned short p2; + + [maybevoid, property] long p3; + [bound, property] unsigned long p4; + + [constrained, property] hyper p5; + [transient, property] unsigned hyper p6; + + [maybeambiguous, property] string p7; + [maybedefault, property] type p8; + [removable, property] any p9; + + [readonly, optional, removable, property] ::idlc::test::BaseStruct p10; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +service BetterIdlTest +{ + service IdlTest; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/singleton.idl b/idlc/test/singleton.idl new file mode 100644 index 000000000..e69e2900f --- /dev/null +++ b/idlc/test/singleton.idl @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <interface.idl> + +module idlc +{ +module test +{ + +exception bla +{ +}; + +service IdlTest +{ +// [property] bla p0; + [property] short p1; + [optional, property] unsigned short p2; + + [maybevoid, property] long p3; + [bound, property] unsigned long p4; + + [constrained, property] hyper p5; + [transient, property] unsigned hyper p6; + + [maybeambiguous, property] string p7; + [maybedefault, property] type p8; + [removable, property] any p9; + + [readonly, optional, removable, property] ::idlc::test::BaseStruct p10; + + interface XTestBaseTypes; + [optional] interface ::idlc::test::XTestComplexTypes; +}; + +singleton SingletonTest +{ + service IdlTest; +}; + +}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/struct.idl b/idlc/test/struct.idl new file mode 100644 index 000000000..133471d2e --- /dev/null +++ b/idlc/test/struct.idl @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/* In this file the idl struct will be tested. + bla + */ + +/// idlc defines a test module +module idlc +{ + +/// test defines a test module +module test +{ + +typedef sequence< long > Id; +//struct Bla +//{ +// long bla; +//}; + +/** bla + BaseStruct defines an * initial struct + */ +struct BaseStruct +{ + Id Id; + + /// a short member + short m1; + + /// an unsigned short member + unsigned short m2; + + /// a long member + long m3; + + /// an unsigned long member + unsigned long m4; + + /// a hyper member + hyper m5; + + /// an unsigned hyper member + unsigned hyper m6; + + /// a string member + string m7; + + /// a byte member + byte m8; + + /// a type member + type m9; + + /// a float member + float m10; + + /// a double member + double m11; + + /// a char member + char m12; + + /// a boolean member + boolean m13; + + /// an any member + any m14; +}; + +interface XTestBaseTypes; + +typedef sequence< long > LongSeq; + +typedef sequence< LongSeq > LongSeqSeq; + +/** TestStruct deinfes a struct which inherits + from the base strcut type BaseStruct. +*/ +struct TestStruct : BaseStruct +{ + /// a sequence< long > member + sequence< long > ms1; + + /// a sequence< sequence< long > > member + sequence< sequence< long > > ms2; + + /// an interface member + XTestBaseTypes ms5; + + /// a typedef member + LongSeq ms6; + + /// a further typedef member + LongSeqSeq ms7; + + /// a sequence typedef member + sequence<LongSeq> ms8; + +}; + +}; }; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/idlc/test/typelookup.idl b/idlc/test/typelookup.idl new file mode 100644 index 000000000..a9b5612ef --- /dev/null +++ b/idlc/test/typelookup.idl @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +/* In this file the idl struct will be tested. + bla + */ + +#include <enum.idl> + +typedef short Error; + +/// idlc defines a test module +module idlc +{ + +typedef long Error; + +/// test defines a test module +module test +{ + +/** bla + BaseStruct defines an * initial struct + */ +struct BaseStruct +{ + /// a long member + long m1; + /// a string member + string m2; + /// a byte member + byte m3; + /// a type member + type m4; + /// an enum member, Error in module idlc::test + Error m5; + /// a typedef member, global Error (typedef short) + ::Error m6; + /// a typedef member, Error in module idlc (typedef long) + ::idlc::Error m7; + /// a typedef member, Error in module idlc (typedef long) + idlc::Error m8; + /// an enum member, Error in module idlc::test + test::Error m9; +}; + +/** TestStruct deinfes a struct which inherits + from the base strcut type BaseStruct. +*/ +struct TestStruct : BaseStruct +{ + /// a short member + short ms1; + /// a hyper member + hyper ms2; + /// a sequence<long> member + sequence< long > ms3; +}; + +}; // test + +}; // idlc + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |