From ed5640d8b587fbcfed7dd7967f3de04b37a76f26 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:06:44 +0200 Subject: Adding upstream version 4:7.4.7. Signed-off-by: Daniel Baumann --- idlc/CustomTarget_parser_test.mk | 91 + idlc/Executable_idlc.mk | 81 + idlc/Makefile | 14 + idlc/Module_idlc.mk | 25 + idlc/README.md | 7 + idlc/inc/astattribute.hxx | 107 ++ idlc/inc/astbasetype.hxx | 50 + idlc/inc/astconstant.hxx | 50 + idlc/inc/astconstants.hxx | 35 + idlc/inc/astdeclaration.hxx | 136 ++ idlc/inc/astenum.hxx | 45 + idlc/inc/astexception.hxx | 35 + idlc/inc/astexpression.hxx | 139 ++ idlc/inc/astinterface.hxx | 129 ++ idlc/inc/astinterfacemember.hxx | 45 + idlc/inc/astmember.hxx | 48 + idlc/inc/astmodule.hxx | 44 + idlc/inc/astneeds.hxx | 41 + idlc/inc/astobserves.hxx | 41 + idlc/inc/astoperation.hxx | 54 + idlc/inc/astparameter.hxx | 46 + idlc/inc/astscope.hxx | 73 + idlc/inc/astsequence.hxx | 49 + idlc/inc/astservice.hxx | 61 + idlc/inc/astservicemember.hxx | 45 + idlc/inc/aststack.hxx | 46 + idlc/inc/aststruct.hxx | 62 + idlc/inc/aststructinstance.hxx | 49 + idlc/inc/asttype.hxx | 37 + idlc/inc/asttypedef.hxx | 44 + idlc/inc/errorhandler.hxx | 118 ++ idlc/inc/fehelper.hxx | 70 + idlc/inc/idlc.hxx | 164 ++ idlc/inc/idlctypes.hxx | 189 ++ idlc/inc/inheritedinterface.hxx | 56 + idlc/inc/options.hxx | 76 + idlc/source/astconstant.cxx | 123 ++ idlc/source/astdeclaration.cxx | 164 ++ idlc/source/astdump.cxx | 420 ++++ idlc/source/astenum.cxx | 105 + idlc/source/astexpression.cxx | 1327 +++++++++++++ idlc/source/astinterface.cxx | 399 ++++ idlc/source/astoperation.cxx | 115 ++ idlc/source/astscope.cxx | 314 +++ idlc/source/astservice.cxx | 54 + idlc/source/aststack.cxx | 79 + idlc/source/aststruct.cxx | 167 ++ idlc/source/aststructinstance.cxx | 63 + idlc/source/attributeexceptions.hxx | 38 + idlc/source/errorhandler.cxx | 583 ++++++ idlc/source/fehelper.cxx | 102 + idlc/source/idlc.cxx | 400 ++++ idlc/source/idlccompile.cxx | 394 ++++ idlc/source/idlcmain.cxx | 164 ++ idlc/source/idlcproduce.cxx | 242 +++ idlc/source/options.cxx | 424 +++++ idlc/source/parser.y | 2737 +++++++++++++++++++++++++++ idlc/source/scanner.l | 526 +++++ idlc/test/const.idl | 71 + idlc/test/enum.idl | 45 + idlc/test/exception.idl | 40 + idlc/test/identifiers.idl | 43 + idlc/test/interface.idl | 71 + idlc/test/parser/attribute.tests | 232 +++ idlc/test/parser/constant.tests | 294 +++ idlc/test/parser/constructor.tests | 190 ++ idlc/test/parser/conversion.tests | 79 + idlc/test/parser/interfaceinheritance.tests | 279 +++ idlc/test/parser/methodoverload.tests | 177 ++ idlc/test/parser/oldstyle.tests | 28 + idlc/test/parser/polystruct.tests | 251 +++ idlc/test/parser/published.tests | 681 +++++++ idlc/test/parser/struct.tests | 46 + idlc/test/parser/typedef.tests | 63 + idlc/test/service.idl | 64 + idlc/test/singleton.idl | 61 + idlc/test/struct.idl | 121 ++ idlc/test/typelookup.idl | 80 + 78 files changed, 14258 insertions(+) create mode 100644 idlc/CustomTarget_parser_test.mk create mode 100644 idlc/Executable_idlc.mk create mode 100644 idlc/Makefile create mode 100644 idlc/Module_idlc.mk create mode 100644 idlc/README.md create mode 100644 idlc/inc/astattribute.hxx create mode 100644 idlc/inc/astbasetype.hxx create mode 100644 idlc/inc/astconstant.hxx create mode 100644 idlc/inc/astconstants.hxx create mode 100644 idlc/inc/astdeclaration.hxx create mode 100644 idlc/inc/astenum.hxx create mode 100644 idlc/inc/astexception.hxx create mode 100644 idlc/inc/astexpression.hxx create mode 100644 idlc/inc/astinterface.hxx create mode 100644 idlc/inc/astinterfacemember.hxx create mode 100644 idlc/inc/astmember.hxx create mode 100644 idlc/inc/astmodule.hxx create mode 100644 idlc/inc/astneeds.hxx create mode 100644 idlc/inc/astobserves.hxx create mode 100644 idlc/inc/astoperation.hxx create mode 100644 idlc/inc/astparameter.hxx create mode 100644 idlc/inc/astscope.hxx create mode 100644 idlc/inc/astsequence.hxx create mode 100644 idlc/inc/astservice.hxx create mode 100644 idlc/inc/astservicemember.hxx create mode 100644 idlc/inc/aststack.hxx create mode 100644 idlc/inc/aststruct.hxx create mode 100644 idlc/inc/aststructinstance.hxx create mode 100644 idlc/inc/asttype.hxx create mode 100644 idlc/inc/asttypedef.hxx create mode 100644 idlc/inc/errorhandler.hxx create mode 100644 idlc/inc/fehelper.hxx create mode 100644 idlc/inc/idlc.hxx create mode 100644 idlc/inc/idlctypes.hxx create mode 100644 idlc/inc/inheritedinterface.hxx create mode 100644 idlc/inc/options.hxx create mode 100644 idlc/source/astconstant.cxx create mode 100644 idlc/source/astdeclaration.cxx create mode 100644 idlc/source/astdump.cxx create mode 100644 idlc/source/astenum.cxx create mode 100644 idlc/source/astexpression.cxx create mode 100644 idlc/source/astinterface.cxx create mode 100644 idlc/source/astoperation.cxx create mode 100644 idlc/source/astscope.cxx create mode 100644 idlc/source/astservice.cxx create mode 100644 idlc/source/aststack.cxx create mode 100644 idlc/source/aststruct.cxx create mode 100644 idlc/source/aststructinstance.cxx create mode 100644 idlc/source/attributeexceptions.hxx create mode 100644 idlc/source/errorhandler.cxx create mode 100644 idlc/source/fehelper.cxx create mode 100644 idlc/source/idlc.cxx create mode 100644 idlc/source/idlccompile.cxx create mode 100644 idlc/source/idlcmain.cxx create mode 100644 idlc/source/idlcproduce.cxx create mode 100644 idlc/source/options.cxx create mode 100644 idlc/source/parser.y create mode 100644 idlc/source/scanner.l create mode 100644 idlc/test/const.idl create mode 100644 idlc/test/enum.idl create mode 100644 idlc/test/exception.idl create mode 100644 idlc/test/identifiers.idl create mode 100644 idlc/test/interface.idl create mode 100644 idlc/test/parser/attribute.tests create mode 100644 idlc/test/parser/constant.tests create mode 100644 idlc/test/parser/constructor.tests create mode 100644 idlc/test/parser/conversion.tests create mode 100644 idlc/test/parser/interfaceinheritance.tests create mode 100644 idlc/test/parser/methodoverload.tests create mode 100644 idlc/test/parser/oldstyle.tests create mode 100644 idlc/test/parser/polystruct.tests create mode 100644 idlc/test/parser/published.tests create mode 100644 idlc/test/parser/struct.tests create mode 100644 idlc/test/parser/typedef.tests create mode 100644 idlc/test/service.idl create mode 100644 idlc/test/singleton.idl create mode 100644 idlc/test/struct.idl create mode 100644 idlc/test/typelookup.idl (limited to 'idlc') 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 +#include + +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 + +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 + +#include + +#include "idlc.hxx" +#include + +// 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 eval_bin_op(); + std::unique_ptr eval_bit_op(); + std::unique_ptr eval_un_op(); + std::unique_ptr eval_symbol(); + + ExprComb m_combOperator; + std::unique_ptr + m_subExpr1; + std::unique_ptr + m_subExpr2; + std::unique_ptr + m_exprValue; + std::optional + 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 +#include + +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 + +#include +#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(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 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 +#include + +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 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 + +#include + +#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> 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 + +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 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 +#include + +#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 m_pScopes; + std::unique_ptr 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 + +#include +#include +#include +#include +#include + +#include +#include + + +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 +#include + +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 + +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 +#include + +#include + +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 +#include +#include +#include +#include + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +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(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(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(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(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(*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(*i)->dumpBlob(writer, constructorIndex++); + break; + + case NT_property: + static_cast(*i)->dumpBlob(writer, propertyIndex++, nullptr); + break; + + case NT_interface_member: + { + AstInterfaceMember * decl = static_cast(*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(*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(*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(*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 + +#include + +#include + +#include +#include + +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(pDecl)->getConstValue()->compareLong(pExpr); }); + + if (iter != end) + return static_cast(*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(pDecl)->dumpBlob(aBlob, index++, false); + + ++iter; + } + + sal_uInt32 aBlobSize; + void const * pBlob = aBlob.getBlob(&aBlobSize); + + if (localKey.setValue("", RegValueType::BINARY, + const_cast(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 +#include +#include +#include + +#include +#include + +#include +#include +#include + +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(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(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(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(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(ev->u.uhval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_boolean: + { + auto tmp = static_cast(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(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(ev->u.dval); + ev->u.sval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(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(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(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(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(ev->u.uhval); + ev->u.usval = tmp; + ev->et = ET_ushort; + return true; + } + case ET_boolean: + { + auto tmp = static_cast(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(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(ev->u.dval); + ev->u.usval = tmp; + ev->et = ET_short; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(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(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(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(ev->u.uhval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast(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(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(ev->u.dval); + ev->u.lval = tmp; + ev->et = ET_long; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(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(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(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(ev->u.uhval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_boolean: + { + auto tmp = static_cast(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(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(ev->u.dval); + ev->u.ulval = tmp; + ev->et = ET_ulong; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(ev->u.usval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_long: + { + auto tmp = static_cast(ev->u.lval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast(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(ev->u.uhval); + ev->u.hval = tmp; + ev->et = ET_long; + return true; + } + case ET_boolean: + { + auto tmp = static_cast(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(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(ev->u.dval); + ev->u.hval = tmp; + ev->et = ET_hyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(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(ev->u.lval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_ulong: + { + auto tmp = static_cast(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(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(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(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(ev->u.dval); + ev->u.uhval = tmp; + ev->et = ET_uhyper; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(ev->u.usval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_long: + { + auto tmp = static_cast(ev->u.lval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_ulong: + { + auto tmp = static_cast(ev->u.ulval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_hyper: + { + auto tmp = static_cast(ev->u.hval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_uhyper: + { + if (static_cast(ev->u.ulval) > FLT_MAX) + return false; + auto tmp = static_cast(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(ev->u.dval) > FLT_MAX + || static_cast(ev->u.dval) < -FLT_MAX) + return false; + auto tmp = static_cast(ev->u.dval); + ev->u.fval = tmp; + ev->et = ET_float; + return true; + } + case ET_byte: + { + auto tmp = static_cast(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(ev->u.sval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ushort: + { + auto tmp = static_cast(ev->u.usval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_long: + { + auto tmp = static_cast(ev->u.lval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_ulong: + { + auto tmp = static_cast(ev->u.ulval); + ev->u.dval = tmp; + ev->et = ET_double; + return true; + } + case ET_hyper: + { + auto tmp = static_cast(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(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(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(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(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(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(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(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(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(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(static_cast(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(static_cast(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 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 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 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 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 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 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 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(pDecl); + pConst->getConstValue()->evaluate(); + auto const val = pConst->getConstValue()->getExprValue(); + return val == nullptr ? nullptr : std::make_unique(*val); +} + +OString AstExpression::toString() +{ + OString exprStr; + if (m_combOperator == ExprComb::Symbol) + return m_xSymbolicName ? *m_xSymbolicName : OString(""); + + 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 +#include +#include +#include + +#include +#include + +#include + +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(*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(*i)->dumpBlob( + aBlob, attributeIndex++, &methodIndex); + break; + + case NT_operation: + static_cast(*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(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 +#include +#include +#include +#include + +#include + +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(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(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 + +#include +#include + +#include +#include +#include +#include +#include +#include + + +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(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(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(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(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 + +#include +#include +#include +#include + +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 +#include +#include + +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 +#include + +#include +#include + +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(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(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 + +#include +#include + +#include +#include + +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 + +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 +#include + +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(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 +#include +#include + +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(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +AstDeclaration* scopeAsDecl(AstScope* pScope) +{ + if (pScope == nullptr) return nullptr; + + switch( pScope->getScopeNodeType() ) + { + case NT_service: + case NT_singleton: + return static_cast(pScope); + case NT_module: + case NT_root: + return static_cast(pScope); + case NT_constants: + return static_cast(pScope); + case NT_interface: + return static_cast(pScope); + case NT_operation: + return static_cast(pScope); + case NT_exception: + return static_cast(pScope); + case NT_struct: + return static_cast(pScope); + case NT_enum: + return static_cast(pScope); + default: + return nullptr; + } +} + +AstScope* declAsScope(AstDeclaration* pDecl) +{ + if (pDecl == nullptr) return nullptr; + + switch(pDecl->getNodeType()) + { + case NT_interface: + return static_cast(pDecl); + case NT_service: + case NT_singleton: + return static_cast(pDecl); + case NT_module: + case NT_root: + return static_cast(pDecl); + case NT_constants: + return static_cast(pDecl); + case NT_exception: + return static_cast(pDecl); + case NT_struct: + return static_cast(pDecl); + case NT_enum: + return static_cast(pDecl); + case NT_operation: + return static_cast(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(pRoot->lookupPrimitiveType(ET_any)), + "queryInterface", pInterface); + AstParameter* pParam = new AstParameter(DIR_IN, false, + static_cast(pRoot->lookupPrimitiveType(ET_type)), + "aType", pOp); + pOp->addDeclaration(pParam); + pInterface->addMember(pOp); + + // define XInterface::acquire + pOp = new AstOperation(static_cast(pRoot->lookupPrimitiveType(ET_void)), + "acquire", pInterface); + pInterface->addMember(pOp); + + // define XInterface::release + pOp = new AstOperation(static_cast(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(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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#endif + +#ifdef SAL_UNX +#include +#include +#include +#endif + +#include + +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 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 +#include + +#include + +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(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 +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#include +#include +#include +#endif + +#ifdef SAL_UNX +#include +#include +#include +#endif + +#include + +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 + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include + +#ifdef _WIN32 +# if !defined WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# endif +# include +#endif + +#include +#include + + +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) + { + // "@" + result = Options::checkCommandFile (rArgs, &(arg[1])); + } + break; + case '-': + result = len > 1; + if (result) + { + // "-