diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..166c120 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 2.6) + +project(tars2node) + +set(CMAKE_VERBOSE_MAKEFILE off) + +# version +set(TARS_VERSION "1.1.0") +set(PARSER_VERSION "${TARS_VERSION}") +set(GENERATOR_VERSION "20180713") + +# namespace +set(IDL_NAMESPACE Tars) +string(TOLOWER ${IDL_NAMESPACE} TC_NAMESPACE) +set(GRAMMAR_NAME Grammar) + +# idl +set(RPC_MODULE_PATH "@tars/rpc") +set(STREAM_MODULE_PATH "@tars/stream") +set(IDL_TYPE "Tars") +set(PROTOCOL_NAME "Tup") + +# flag +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -g -O2 -Wall -Wno-sign-compare -Wno-unused-result") +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O2 -Wall") + +# define +add_definitions(-DTARS_VERSION="${TARS_VERSION}") +add_definitions(-DPARSER_VERSION="${PARSER_VERSION}") +add_definitions(-DGENERATOR_VERSION="${GENERATOR_VERSION}") +add_definitions(-DTC_NAMESPACE=${TC_NAMESPACE}) +add_definitions(-DIDL_NAMESPACE=${IDL_NAMESPACE}) +add_definitions(-DGRAMMAR_NAME=${GRAMMAR_NAME}) +add_definitions(-DRPC_MODULE_PATH="${RPC_MODULE_PATH}") +add_definitions(-DSTREAM_MODULE_PATH="${STREAM_MODULE_PATH}") +add_definitions(-DEXECUTE_FILENAME="${PROJECT_NAME}") +add_definitions(-DIDL_TYPE="${IDL_TYPE}") +add_definitions(-DPROTOCOL_NAME="${PROTOCOL_NAME}") + +# include +include_directories(${PROJECT_SOURCE_DIR}/third_partly/dirent/include) +include_directories(${PROJECT_SOURCE_DIR}/third_partly/tarsgrammar) +include_directories(${PROJECT_SOURCE_DIR}/third_partly/tarsparse) +include_directories(${PROJECT_SOURCE_DIR}/third_partly/util/include) +include_directories(${PROJECT_SOURCE_DIR}/include) + +# source +aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/tarsgrammar DIR_SRCS) +aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/tarsparse DIR_SRCS) +aux_source_directory(${PROJECT_SOURCE_DIR}/third_partly/util/src DIR_SRCS) +aux_source_directory(${PROJECT_SOURCE_DIR}/src DIR_SRCS) +add_executable(${PROJECT_NAME} ${DIR_SRCS}) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1129a5 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Tars2Node + +`tars2node` 可以将 Tars IDL 定义文件转换为 JavaScript 语言所使用的版本,结合 [@tars/stream](https://www.npmjs.com/package/@tars/stream) 模块执行编解码操作。 + +如您有 Tars RPC 需求可结合 [@tars/rpc](https://www.npmjs.com/package/@tars/rpc) 模块进行调用。 + +## 用法 + +直接使用 build 目录中的 `tars2node` 预编译程序即可(Linux 平台)。 + +```bash +tars2node [OPTIONS] tarsfile +``` + +## 选项 + +> Options: + +> --version print tars2node version +> --rpc-path=[DIRECTORY] specify the path of rpc module. +> --stream-path=[DIRECTORY[] specify the path of stream module. +> --allow-reserved-namespace allow you to use reserved word as a namespace. +> --dir=DIRECTORY generate source file to DIRECTORY. +> --relative use current path. +> --tarsBase=DIRECTORY where to search tars files. +> --r generate source all tars files. +> --r-minimal minimize the dependent members. +> --r-reserved list of names(split by ",") that should be keeped. +> --client just for client side source file. +> --server just for server side source file. +> --dts generate d.ts file. +> --use-string-represent use string represent long type. +> --string-binary-encoding get string raw bytes . +> --optimize=[0|s] support "s" to reduce code size, default is 0. + +## 从源码编译 + +1. 安装对应平台的 build-essential +2. 安装 [CMake](https://cmake.org/) +3. 在源码 build 目录下执行 `cmake ../ && make` \ No newline at end of file diff --git a/build/tars2node b/build/tars2node new file mode 100755 index 0000000..a5b77f5 Binary files /dev/null and b/build/tars2node differ diff --git a/include/code_generator.h b/include/code_generator.h new file mode 100644 index 0000000..c2c0de8 --- /dev/null +++ b/include/code_generator.h @@ -0,0 +1,273 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef _CODEGENERATOR_H +#define _CODEGENERATOR_H + +#include "parse.h" +#include "util/tc_file.h" +#include "util/tc_encoder.h" +#include + +#ifndef TAB + #define TAB g_parse->getTab() +#endif + +#ifndef INC_TAB + #define INC_TAB g_parse->incTab() +#endif + +#ifndef DEL_TAB + #define DEL_TAB g_parse->delTab() +#endif + +#define TO_LOWER_STRING(str) TC_Common::lower(str) + +#define DEFINE_STRING(str) string(CSTR(str)) +#define CSTR(str) #str +#define IDL_NAMESPACE_STR DEFINE_STRING(IDL_NAMESPACE) + +#define GET_CONST_GRAMMAR_PTR_V(name, ptr) \ + ptr->getConst##name##Ptr() +#define GET_CONST_GRAMMAR_PTR_BASE(name, ptr) \ + GET_CONST_GRAMMAR_PTR_V(name, ptr) +#define GET_CONST_GRAMMAR_PTR(ptr) \ + GET_CONST_GRAMMAR_PTR_BASE(GRAMMAR_NAME, ptr) + +#define CONST_GRAMMAR_V(name, val) \ + Const##name::val +#define CONST_GRAMMAR_BASE(name, val) \ + CONST_GRAMMAR_V(name, val) +#define CONST_GRAMMAR(val) \ + CONST_GRAMMAR_BASE(GRAMMAR_NAME, val) + +#define PROTOCOL_V(space, protocol, type) \ + space + "Stream." + protocol + "." + TC_Common::upper(protocol) + "_" + type +#define PROTOCOL_SIMPLE PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "SIMPLE") +#define PROTOCOL_COMPLEX PROTOCOL_V(IDL_NAMESPACE_STR, PROTOCOL_NAME, "COMPLEX") +#define PROTOCOL_VAR TO_LOWER_STRING(PROTOCOL_NAME) + +using namespace TC_NAMESPACE; + +class CodeGenerator +{ +public: + CodeGenerator() + : uiNameIndex(0), + _sRpcPath(RPC_MODULE_PATH), + _sStreamPath(STREAM_MODULE_PATH), + _sToPath("./"), + _bClient(false), + _bServer(false), + _bRecursive(false), + _bUseSpecialPath(false), + _bUseStringRepresent(false), + _bStringBinaryEncoding(false), + _bMinimalMembers(false), + _bDTS(false), + _iOptimizeLevel(O0) {} + + void createFile(const string& file, const bool bEntry = true); + + void setRpcPath(const string& sPath) { _sRpcPath = sPath; } + + void setStreamPath(const string& sPath) { _sStreamPath = sPath; } + + void setEnableClient(bool bEnable) { _bClient = bEnable; } + + void setEnableServer(bool bEnable) { _bServer = bEnable; } + + void setTargetPath(const string& sPath) { _sToPath = sPath + "/"; } + + void setRecursive(bool bEnable) { _bRecursive = bEnable; } + + void setUseSpecialPath(bool bEnable) { _bUseSpecialPath = bEnable; } + + void setUseStringRepresent(bool bEnable) { _bUseStringRepresent = bEnable; } + + void setStringBinaryEncoding(bool bEnable) { _bStringBinaryEncoding = bEnable; } + + void setMinimalMembers(bool bEnable) { _bMinimalMembers = bEnable; } + + void setDependent(set& deps) { _depMembers = deps; } + + void setEnableDTS(bool bEnable) { _bDTS = bEnable; } + + void setOptimize(int iLevel) { _iOptimizeLevel = iLevel; } + + enum OPTIMIZE_LEVEL {O0 = 0, Os}; + +private: + struct ImportFileType + { + enum TYPE_T {EN_ENUM = 10000, EN_ENUM_VALUE, EN_STRUCT}; + int iType; + string sNamespace; + string sTypeName; + string sName; + }; + + struct ImportFile + { + string sFile; + string sModule; + map mapVars; + }; + + uint32_t uiNameIndex; + + map _mapFiles; + + set _depMembers; + + void scan(const string & sFile, bool bNotPrefix); + + string makeName(); + + string findName(const string & sNamespace, const string & sName); + +private: + string toFunctionName(const TypeIdPtr & pPtr, const string &sAction); + + string getDataType(const TypePtr& pPtr); + + string getClassName(const TypePtr& pPtr); + + string getDtsType(const TypePtr &pPtr, const bool bStream = true); + + string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace); + + string getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string & sNamespace, const bool bGlobal); + +private: + string generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert); + + string generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); + + string generateJS(const EnumPtr &pPtr, const string &sNamespace); + + string generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert); + + bool generateJS(const ContextPtr &pPtr); + +private: + string generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream); + + string generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + string generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + bool generateJSProxy(const ContextPtr &pPtr); + +private: + string generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert); + + string generatePing(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + string generateAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateJSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateJSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr); + + bool generateJSServer(const ContextPtr &pPtr); + +private: + string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr); + + string generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + string generateJSServerImp(const ContextPtr &cPtr, const NamespacePtr &nPtr); + + void generateJSServerImp(const ContextPtr &cPtr); + +private: + string generateDTS(const StructPtr &pPtr, const string &sNamespace); + + string generateDTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream); + + string generateDTS(const EnumPtr &pPtr, const string &sNamespace); + + string generateDTS(const NamespacePtr &pPtr, bool &bNeedStream); + + string generateDTS(const NamespacePtr &pPtr, const string &sContent); + + void generateDTS(const ContextPtr &cPtr); + +private: + string generateDTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc); + + string generateDTSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr); + + void generateDTSServer(const ContextPtr &cPtr); + +private: + string generateDTSProxyInfo(); + + string generateDTSProxy(const InterfacePtr &pPtr); + + string generateDTSProxy(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc); + + void generateDTSProxy(const ContextPtr &pPtr); + +private: + void makeUTF8File(const string & sFileName, const string & sFileContent); + + bool isSimple(const TypePtr & pPtr) const; + + bool isBinBuffer(const TypePtr & pPtr) const; + + bool isRawOrString(const TypePtr & pPtr) const; + + bool isDependent(const string & sNamespace, const string & sName) const; + + string getRealFileInfo(const string & sPath); + + string printHeaderRemark(const string & sTypeName); + +private: + string _sRpcPath; + + string _sStreamPath; + + string _sToPath; + + bool _bClient; + + bool _bServer; + + bool _bRecursive; + + bool _bUseSpecialPath; + + bool _bUseStringRepresent; + + bool _bStringBinaryEncoding; + + bool _bMinimalMembers; + + bool _bEntry; + + string _sIdlFile; + + bool _bDTS; + + int _iOptimizeLevel; +}; + +#endif \ No newline at end of file diff --git a/src/code_generator.cpp b/src/code_generator.cpp new file mode 100644 index 0000000..67578f8 --- /dev/null +++ b/src/code_generator.cpp @@ -0,0 +1,90 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::printHeaderRemark(const string &sTypeName) +{ + ostringstream s; + s << "// **********************************************************************" << endl; + s << "// Parsed By " << IDL_NAMESPACE_STR << "Parser(" << PARSER_VERSION << "), Generated By " << EXECUTE_FILENAME << "(" << GENERATOR_VERSION << ")" << endl; + s << "// " << IDL_NAMESPACE_STR << "Parser Maintained By <" << TC_Common::upper(IDL_NAMESPACE_STR) << "> and " << EXECUTE_FILENAME << " Maintained By " << endl; + s << "// Generated from \"" << TC_File::extractFileName(_sIdlFile) << "\" by " << + (_bEntry ? sTypeName : (_bMinimalMembers ? "Minimal" : "Relation")) << " Mode" << endl; + s << "// **********************************************************************" << endl; + s << endl; + + s << "/* eslint-disable */" << endl; + s << endl; + + return s.str(); +} + +void CodeGenerator::createFile(const string &file, const bool bEntry) +{ + _sIdlFile = getRealFileInfo(file); + _bEntry = bEntry; + + g_parse->parse(_sIdlFile); + + vector contexts = g_parse->getContexts(); + + for(size_t i = 0; i < contexts.size(); i++) + { + if (_sIdlFile == contexts[i]->getFileName()) + { + scan(_sIdlFile, true); //分析枚举值、结构体所在的文件 + + if (!_bClient && !_bServer) + { + generateJS(contexts[i]); //生成当前文件的编解码文件 + if(_bDTS) generateDTS(contexts[i]); //生成 typescript 描述文件 + } + + if (_bClient) + { + if(!generateJSProxy(contexts[i])) return; //生成当前文件的客户端代理类文件 + if(_bDTS) generateDTSProxy(contexts[i]); //生成客户端 typescript 描述文件 + } + + if (_bServer) + { + if(!generateJSServer(contexts[i])) return; //生成当前文件的服务端代理类文件 + if(_bDTS) generateDTSServer(contexts[i]); //生成服务端 typescript 描述文件 + + generateJSServerImp(contexts[i]); //生成当前文件的服务端实现类文件 + } + + vector files = contexts[i]->getIncludes(); + for (size_t ii = 0; _bRecursive && ii < files.size(); ii++) + { + CodeGenerator node; + node.setRpcPath(_sRpcPath); + node.setStreamPath(_sStreamPath); + node.setTargetPath(_sToPath); + node.setRecursive(_bRecursive); + node.setUseSpecialPath(_bUseSpecialPath); + node.setUseStringRepresent(_bUseStringRepresent); + node.setStringBinaryEncoding(_bStringBinaryEncoding); + node.setMinimalMembers(_bMinimalMembers); + node.setDependent(_depMembers); + node.setEnableDTS(_bDTS); + + node.createFile(files[ii], false); + } + } + } +} \ No newline at end of file diff --git a/src/file_util.cpp b/src/file_util.cpp new file mode 100644 index 0000000..ecddb92 --- /dev/null +++ b/src/file_util.cpp @@ -0,0 +1,38 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +void CodeGenerator::makeUTF8File(const string& sFileName, const string& sFileContent) +{ + try { + char header[3] = {(char)(0xef), (char)(0xbb), (char)(0xbf)}; + + string sData(header, 3); + + sData += TC_Encoder::gbk2utf8(sFileContent); + + TC_File::save2file(sFileName, sData.c_str()); + } catch (...) { + cout << "Convert GBK to UTF8 failed, current encoding is GBK."; + TC_File::save2file(sFileName, sFileContent.c_str()); + } +} + +string CodeGenerator::getRealFileInfo(const string& sPath) +{ + return TC_File::extractFilePath(sPath) + TC_File::excludeFileExt(TC_File::extractFileName(sPath)) + "." + TC_Common::lower(IDL_TYPE); +} \ No newline at end of file diff --git a/src/gen_js.cpp b/src/gen_js.cpp new file mode 100644 index 0000000..21fc0a6 --- /dev/null +++ b/src/gen_js.cpp @@ -0,0 +1,398 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generateJS(const EnumPtr &pPtr, const string &sNamespace) +{ + ostringstream s; + s << TAB << sNamespace << "." << pPtr->getId() << " = {" << endl; + INC_TAB; + + //成员变量 + int nenum = -1; + bool bDependent = false; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); + + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + + s << TAB << "\"" << member[i]->getId() << "\" : " << TC_Common::tostr(nenum) << "," << endl; + } + s << TAB << "\"_classname\" : \"" << sNamespace << "." << pPtr->getId() << "\"" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //函数 + s << TAB << sNamespace << "." << pPtr->getId() << "._write = function(os, tag, val) { return os.writeInt32(tag, val); };" << endl; + s << TAB << sNamespace << "." << pPtr->getId() << "._read = function(is, tag, def) { return is.readInt32(tag, true, def); };" << endl; + + if (!_bMinimalMembers || _bEntry || bDependent || isDependent(sNamespace, pPtr->getId())) { + return s.str(); + } else { + return ""; + } +} + +string CodeGenerator::generateJS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getTypeIdPtr()->getId())) + { + return ""; + } + + ostringstream s; + + if (_bStringBinaryEncoding && GET_CONST_GRAMMAR_PTR(pPtr)->t == CONST_GRAMMAR(STRING)) + { + bNeedStream = true; + } + + s << TAB << sNamespace << "." << pPtr->getTypeIdPtr()->getId() << " = " << getDefault(pPtr->getTypeIdPtr(), GET_CONST_GRAMMAR_PTR(pPtr)->v, sNamespace, false) << ";" << endl; + + return s.str(); +} + +string CodeGenerator::generateJS(const StructPtr & pPtr, const string &sNamespace, bool &bNeedAssert) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId())) + { + return ""; + } + + ostringstream s; + vector& member = pPtr->getAllMemberPtr(); + + s << TAB << sNamespace << "." << pPtr->getId() << " = function() {"<< endl; + + INC_TAB; + + for (size_t i = 0; i < member.size(); i++) + { + s << TAB << "this." << member[i]->getId() << " = " << getDefault(member[i], member[i]->def(), sNamespace) << ";" << endl; + } + + { + s << TAB << "this._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; + } + + DEL_TAB; + + s << TAB << "};" << endl; + s << TAB << sNamespace << "." << pPtr->getId() << "._classname = \"" << sNamespace << "." << pPtr->getId() << "\";" << endl; + + string sProto = TC_Common::replace(pPtr->getSid(), "::", "."); + s << TAB << sProto << "._write = function (os, tag, value) { os.writeStruct(tag, value); };" << endl; + s << TAB << sProto << "._read = function (is, tag, def) { return is.readStruct(tag, true, def); };" << endl; + + //_readFrom + s << TAB << sNamespace << "." << pPtr->getId() << "._readFrom = function (is) {" << endl; + INC_TAB; + s << TAB << "var tmp = new " << sNamespace << "." << pPtr->getId() << ";" << endl; + for (size_t i = 0; i < member.size(); i++) + { + string sFuncName = toFunctionName(member[i], "read"); + s << TAB << "tmp." << member[i]->getId() << " = is." << sFuncName << "(" << member[i]->getTag() + << ", " << (member[i]->isRequire()?"true":"false") << ", "; + + if (isSimple(member[i]->getTypePtr())) + { + s << getDefault(member[i], member[i]->def(), sNamespace) + << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : ""); + } + else + { + s << getDataType(member[i]->getTypePtr()); + } + + s << ");" << endl; + } + s << TAB << "return tmp;" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //_writeTo + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._writeTo = function (os) {" << endl; + + INC_TAB; + for (size_t i = 0; i < member.size(); i++) + { + string sFuncName = toFunctionName(member[i], "write"); + + s << TAB << "os." << sFuncName << "(" << member[i]->getTag() << ", this." << member[i]->getId() + << (isRawOrString(member[i]->getTypePtr()) ? ", 1" : "") << ");" << endl; + } + DEL_TAB; + s << TAB << "};" << endl; + + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel == Os) + { + return s.str(); + } + + //_equal + vector key = pPtr->getKey(); + + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._equal = function (" << (key.size() > 0 ? "anItem" : "") << ") {" << endl; + + INC_TAB; + + if (key.size() > 0) + { + s << TAB << "return "; + + for (size_t i = 0; i < key.size(); i++) + { + for (size_t ii =0; ii < member.size(); ii++) + { + if (key[i] != member[ii]->getId()) + { + continue; + } + + if (isSimple(member[i]->getTypePtr())) + { + s << (i==0?"":TAB + TAB) << "this." << key[i] << " === " << "anItem." << key[i]; + } + else + { + s << (i==0?"":TAB + TAB) << "this._equal(" << "anItem)"; + } + } + + if (i != key.size() - 1) + { + s << " && " << endl; + } + } + + s << ";" << endl; + + } + else + { + bNeedAssert = true; + s << TAB << "assert.fail(\"this structure not define key operation\");" << endl; + } + + DEL_TAB; + s << TAB << "};" << endl; + + //_genKey + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype._genKey = function () {" << endl; + INC_TAB; + s << TAB << "if (!this._proto_struct_name_) {" << endl; + INC_TAB; + s << TAB << "this._proto_struct_name_ = \"STRUCT\" + Math.random();" << endl; + DEL_TAB; + s << TAB << "}" << endl; + s << TAB << "return this._proto_struct_name_;" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //toObject + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.toObject = function() { "<< endl; + INC_TAB; + s << TAB << "return {" << endl; + + for (size_t i = 0; i < member.size(); i++) + { + INC_TAB; + if (i > 0 && i < member.size()) { + s << "," << endl; + } + + if (isSimple(member[i]->getTypePtr())) { + s << TAB << "\"" << member[i]->getId() << "\" : this." << member[i]->getId(); + } + else { + s << TAB << "\"" << member[i]->getId() << "\" : this." << member[i]->getId() << ".toObject()"; + } + DEL_TAB; + } + + s << endl; + s << TAB << "};" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //readFromJson + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.readFromObject = function(json) { "<< endl; + INC_TAB; + + for (size_t i = 0; i < member.size(); i++) + { + if (isSimple(member[i]->getTypePtr())) { + s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << " = json." << member[i]->getId() << ");" << endl; + } else { + s << TAB << "json.hasOwnProperty(\"" << member[i]->getId() << "\") && (this." << member[i]->getId() << ".readFromObject(json." << member[i]->getId() << "));" << endl; + } + } + + DEL_TAB; + s << TAB << "};" << endl; + + //toBinBuffer + s << TAB << sNamespace << "." << pPtr->getId() << ".prototype.toBinBuffer = function () {" << endl; + INC_TAB; + s << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + s << TAB << "this._writeTo(os);" << endl; + s << TAB << "return os.getBinBuffer();" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //new + s << TAB << sNamespace << "." << pPtr->getId() << ".new = function () {" << endl; + INC_TAB; + s << TAB << "return new " << sNamespace << "." << pPtr->getId() << "();" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + //create + s << TAB << sNamespace << "." << pPtr->getId() << ".create = function (is) {" << endl; + INC_TAB; + s << TAB << "return " << sNamespace << "." << pPtr->getId() << "._readFrom(is);" << endl; + DEL_TAB; + s << TAB << "};" << endl; + + return s.str(); +} + +string CodeGenerator::generateJS(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedAssert) +{ + ostringstream sstr; + vector ss(pPtr->getAllStructPtr()); + for (size_t last = 0; last != ss.size() && ss.size() != 0;) + { + last = ss.size(); + + for (vector::iterator iter=ss.begin(); iter!=ss.end();) + { + string str = generateJS(*iter, pPtr->getId(), bNeedAssert); + + if (!str.empty()) { + sstr << str << endl; + iter = ss.erase(iter); + + } else { + iter++; + } + } + } + + ostringstream cstr; + vector &cs = pPtr->getAllConstPtr(); + for (size_t i = 0; i < cs.size(); i++) + { + cstr << generateJS(cs[i], pPtr->getId(), bNeedStream); + } + + ostringstream estr; + vector & es = pPtr->getAllEnumPtr(); + for (size_t i = 0; i < es.size(); i++) + { + estr << generateJS(es[i], pPtr->getId()); + } + + ostringstream str; + if (!estr.str().empty()) str << estr.str() << endl; + if (!cstr.str().empty()) str << cstr.str() << endl; + if (!sstr.str().empty()) + { + bNeedStream = true; + str << sstr.str() << endl; + } + + return str.str(); +} + +bool CodeGenerator::generateJS(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + ostringstream istr; + set setNamespace; + for(size_t i = 0; i < namespaces.size(); i++) + { + if (setNamespace.count(namespaces[i]->getId()) == 0) + { + istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl; + istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl; + + setNamespace.insert(namespaces[i]->getId()); + } + } + + //先生成编解码体 + ostringstream estr; + bool bNeedAssert = false; + bool bNeedStream = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + } + if (estr.str().empty()) + { + return false; + } + + //再生成导入模块 + ostringstream ostr; + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; + } + + //生成文件内容 + ostringstream sstr; + sstr << printHeaderRemark("Structure"); + sstr << "\"use strict\";" << endl << endl; + if (bNeedAssert) + { + sstr << "var assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl; + } + sstr << ostr.str() << endl; + sstr << istr.str(); + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + IDL_TYPE + ".js"; + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, sstr.str()); + + return true; +} \ No newline at end of file diff --git a/src/gen_js_dts.cpp b/src/gen_js_dts.cpp new file mode 100644 index 0000000..74f8a47 --- /dev/null +++ b/src/gen_js_dts.cpp @@ -0,0 +1,239 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generateDTS(const EnumPtr &pPtr, const string &sNamespace) +{ + ostringstream s; + + INC_TAB; + s << TAB << "enum " << pPtr->getId() << " {" << endl; + + INC_TAB; + //成员变量 + int nenum = -1; + bool bDependent = false; + vector& member = pPtr->getAllMemberPtr(); + for (size_t i = 0; i < member.size(); i++) + { + bDependent |= isDependent(sNamespace, member[i]->getId()); + if (member[i]->hasDefault()) + { + nenum = TC_Common::strto(member[i]->def()); + } + else + { + nenum++; + } + s << TAB << "\"" << member[i]->getId() << "\" = " << TC_Common::tostr(nenum) << ((i < member.size() - 1) ? "," : "") << endl; + } + DEL_TAB; + + s << TAB << "}" << endl; + DEL_TAB; + + if (!_bMinimalMembers || _bEntry || bDependent || isDependent(sNamespace, pPtr->getId())) { + return s.str(); + } else { + return ""; + } +} + +string CodeGenerator::generateDTS(const ConstPtr &pPtr, const string &sNamespace, bool &bNeedStream) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getTypeIdPtr()->getId())) + { + return ""; + } + + ostringstream s; + if (_bStringBinaryEncoding && GET_CONST_GRAMMAR_PTR(pPtr)->t == CONST_GRAMMAR(STRING)) + { + bNeedStream = true; + } + + INC_TAB; + s << TAB << "const " << pPtr->getTypeIdPtr()->getId() << ":" + << getDtsType(pPtr->getTypeIdPtr()->getTypePtr()) << ";" + << endl; + DEL_TAB; + return s.str(); +} + +string CodeGenerator::generateDTS(const StructPtr &pPtr, const string &sNamespace) +{ + if (_bMinimalMembers && !_bEntry && !isDependent(sNamespace, pPtr->getId())) + { + return ""; + } + + string sStructName = pPtr->getId() + "$OBJ"; + vector &member = pPtr->getAllMemberPtr(); + ostringstream s; + + INC_TAB; + s << TAB << "class " << pPtr->getId() << " {" << endl; + INC_TAB; + + for (size_t i = 0; i < member.size(); i++) + { + s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << getDtsType(member[i]->getTypePtr()) << ";" << endl; + } + if (member.size() > 0) + { + s << endl; + } + + /* + * Size Optimize: + * Remove support. + * Remove toBinBuffer, readFromObject, toObject, new, create members. + */ + if (_iOptimizeLevel != Os) + { + s << TAB << "toObject(): " << sStructName << ";" << endl; + s << TAB << "readFromObject(json: " << sStructName << "): void;" << endl; + s << TAB << "toBinBuffer(): " << IDL_NAMESPACE_STR << "Stream.BinBuffer;" << endl; + s << TAB << "static new(): " << pPtr->getId() << ";" << endl; + s << TAB << "static create(is: " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream): " << pPtr->getId() << ";" << endl; + } + DEL_TAB; + s << TAB << "}" << endl; + + s << TAB << "interface " << sStructName << " {" << endl; + INC_TAB; + + for (size_t i = 0; i < member.size(); i++) + { + const string &sType = getDtsType(member[i]->getTypePtr(), false); + if (!sType.empty()) + { + s << TAB << (member[i]->getId()) << (member[i]->isRequire()?": ":"?: ") << sType << ";" << endl; + } + } + DEL_TAB; + s << TAB << "}" << endl; + DEL_TAB; + return s.str(); +} + +string CodeGenerator::generateDTS(const NamespacePtr &pPtr, bool &bNeedStream) +{ + //结构 + ostringstream sstr; + vector ss(pPtr->getAllStructPtr()); + for (size_t last = 0; last != ss.size() && ss.size() != 0;) + { + last = ss.size(); + for (vector::iterator iter=ss.begin(); iter!=ss.end();) + { + string str = generateDTS(*iter, pPtr->getId()); + if (!str.empty()) + { + sstr << str << endl; + iter = ss.erase(iter); + } + else + { + iter++; + } + } + } + + //常量 + ostringstream cstr; + vector &cs = pPtr->getAllConstPtr(); + for (size_t i = 0; i < cs.size(); i++) + { + cstr << generateDTS(cs[i], pPtr->getId(), bNeedStream); + } + + //枚举 + ostringstream estr; + vector &es = pPtr->getAllEnumPtr(); + for (size_t i = 0; i < es.size(); i++) + { + estr << generateDTS(es[i], pPtr->getId()); + } + + ostringstream kstr; + if (!estr.str().empty()) kstr << estr.str() << endl; + if (!cstr.str().empty()) kstr << cstr.str() << endl; + if (!sstr.str().empty()) + { + bNeedStream = true; + kstr << sstr.str(); + } + + return kstr.str(); +} + +string CodeGenerator::generateDTS(const NamespacePtr &pPtr, const string &sContent) +{ + ostringstream str; + if (!sContent.empty()) + { + str << "export declare namespace " << pPtr->getId() << " {" << endl; + str << sContent; + str << "}" << endl << endl; + } + return str.str(); +} + +void CodeGenerator::generateDTS(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + //先生成编解码体 + ostringstream estr; + bool bNeedStream = false; + for (size_t i = 0; i < namespaces.size(); i++) + { + estr << generateDTS(namespaces[i], generateDTS(namespaces[i], bNeedStream)); + } + if (estr.str().empty()) + { + return; + } + + //再生成导入模块 + ostringstream ostr; + if (bNeedStream) + { + ostr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + //生成文件内容 + ostringstream sstr; + sstr << printHeaderRemark("Structure"); + sstr << ostr.str() << endl; + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + IDL_TYPE + ".d.ts"; + + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, sstr.str()); +} \ No newline at end of file diff --git a/src/gen_proxy.cpp b/src/gen_proxy.cpp new file mode 100644 index 0000000..e33636e --- /dev/null +++ b/src/gen_proxy.cpp @@ -0,0 +1,549 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +#define INVOKE_RETURN(protocol, prefix, params) \ + str << TAB << "return this._worker." << TC_Common::lower(protocol) << "_invoke(\"" << oPtr->getId() << "\", "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "E"; \ + str << "(" << sParams << params << "), arguments[arguments.length - 1], "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF" << ").then("; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$" << prefix << "D, "; \ + str << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER);" << endl; +#define PROTOCOL_PARAMS (sParams.empty() ? "" : ", ") << "version" + +struct SortOperation +{ + bool operator()(const OperationPtr &o1, const OperationPtr &o2) + { + return o1->getId() < o2->getId(); + } +}; + +string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + bool bHasParamOut = false; + string sParams = ""; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) + { + continue; + } + + sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId(); + } + + //SETP01 生成函数声明(Interface = IF) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF = {" << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << oPtr->getId() << "\"," << endl; + str << TAB << "\"return\" : \"" << getClassName(oPtr->getReturnPtr()->getTypePtr()) << "\"," << endl; + str << TAB << "\"arguments\" : ["; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + str << (i > 0 ? ", {" : "{") << endl; + + INC_TAB; + + str << TAB << "\"name\" : \"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"," << endl; + str << TAB << "\"class\" : \"" << getClassName(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << "\"," << endl; + + if (vParamDecl[i]->isOut()) + { + bHasParamOut = true; + str << TAB << "\"direction\" : \"out\"" << endl; + } + else + { + str << TAB << "\"direction\" : \"in\"" << endl; + } + + DEL_TAB; + + str << TAB << "}"; + } + str << "]" << endl; + + DEL_TAB; + + str << TAB << "};" << endl << endl; + + //SETP02 生成 IDL 编码接口(IDL Encoder = IE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IE = function (" << sParams << ") {" << endl; + + INC_TAB; + + str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + + // 写入 Dependent 列表 + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return os.getBinBuffer();" << endl; + + DEL_TAB; + + str << TAB << "};" << endl << endl; + + //STEP03 生成 IDL 解码函数(IDL Decoder = ID) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ID = function (data) {" << endl; + INC_TAB; + str << TAB << "try {" << endl; + INC_TAB; + + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) + { + str << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(data.response.sBuffer);" << endl; + } + + str << TAB << "return {" << endl; + INC_TAB; + str << TAB << "\"request\" : data.request," << endl; + str << TAB << "\"response\" : {" << endl; + INC_TAB; + str << TAB << "\"costtime\" : data.request.costtime"; + + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << "," << endl; + str << TAB << "\"return\"" + << " : is." << toFunctionName(oPtr->getReturnPtr(), "read") << "(0, true, "; + + if (isSimple(oPtr->getReturnPtr()->getTypePtr())) + { + str << getDefault(oPtr->getReturnPtr(), oPtr->getReturnPtr()->def(), nPtr->getId()) + << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : ""); + } + else + { + str << getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + str << ")"; + } + + if (bHasParamOut) + { + str << "," << endl; + str << TAB << "\"arguments\" : {" << endl; + + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\"" + << " : is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" << (i + 1) << ", true, "; + + if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + } + else + { + str << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + + } + + DEL_TAB; + str << TAB << "}"; + } + + str << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw {" << endl; + INC_TAB; + str << TAB << "\"request\" : data.request," << endl; + str << TAB << "\"response\" : {" << endl; + INC_TAB; + str << TAB << "\"costtime\" : data.request.costtime," << endl; + str << TAB << "\"error\" : {" << endl; + INC_TAB; + str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl; + str << TAB << "\"message\" : e.message" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + //SETP04 生成 Protocol 编码接口(Protocol Encoder = PE) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PE = function (" + << sParams << (sParams.empty() ? "" : ", ") << "__$PROTOCOL$VERSION) {" << endl; + + INC_TAB; + + str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = __$PROTOCOL$VERSION;" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + + // 写入 Dependent 列表 + getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << TAB << "return " << PROTOCOL_VAR << ";" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + // STEP05 生成 Protocol 解码函数(Protocol Decoder = PD) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$PD = function (data) {" << endl; + INC_TAB; + str << TAB << "try {" << endl; + INC_TAB; + if (oPtr->getReturnPtr()->getTypePtr() || bHasParamOut) { + str << TAB << "var " << PROTOCOL_VAR << " = data.response." << PROTOCOL_VAR << ";" << endl; + } + str << TAB << "return {" << endl; + INC_TAB; + str << TAB << "\"request\" : data.request," << endl; + str << TAB << "\"response\" : {" << endl; + INC_TAB; + str << TAB << "\"costtime\" : data.request.costtime"; + + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << "," << endl; + str << TAB << "\"return\" : " << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "read") << "(\"\""; + + if (!isSimple(oPtr->getReturnPtr()->getTypePtr()) && !isBinBuffer(oPtr->getReturnPtr()->getTypePtr())) + { + str << ", " << getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + str << ", " << getDefault(oPtr->getReturnPtr(), "", nPtr->getId(), true) + << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : ""); + + str << ")"; + } + + if (bHasParamOut) + { + str << "," << endl; + str << TAB << "\"arguments\" : {" << endl; + + INC_TAB; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\" : " + << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + str << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + str << ")"; + + if (i == vParamDecl.size() - 1) + { + str << endl; + } + else + { + str << "," << endl; + } + + } + + DEL_TAB; + str << TAB << "}"; + } + + str << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "} catch (e) {" << endl; + INC_TAB; + str << TAB << "throw {" << endl; + INC_TAB; + str << TAB << "\"request\" : data.request," << endl; + str << TAB << "\"response\" : {" << endl; + INC_TAB; + str << TAB << "\"costtime\" : data.request.costtime," << endl; + str << TAB << "\"error\" : {" << endl; + INC_TAB; + str << TAB << "\"code\" : " << IDL_NAMESPACE_STR << "Error.CLIENT.DECODE_ERROR," << endl; + str << TAB << "\"message\" : e.message" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + + //STEP03 生成框架调用错误处理函数(Error Response = ER) + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$ER = function (data) {" << endl; + INC_TAB; + str << TAB << "throw {" << endl; + INC_TAB; + str << TAB << "\"request\" : data.request," << endl; + str << TAB << "\"response\" : {" << endl; + INC_TAB; + str << TAB << "\"costtime\" : data.request.costtime," << endl; + str << TAB << "\"error\" : data.error" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + + //SETP04 生成函数接口 + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy.prototype." << oPtr->getId() << " = function (" + << sParams << ") {" << endl; + + INC_TAB; + + str << TAB << "var version = this._worker.version;" << endl; + + str << TAB << "if (version === " << PROTOCOL_SIMPLE << " || version === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + INVOKE_RETURN(PROTOCOL_VAR, "P", PROTOCOL_PARAMS); + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + INVOKE_RETURN(IDL_NAMESPACE_STR, "I", ""); + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + + str << TAB << "};" << endl; + + //SETP05 绑定函数声明 + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Proxy." << oPtr->getId() << " = " + << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$IF;" << endl; + + return str.str(); +} + +string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, const InterfacePtr &pPtr) +{ + ostringstream str; + + vector & vOperation = pPtr->getAllOperationPtr(); + sort(vOperation.begin(), vOperation.end(), SortOperation()); + for (size_t i = 0; i < vOperation.size(); i++) + { + str << generateJSProxy(nPtr, pPtr, vOperation[i]) << endl; + } + + return str.str(); +} + +string CodeGenerator::generateJSProxy(const NamespacePtr &nPtr, bool &bNeedRpc, bool &bNeedStream) +{ + ostringstream str; + + vector & is = nPtr->getAllInterfacePtr(); + for (size_t i = 0; i < is.size(); i++) + { + str << generateJSProxy(nPtr, is[i]) << endl; + } + if (is.size() != 0) + { + bNeedRpc = true; + bNeedStream = true; + } + + return str.str(); +} + +bool CodeGenerator::generateJSProxy(const ContextPtr &cPtr) +{ + vector namespaces = cPtr->getNamespaces(); + + ostringstream istr; + set setNamespace; + for(size_t i = 0; i < namespaces.size(); i++) + { + if (setNamespace.count(namespaces[i]->getId()) == 0) + { + istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl; + istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl; + + setNamespace.insert(namespaces[i]->getId()); + } + } + + set setInterface; + for(size_t i = 0; i < namespaces.size(); i++) + { + vector & is = namespaces[i]->getAllInterfacePtr(); + for (size_t ii = 0; ii < is.size(); ii++) + { + if (setInterface.count(namespaces[i]->getId() + "::" + is[ii]->getId()) != 0) + { + continue; + } + setInterface.insert(namespaces[i]->getId() + "::" + is[ii]->getId()); + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy = function () {" << endl; + INC_TAB; + istr << TAB << "this._name = undefined;" << endl; + istr << TAB << "this._worker = undefined;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setTimeout = function (iTimeout) {" << endl; + INC_TAB; + istr << TAB << "this._worker.timeout = iTimeout;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getTimeout = function () {" << endl; + INC_TAB; + istr << TAB << "return this._worker.timeout;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.setVersion = function (iVersion) {" << endl; + INC_TAB; + istr << TAB << "this._worker.version = iVersion;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + + istr << TAB << namespaces[i]->getId() << "." << is[ii]->getId() << "Proxy.prototype.getVersion = function () {" << endl; + INC_TAB; + istr << TAB << "return this._worker.version;" << endl; + DEL_TAB; + istr << TAB << "};" << endl << endl; + } + } + + //先生成编解码 + 代理类 + ostringstream estr; + bool bNeedAssert = false; + bool bNeedStream = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + } + + bool bNeedRpc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << generateJSProxy(namespaces[i], bNeedRpc, bNeedStream); + } + + if (estr.str().empty()) + { + return false; + } + + //再生成导入模块 + ostringstream ostr; + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; + } + + //生成文件内容 + ostringstream sstr; + sstr << printHeaderRemark("Client"); + sstr << "\"use strict\";" << endl << endl; + if (bNeedAssert) + { + sstr << "var assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + sstr << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl; + } + if (bNeedRpc) + { + sstr << "var " << IDL_NAMESPACE_STR << "Error = require(\"" << _sRpcPath << "\").error;" << endl; + } + + sstr << ostr.str() << endl; + sstr << istr.str() << endl; + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.js"; + + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, sstr.str()); + + return true; +} + +#undef INVOKE_RETURN +#undef PROTOCOL_PARAMS \ No newline at end of file diff --git a/src/gen_proxy_dts.cpp b/src/gen_proxy_dts.cpp new file mode 100644 index 0000000..4187bd0 --- /dev/null +++ b/src/gen_proxy_dts.cpp @@ -0,0 +1,208 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generateDTSProxyInfo() +{ + ostringstream str; + + INC_TAB; + + // Argument + str << TAB << "interface SharedArgumentInfo {" << endl; + INC_TAB; + str << TAB << "name: string;" << endl; + str << TAB << "class: string;" << endl; + str << TAB << "direction: 'in' | 'out';" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + // Function + str << TAB << "interface SharedFunctionInfo {" << endl; + INC_TAB; + str << TAB << "name: string;" << endl; + str << TAB << "return: string;" << endl; + str << TAB << "arguments: SharedArgumentInfo[];" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + + return str.str(); +} + +string CodeGenerator::generateDTSProxy(const InterfacePtr &pPtr) +{ + vector &vOperation = pPtr->getAllOperationPtr(); + ostringstream str; + + //class + INC_TAB; + str << TAB << "class " << pPtr->getId() << "Proxy {" << endl; + INC_TAB; + str << TAB << "setTimeout(iTimeout: number): void;" << endl; + str << TAB << "getTimeout(): number;" << endl; + str << TAB << "setVersion(iVersion: number): void;" << endl; + str << TAB << "getVersion(): number;" << endl; + for (size_t i = 0; i < vOperation.size(); i++) + { + OperationPtr &oPtr = vOperation[i]; + + str << TAB << oPtr->getId() << "("; + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(vParamDecl[j]->isOut()) + { + continue; + } + str << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + str << ", "; + } + str << "property?: " << IDL_NAMESPACE_STR << "Rpc.InvokeProperty): Promise<" << pPtr->getId() << "$" << oPtr->getId() << "$DE>;" << endl; + + str << TAB << "static " << oPtr->getId() << ": SharedFunctionInfo;" << endl; + } + DEL_TAB; + str << TAB << "}" << endl; + + //interface + for (size_t i = 0; i < vOperation.size(); i++) + { + OperationPtr &oPtr = vOperation[i]; + + str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$DE {" << endl; + INC_TAB; + str << TAB << "request: object;" << endl; + str << TAB << "response: {" << endl; + INC_TAB; + str << TAB << "costtime: number;" << endl; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << TAB << "return: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()) << ";" << endl; + } + else + { + str << TAB << "return: void;" << endl; + } + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + bool hasArgs = false; + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(vParamDecl[j]->isOut()) { + hasArgs = true; + break; + } + } + + if(hasArgs) + { + str << TAB << "arguments: {" << endl; + INC_TAB; + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(!vParamDecl[j]->isOut()) { + continue; + } + str << TAB << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) << ";" << endl; + } + DEL_TAB; + str << TAB << "}" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "}" << endl; + } + DEL_TAB; + + return str.str(); +} + +string CodeGenerator::generateDTSProxy(const NamespacePtr &nPtr, bool &bNeedStream, bool &bNeedRpc) +{ + ostringstream str; + vector &is = nPtr->getAllInterfacePtr(); + if (is.size() > 0) + { + bNeedStream = true; + bNeedRpc = true; + + str << generateDTSProxyInfo() << endl; + } + for (size_t i = 0; i < is.size(); i++) + { + str << generateDTSProxy(is[i]) << endl; + } + return str.str(); +} + +void CodeGenerator::generateDTSProxy(const ContextPtr &cPtr) +{ + vector namespaces = cPtr->getNamespaces(); + + //先生成编解码 + 代理类 + ostringstream estr; + bool bNeedStream = false; + bool bNeedRpc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + ostringstream kstr; + + kstr << generateDTS(namespaces[i], bNeedStream); + kstr << generateDTSProxy(namespaces[i], bNeedStream, bNeedRpc); + + estr << generateDTS(namespaces[i], kstr.str()); + } + if (estr.str().empty()) + { + return; + } + + //再生成导入模块 + ostringstream ostr; + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + //生成文件内容 + ostringstream sstr; + sstr << printHeaderRemark("Client"); + if (bNeedStream) + { + sstr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + if (bNeedRpc) + { + sstr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl; + } + + sstr << ostr.str() << endl; + sstr << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Proxy.d.ts"; + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, sstr.str()); +} \ No newline at end of file diff --git a/src/gen_server.cpp b/src/gen_server.cpp new file mode 100644 index 0000000..4501df4 --- /dev/null +++ b/src/gen_server.cpp @@ -0,0 +1,381 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generatePing(const NamespacePtr &nPtr, const InterfacePtr &pPtr) +{ + ostringstream str; + + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping$RE = function (_ret) {" << endl; + INC_TAB; + str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl; + str << TAB << PROTOCOL_VAR << ".writeInt32(\"\", _ret);" << endl << endl; + str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + str << TAB << "os.writeInt32(0, _ret);" << endl << endl; + str << TAB << "this.doResponse(os.getBinBuffer());" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.__" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping = function (current) {" << endl; + INC_TAB; + str << TAB << "__" << nPtr->getId() << "_" << pPtr->getId() << "$" << TC_Common::lower(IDL_NAMESPACE_STR) << "_ping$RE.call(current, 0);" << endl << endl; + str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SUCCESS;" << endl; + DEL_TAB; + str << TAB << "};" << endl; + + return str.str(); +} + +string CodeGenerator::generateAsync(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + + string sParams = ""; + if (oPtr->getReturnPtr()->getTypePtr()) + { + sParams += "_ret"; + + // 写入 Dependent 列表 + getDataType(oPtr->getReturnPtr()->getTypePtr()); + } + + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + sParams += (sParams.empty()?"":", ") + vParamDecl[i]->getTypeIdPtr()->getId(); + } + + str << TAB << "var __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$RE = function (" << sParams << ") {" << endl; + + INC_TAB; + + if (sParams.empty()) + { + str << TAB << "this.doResponse(new " << IDL_NAMESPACE_STR << "Stream.BinBuffer());" << endl; + DEL_TAB; + str << TAB << "};" << endl; + + return str.str(); + } + + str << TAB << "if (this.getRequestVersion() === " << PROTOCOL_SIMPLE << " || this.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + str << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + str << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = this.getRequestVersion();" << endl; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << TAB << PROTOCOL_VAR << "." << toFunctionName(oPtr->getReturnPtr(), "write") << "(\"\", _ret" + << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + } + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(\"" + << vParamDecl[i]->getTypeIdPtr()->getId() << "\", " << vParamDecl[i]->getTypeIdPtr()->getId() + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + } + str << endl; + str << TAB << "this.doResponse(" << PROTOCOL_VAR << ".encode());" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + + INC_TAB; + str << TAB << "var os = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "OutputStream();" << endl; + if (oPtr->getReturnPtr()->getTypePtr()) + { + str << TAB << "os." << toFunctionName(oPtr->getReturnPtr(), "write") << "(0, _ret" + << (isRawOrString(oPtr->getReturnPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + } + for (size_t i = 0; i < vParamDecl.size(); i++) + { + if (!vParamDecl[i]->isOut()) continue; + + str << TAB << "os." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "write") << "(" + << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : "") << ");" << endl; + } + str << endl; + str << TAB << "this.doResponse(os.getBinBuffer());" << endl; + DEL_TAB; + str << TAB << "}" << endl; + + DEL_TAB; + + str << TAB << "};" << endl; + + return str.str(); +} + +string CodeGenerator::generateDispatch(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.__" << oPtr->getId() << " = function (current" << (vParamDecl.size() != 0 ? ", binBuffer" : "") << ") {" << endl; + + INC_TAB; + + ostringstream dstr; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + dstr << TAB << "var " << vParamDecl[i]->getTypeIdPtr()->getId() << " = null;" << endl; + } + if (vParamDecl.size() != 0) + { + dstr << endl; + } + + dstr << TAB << "if (current.getRequestVersion() === " << PROTOCOL_SIMPLE << " || current.getRequestVersion() === " << PROTOCOL_COMPLEX << ") {" << endl; + INC_TAB; + dstr << TAB << "var " << PROTOCOL_VAR << " = new " << IDL_NAMESPACE_STR << "Stream.UniAttribute();" << endl; + dstr << TAB << PROTOCOL_VAR << "." << PROTOCOL_VAR << "Version = current.getRequestVersion();" << endl; + dstr << TAB << PROTOCOL_VAR << ".decode(binBuffer);" << endl; + + for (size_t i = 0; i < vParamDecl.size(); i++) + { + dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId() + << " = " << PROTOCOL_VAR << "." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") + << "(\"" << vParamDecl[i]->getTypeIdPtr()->getId() << "\""; + + if (!isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) && !isBinBuffer(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + dstr << ", " << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + if (vParamDecl[i]->isOut()) + { + dstr << ", " << getDefault(vParamDecl[i]->getTypeIdPtr(), "", nPtr->getId(), true) + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + } + + dstr << ");" << endl; + } + DEL_TAB; + dstr << TAB << "} else {" << endl; + + INC_TAB; + dstr << TAB << "var is = new " << IDL_NAMESPACE_STR << "Stream." << IDL_TYPE << "InputStream(binBuffer);" << endl; + string sParams = ""; + for (size_t i = 0; i < vParamDecl.size(); i++) + { + sParams += ", " + vParamDecl[i]->getTypeIdPtr()->getId(); + + dstr << TAB << vParamDecl[i]->getTypeIdPtr()->getId() + << " = is." << toFunctionName(vParamDecl[i]->getTypeIdPtr(), "read") << "(" + << (i + 1) << ", " << (vParamDecl[i]->isOut() ? "false" : "true") << ", "; + + if (isSimple(vParamDecl[i]->getTypeIdPtr()->getTypePtr())) + { + dstr << getDefault(vParamDecl[i]->getTypeIdPtr(), vParamDecl[i]->getTypeIdPtr()->def(), nPtr->getId()) + << (isRawOrString(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) ? ", 1" : ""); + } + else + { + dstr << getDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()); + } + + dstr << ");" << endl; + } + DEL_TAB; + dstr << TAB << "}" << endl << endl; + + if (!sParams.empty()) + { + str << dstr.str(); + } + + str << TAB << "current.sendResponse = __" << nPtr->getId() << "_" << pPtr->getId() << "$" << oPtr->getId() << "$RE;" << endl << endl; + + str << TAB << "this." << oPtr->getId() << "(current" << sParams << ");" << endl << endl; + + str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SUCCESS;" << endl; + + DEL_TAB; + + str << TAB << "};" << endl; + + return str.str(); +} + +string CodeGenerator::generateJSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype." << oPtr->getId() << " = function () {" << endl; + + INC_TAB; + str << TAB << "assert.fail(\"" << oPtr->getId() << " function not implemented\");" << endl; + DEL_TAB; + str << TAB << "};" << endl; + + return str.str(); +} + +string CodeGenerator::generateJSServer(const InterfacePtr &pPtr, const NamespacePtr &nPtr) +{ + ostringstream str; + vector & vOperation = pPtr->getAllOperationPtr(); + + //生成类 + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp = function () { " << endl; + INC_TAB; + str << TAB << "this._name = undefined;" << endl; + str << TAB << "this._worker = undefined;" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + //生成初始化函数 + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.initialize = function () {};" << endl << endl; + + //生成分发函数 + str << TAB << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype.onDispatch = function (current, funcName, binBuffer) { " << endl; + INC_TAB; + str << TAB << "if (\"__\" + funcName in this) {" << endl; + INC_TAB; + str << TAB << "return this[\"__\" + funcName](current, binBuffer);" << endl; + DEL_TAB; + str << TAB << "} else {" << endl; + INC_TAB; + str << TAB << "return " << IDL_NAMESPACE_STR << "Error.SERVER.FUNC_NOT_FOUND;" << endl; + DEL_TAB; + str << TAB << "}" << endl; + DEL_TAB; + str << TAB << "};" << endl << endl; + + //生成 PING 方法 + str << generatePing(nPtr, pPtr) << endl; + + //生成接口函数 + for (size_t i = 0; i < vOperation.size(); i++) + { + str << generateJSServer(nPtr, pPtr, vOperation[i]) << endl; + str << generateAsync(nPtr, pPtr, vOperation[i]) << endl; + str << generateDispatch(nPtr, pPtr, vOperation[i]) << endl; + } + + str << endl; + + return str.str(); +} + +string CodeGenerator::generateJSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc, bool &bNeedAssert) +{ + ostringstream str; + + vector & is = pPtr->getAllInterfacePtr(); + for (size_t i = 0; i < is.size(); i++) + { + str << generateJSServer(is[i], pPtr) << endl; + } + if (is.size() != 0) + { + bNeedRpc = true; + bNeedStream = true; + bNeedAssert = true; + } + + return str.str(); +} + +bool CodeGenerator::generateJSServer(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + ostringstream istr; + set setNamespace; + for(size_t i = 0; i < namespaces.size(); i++) + { + if (setNamespace.count(namespaces[i]->getId()) == 0) + { + istr << TAB << "var " << namespaces[i]->getId() << " = " << namespaces[i]->getId() << " || {};" << endl; + istr << TAB << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl << endl; + + setNamespace.insert(namespaces[i]->getId()); + } + } + + //生成编解码 + 服务类 + ostringstream estr; + bool bNeedAssert = false; + bool bNeedStream = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << generateJS(namespaces[i], bNeedStream, bNeedAssert); + } + + bool bNeedRpc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + estr << generateJSServer(namespaces[i], bNeedStream, bNeedRpc, bNeedAssert) << endl; + } + + if (estr.str().empty()) + { + return false; + } + + //再生成导入模块 + ostringstream ostr; + if (bNeedAssert) + { + ostr << TAB << "var assert = require(\"assert\");" << endl; + } + if (bNeedStream) + { + ostr << TAB << "var " << IDL_NAMESPACE_STR << "Stream = require(\"" << _sStreamPath << "\");" << endl; + } + if (bNeedRpc) + { + ostr << TAB << "var " << IDL_NAMESPACE_STR << "Error = require(\"" << _sRpcPath << "\").error;" << endl; + } + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << TAB << "var " << it->second.sModule << " = require(\"" << it->second.sFile << "\");" << endl; + } + + ostringstream str; + + str << printHeaderRemark("Server"); + str << "\"use strict\";" << endl << endl; + str << ostr.str() << endl; + str << istr.str(); + str << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".js"; + + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, str.str()); + + return true; +} \ No newline at end of file diff --git a/src/gen_server_dts.cpp b/src/gen_server_dts.cpp new file mode 100644 index 0000000..49803cb --- /dev/null +++ b/src/gen_server_dts.cpp @@ -0,0 +1,149 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generateDTSServer(const NamespacePtr &nPtr, const InterfacePtr &pPtr) +{ + vector &vOperation = pPtr->getAllOperationPtr(); + ostringstream str; + + //class + INC_TAB; + str << TAB << "class " << pPtr->getId() << "Imp {" << endl; + INC_TAB; + str << TAB << "initialize(): Promise | void;" << endl; + str << TAB << "protected onDispatch(current: " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current, funcName: string, binBuffer: " << IDL_NAMESPACE_STR << "Stream.BinBuffer): number" << endl; + for (size_t i = 0; i < vOperation.size(); i++) + { + OperationPtr &oPtr = vOperation[i]; + str << TAB << oPtr->getId() << "(current: " << pPtr->getId() << "$" << oPtr->getId() << "$CUR"; + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()); + } + str << "): void;" << endl; + } + DEL_TAB; + str << TAB << "}" << endl; + + //interface + for (size_t i = 0; i < vOperation.size(); i++) + { + OperationPtr &oPtr = vOperation[i]; + + str << TAB << "interface " << pPtr->getId() << "$" << oPtr->getId() << "$CUR extends " << IDL_NAMESPACE_STR << "Rpc." << IDL_TYPE << "Current {" <getReturnPtr()->getTypePtr()) + { + str << "sendResponse(ret: " << getDtsType(oPtr->getReturnPtr()->getTypePtr()); + + vector &vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t j = 0; j < vParamDecl.size(); j++) + { + if(!vParamDecl[j]->isOut()) { + continue; + } + str << ", " << vParamDecl[j]->getTypeIdPtr()->getId() << ": " << getDtsType(vParamDecl[j]->getTypeIdPtr()->getTypePtr()) ; + } + str << "): void;" << endl; + } + else + { + str << "sendResponse(): void;" << endl; + } + + DEL_TAB; + str << TAB << "}" << endl; + } + DEL_TAB; + + return str.str(); +} + +string CodeGenerator::generateDTSServer(const NamespacePtr &pPtr, bool &bNeedStream, bool &bNeedRpc) +{ + vector &is = pPtr->getAllInterfacePtr(); + ostringstream str; + + for (size_t i = 0; i < is.size(); i++) + { + str << generateDTSServer(pPtr, is[i]) << endl; + } + + if (is.size() != 0) + { + bNeedRpc = true; + bNeedStream = true; + } + + return str.str(); +} + +void CodeGenerator::generateDTSServer(const ContextPtr &pPtr) +{ + vector namespaces = pPtr->getNamespaces(); + + //生成编解码 + 服务类 + ostringstream estr; + bool bNeedStream = false; + bool bNeedRpc = false; + for(size_t i = 0; i < namespaces.size(); i++) + { + ostringstream kstr; + + kstr << generateDTS(namespaces[i], bNeedStream); + kstr << generateDTSServer(namespaces[i], bNeedStream, bNeedRpc); + + estr << generateDTS(namespaces[i], kstr.str()); + } + if(estr.str().empty()) + { + return; + } + + //再生成导入模块 + ostringstream ostr; + if (bNeedStream) + { + ostr << "import * as " << IDL_NAMESPACE_STR << "Stream from \"" << _sStreamPath << "\";" << endl; + } + if (bNeedRpc) + { + ostr << "import * as " << IDL_NAMESPACE_STR << "Rpc from \"" << _sRpcPath << "\";" << endl; + } + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + if (it->second.sModule.empty()) continue; + + if (estr.str().find(it->second.sModule + ".") == string::npos) continue; + + ostr << "import * as " << it->second.sModule << " from \"" << TC_File::excludeFileExt(it->second.sFile) << "\";" << endl; + } + + ostringstream str; + str << printHeaderRemark("Server"); + str << ostr.str() << endl; + str << estr.str() << endl; + + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(pPtr->getFileName())) + ".d.ts"; + + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, str.str()); +} \ No newline at end of file diff --git a/src/gen_server_imp.cpp b/src/gen_server_imp.cpp new file mode 100644 index 0000000..a73b61b --- /dev/null +++ b/src/gen_server_imp.cpp @@ -0,0 +1,123 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr, const OperationPtr &oPtr) +{ + ostringstream str; + str << nPtr->getId() << "." << pPtr->getId() << "Imp.prototype." << oPtr->getId() << " = function (current"; + + vector & vParamDecl = oPtr->getAllParamDeclPtr(); + for (size_t i = 0; i < vParamDecl.size(); i++) + { + str << ", " << vParamDecl[i]->getTypeIdPtr()->getId(); + } + + str << ") {" << endl; + INC_TAB; + str << TAB << "//TODO::" << endl; + DEL_TAB; + str << "};" << endl << endl; + + return str.str(); +} + +string CodeGenerator::generateJSServerImp(const NamespacePtr &nPtr, const InterfacePtr &pPtr) +{ + ostringstream str; + + + vector & vOperation = pPtr->getAllOperationPtr(); + for (size_t i = 0; i < vOperation.size(); i++) + { + str << generateJSServerImp(nPtr, pPtr, vOperation[i]); + } + + return str.str(); +} + +string CodeGenerator::generateJSServerImp(const ContextPtr &cPtr, const NamespacePtr &nPtr) +{ + ostringstream str; + + vector & is = nPtr->getAllInterfacePtr(); + for (size_t i = 0; i < is.size(); i++) + { + str << generateJSServerImp(nPtr, is[i]) << endl; + } + + return str.str(); +} + +void CodeGenerator::generateJSServerImp(const ContextPtr &cPtr) +{ + string sFileName = TC_File::excludeFileExt(_sToPath + TC_File::extractFileName(cPtr->getFileName())) + "Imp.js"; + if (TC_File::isFileExist(sFileName)) + { + return ; + } + + ostringstream str; + str << printHeaderRemark("Imp"); + str << "\"use strict\";" << endl << endl; + + vector namespaces = cPtr->getNamespaces(); + set setNamespace; + for(size_t i = 0; i < namespaces.size(); i++) + { + if (setNamespace.count(namespaces[i]->getId()) != 0) + { + continue; + } + setNamespace.insert(namespaces[i]->getId()); + + str << "var " << namespaces[i]->getId() << " = require(\"./" + << TC_File::excludeFileExt(TC_File::extractFileName(cPtr->getFileName())) << ".js\")." + << namespaces[i]->getId() << ";" << endl; + + str << "module.exports." << namespaces[i]->getId() << " = " << namespaces[i]->getId() << ";" << endl; + } + str << endl; + + set setInterface; + for(size_t i = 0; i < namespaces.size(); i++) + { + vector & is = namespaces[i]->getAllInterfacePtr(); + for (size_t ii = 0; ii < is.size(); ii++) + { + if (setInterface.count(namespaces[i]->getId() + "::" + is[ii]->getId()) != 0) + { + continue; + } + setInterface.insert(namespaces[i]->getId() + "::" + is[ii]->getId()); + + str << namespaces[i]->getId() << "." << is[ii]->getId() << "Imp.prototype.initialize = function () {" << endl; + INC_TAB; + str << TAB << "//TODO::" << endl; + DEL_TAB; + str << "};" << endl << endl; + } + } + + for(size_t i = 0; i < namespaces.size(); i++) + { + str << generateJSServerImp(cPtr, namespaces[i]); + } + + TC_File::makeDirRecursive(_sToPath, 0755); + makeUTF8File(sFileName, str.str()); +} \ No newline at end of file diff --git a/src/idl_scan.cpp b/src/idl_scan.cpp new file mode 100644 index 0000000..94770f3 --- /dev/null +++ b/src/idl_scan.cpp @@ -0,0 +1,175 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::makeName() +{ + int iHigh = uiNameIndex/26; + int iLow = uiNameIndex%26; + + uiNameIndex++; + + ostringstream s; + + s << "_" << TC_Common::upper(IDL_NAMESPACE_STR) << "_MODULE_"; + + if (iHigh != 0) + { + s << string(1, (char)(iHigh + 65)) << string(1, (char)(iLow + 65)); + } + else + { + s << string(1, (char)(iLow + 65)); + } + + s << "_"; + + return s.str(); +} + +bool CodeGenerator::isDependent(const string& sNamespace, const string& sName) const +{ + return _depMembers.find(sNamespace + "::" + sName) != _depMembers.end(); +} + +string CodeGenerator::findName(const string& sNamespace, const string& sName) +{ +#ifdef DUMP_FIND_NAME + cout << "FINDNAME BEGIN:" << sNamespace << "|" << sName << endl; +#endif + + for (map::iterator it = _mapFiles.begin(); it != _mapFiles.end(); it++) + { + #ifdef DUMP_FIND_NAME + for (map::iterator demo = it->second.mapVars.begin(); demo != it->second.mapVars.end(); demo++) + { + cout << "FINDNAME:" << it->second.sModule << "|" << demo->first << "|" << demo->second.sNamespace << "|" << demo->second.sName << endl; + } + #endif + + map::iterator inIter = it->second.mapVars.find(sNamespace + "::" + sName); + if (inIter == it->second.mapVars.end()) + { + continue; + } + + #ifdef DUMP_FIND_NAME + cout << "DEPMEMBER:" << it->first << "|" << inIter->second.sNamespace << "::" << inIter->second.sName << endl; + #endif + _depMembers.insert(inIter->second.sNamespace + "::" + inIter->second.sName); + + switch (inIter->second.iType) + { + case ImportFileType::EN_ENUM : // [[fallthrough]] + case ImportFileType::EN_STRUCT : + { + return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sName; + } + case ImportFileType::EN_ENUM_VALUE : + { + return it->second.sModule + (it->second.sModule.empty()?"":".") + inIter->second.sNamespace + "." + inIter->second.sTypeName + "." + inIter->second.sName; + } + default : + { + return it->second.sModule; + } + } + } + + return ""; +} + +void CodeGenerator::scan(const string& sFile, bool bNotPrefix) +{ + if (_mapFiles.find(sFile) != _mapFiles.end()) + { + return ; + } + + string sIdlFile = getRealFileInfo(sFile); + g_parse->parse(sIdlFile); + + vector contexts = g_parse->getContexts(); + + for(size_t i = 0; i < contexts.size(); i++) + { + if (sIdlFile == contexts[i]->getFileName()) + { + ImportFile item; + item.sFile = "./" + TC_File::excludeFileExt(TC_File::extractFileName(sFile)) + IDL_TYPE + ".js"; + item.sModule = bNotPrefix?"":makeName(); + + vector namespaces = contexts[i]->getNamespaces(); + for (size_t ii = 0; ii < namespaces.size(); ii++) + { + string sNamespace = namespaces[ii]->getId(); + + vector & ss = namespaces[ii]->getAllStructPtr(); + for (size_t iii = 0; iii < ss.size(); iii++) + { + vector vecNames = TC_Common::sepstr(ss[iii]->getSid(), "::"); + + ImportFileType temp; + temp.iType = ImportFileType::EN_STRUCT; + temp.sNamespace = sNamespace; + temp.sName = vecNames[1]; + + item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp)); + } + + vector & es = namespaces[ii]->getAllEnumPtr(); + for (size_t iii = 0; iii < es.size(); iii++) + { + vector vecNames = TC_Common::sepstr(es[iii]->getSid(), "::"); + + ImportFileType temp; + temp.iType = ImportFileType::EN_ENUM; + temp.sNamespace = sNamespace; + temp.sName = vecNames[1]; + + item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp)); + + vector & eMember = es[iii]->getAllMemberPtr(); + for (size_t iiii = 0; iiii < eMember.size(); iiii++) + { + ImportFileType temp; + temp.iType = ImportFileType::EN_ENUM_VALUE; + temp.sNamespace = sNamespace; + temp.sTypeName = vecNames[1]; + temp.sName = eMember[iiii]->getId(); + + #ifdef DUMP_FIND_NAME + cout << "GET::::" << temp.sNamespace << "|" << temp.sName << endl; + #endif + + item.mapVars.insert(make_pair(temp.sNamespace + "::" + temp.sName, temp)); + } + } + } + + _mapFiles.insert(make_pair(sFile, item)); + + vector vecFiles = contexts[i]->getIncludes(); + for (size_t ii = 0; ii < vecFiles.size(); ii++) + { + string sFileName = TC_File::extractFilePath(vecFiles[ii]) + TC_File::excludeFileExt(TC_File::extractFileName(vecFiles[ii])) + "." + TC_Common::lower(IDL_TYPE); + + scan(sFileName, false); + } + } + } +} \ No newline at end of file diff --git a/src/idl_util.cpp b/src/idl_util.cpp new file mode 100644 index 0000000..f6dc1f5 --- /dev/null +++ b/src/idl_util.cpp @@ -0,0 +1,440 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "code_generator.h" + +string CodeGenerator::toFunctionName(const TypeIdPtr& pPtr, const string& sAction) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return sAction + "Boolean"; + case Builtin::KindString : return sAction + "String"; + case Builtin::KindByte : return sAction + "Int8"; + case Builtin::KindShort : return sAction + (bPtr->isUnsigned() ? "UInt8" : "Int16"); + case Builtin::KindInt : return sAction + (bPtr->isUnsigned() ? "UInt16" : "Int32"); + case Builtin::KindLong : return sAction + (bPtr->isUnsigned() ? "UInt32" : "Int64"); + case Builtin::KindFloat : return sAction + "Float"; + case Builtin::KindDouble : return sAction + "Double"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); + if (vPtr) + { + BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); + if (vbPtr && vbPtr->kind() == Builtin::KindByte) + { + return sAction + "Bytes"; + } + + return sAction + "List"; + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr()); + if (sPtr) + { + return sAction + "Struct"; + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); + if (ePtr) + { + return sAction + "Int32"; + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr()); + if (mPtr) + { + return sAction + "Map"; + } + + return ""; +} + +bool CodeGenerator::isRawOrString(const TypePtr& pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + if (_bUseStringRepresent && bPtr->kind() == Builtin::KindLong) + { + return true; + } + + if (_bStringBinaryEncoding && bPtr->kind() == Builtin::KindString) + { + return true; + } + } + + return false; +} + +string CodeGenerator::getClassName(const TypePtr& pPtr) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return "bool"; + case Builtin::KindString : return "string"; + case Builtin::KindByte : return "char"; + case Builtin::KindShort : return "short"; + case Builtin::KindInt : return "int32"; + case Builtin::KindLong : return "int64"; + case Builtin::KindFloat : return "float"; + case Builtin::KindDouble : return "double"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + return "list(" + getDataType(vPtr->getTypePtr()) + ")"; + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) + { + vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return findName(vecNames[0], vecNames[1]); + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) + { + return "map(" + getClassName(mPtr->getLeftTypePtr()) + ", " + getClassName(mPtr->getRightTypePtr()) + ")"; + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + return "int32"; + } + + return "void"; +} + +string CodeGenerator::getDataType(const TypePtr& pPtr) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return IDL_NAMESPACE_STR + "Stream.Boolean"; + case Builtin::KindString : return IDL_NAMESPACE_STR + "Stream.String"; + case Builtin::KindByte : return IDL_NAMESPACE_STR + "Stream.Int8"; + case Builtin::KindShort : return IDL_NAMESPACE_STR + "Stream.Int16"; + case Builtin::KindInt : return IDL_NAMESPACE_STR + "Stream.Int32"; + case Builtin::KindLong : return IDL_NAMESPACE_STR + "Stream.Int64"; + case Builtin::KindFloat : return IDL_NAMESPACE_STR + "Stream.Float"; + case Builtin::KindDouble : return IDL_NAMESPACE_STR + "Stream.Double"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); + if (vbPtr && vbPtr->kind() == Builtin::KindByte) + { + return IDL_NAMESPACE_STR + "Stream.BinBuffer"; + } + + return IDL_NAMESPACE_STR + "Stream.List(" + getDataType(vPtr->getTypePtr()) + (isRawOrString(vPtr->getTypePtr()) ? ", 1" : "") + ")"; + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) + { + vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return findName(vecNames[0], vecNames[1]); + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) + { + bool bLeft = isRawOrString(mPtr->getLeftTypePtr()); + bool bRight = isRawOrString(mPtr->getRightTypePtr()); + + if (!bRight && !bLeft) { + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ")"; + } else if (bRight && bLeft) { + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1, 1)"; + } else if (bRight) { + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 0, 1)"; + } else if (bLeft) { + return IDL_NAMESPACE_STR + "Stream.Map(" + getDataType(mPtr->getLeftTypePtr()) + ", " + getDataType(mPtr->getRightTypePtr()) + ", 1)"; + } else { + assert(false); + } + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return findName(vecNames[0], vecNames[1]); + } + + assert(false); + return ""; +} + +string CodeGenerator::getDtsType(const TypePtr &pPtr, const bool bStream) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : return "boolean"; + case Builtin::KindString : return _bStringBinaryEncoding ? (bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer") : "string"; + case Builtin::KindByte : return "number"; + case Builtin::KindShort : return "number"; + case Builtin::KindInt : return "number"; + case Builtin::KindLong : return _bUseStringRepresent ? "string" : "number"; + case Builtin::KindFloat : return "number"; + case Builtin::KindDouble : return "number"; + default : assert(false); + } + } + + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); + if (vbPtr && vbPtr->kind() == Builtin::KindByte) + { + return bStream ? (IDL_NAMESPACE_STR + "Stream.BinBuffer") : "Buffer"; + } + return (bStream ? (IDL_NAMESPACE_STR + "Stream.List") : "Array") + string("<") + getDtsType(vPtr->getTypePtr(), bStream) + string(">"); + } + + StructPtr sPtr = StructPtr::dynamicCast(pPtr); + if (sPtr) + { + vector vecNames = TC_Common::sepstr(sPtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return findName(vecNames[0], vecNames[1]) + (bStream ? "" : "$OBJ"); + } + + MapPtr mPtr = MapPtr::dynamicCast(pPtr); + if (mPtr) + { + if (bStream) + { + return IDL_NAMESPACE_STR + "Stream.Map<" + getDtsType(mPtr->getLeftTypePtr(), bStream) + ", " + getDtsType(mPtr->getRightTypePtr(), bStream) + ">"; + } + else + { + const string& sLeftType = getDtsType(mPtr->getLeftTypePtr(), bStream); + if (sLeftType == "number" || sLeftType == "string") + { + return "{[key: " + getDtsType(mPtr->getLeftTypePtr(), bStream) + "]: " + getDtsType(mPtr->getRightTypePtr(), bStream) + "}"; + } + else if (isSimple(mPtr->getLeftTypePtr()) && sLeftType != "Buffer") + { + return "object"; + } + else + { + return ""; + } + } + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); + assert(vecNames.size() == 2); + + return findName(vecNames[0], vecNames[1]); + } + + assert(false); + return ""; +} + +bool CodeGenerator::isSimple(const TypePtr & pPtr) const +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); + if (bPtr) + { + return true; + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); + if (ePtr) + { + return true; + } + + return false; +} + +bool CodeGenerator::isBinBuffer(const TypePtr & pPtr) const +{ + VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); + if (vPtr) + { + BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); + if (vbPtr && vbPtr->kind() == Builtin::KindByte) + { + return true; + } + + } + + return false; +} + +string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace) +{ + return getDefault(pPtr, sDefault, sNamespace, true); +} + +string CodeGenerator::getDefault(const TypeIdPtr & pPtr, const string &sDefault, const string& sNamespace, const bool bGlobal) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); + if (bPtr) + { + switch (bPtr->kind()) + { + case Builtin::KindBool : + return sDefault.empty() ? "false" : sDefault; + case Builtin::KindString : + { + if (_bStringBinaryEncoding) + { + return IDL_NAMESPACE_STR + "Stream.BinBuffer.from(\"" + TC_Common::replace(sDefault, "\"", "\\\"") + "\").toNodeBufferUnSafe()"; + } + else + { + return "\"" + TC_Common::replace(sDefault, "\"", "\\\"") + "\""; + } + } + case Builtin::KindByte : // [[fallthrough]] + case Builtin::KindShort : // [[fallthrough]] + case Builtin::KindInt : // [[fallthrough]] + case Builtin::KindLong : + { + string sTemp = TC_Common::trim(sDefault); + if (sTemp.empty()) + { + sTemp = "0"; + } + else + { + if (TC_Common::tostr(TC_Common::strto(sTemp)) != sTemp) + { + //有可能是枚举值,在枚举值中查找 + vector vecNames = TC_Common::sepstr(sDefault, "::"); + if (vecNames.size() == 2) + { + sTemp = findName(vecNames[0], vecNames[1]); + } + else + { + sTemp = findName(sNamespace, sDefault); + } + } + } + + if (sTemp.empty()) + { + sTemp = "0"; + } + + if (_bUseStringRepresent) + { + if (bPtr->kind() == Builtin::KindLong) + { + sTemp = "\"" + sTemp + "\""; + } + } + + return sTemp; + } + case Builtin::KindFloat : // [[fallthrough]] + case Builtin::KindDouble : + return sDefault.empty()?"0.0":sDefault; + default : + assert(false); + } + } + + EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); + if (ePtr) + { + if (sDefault.empty()) + { + vector& eMember = ePtr->getAllMemberPtr(); + if (eMember.size() > 0) + { + vector vecNames = TC_Common::sepstr(ePtr->getSid(), "::"); + + string sModule = findName(vecNames[0], eMember[0]->getId()); + + return sModule; + } + } + + if (!TC_Common::isdigit(sDefault)) + { + string s1 = sNamespace; + string s2 = sDefault; + + string::size_type index = sDefault.find("::"); + if (index != string::npos) + { + s1 = sDefault.substr(0, index); + s2 = sDefault.substr(index + 2); + } + + string sModule = findName(s1, s2); + + assert(!sModule.empty()); + + return sModule; + } + + return sDefault; + } + + if (bGlobal) + { + return "new " + getDataType(pPtr->getTypePtr()); + } + + return sDefault; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..304708c --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,198 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "util/tc_option.h" +#include "code_generator.h" + +void version() +{ + cout << "v" << GENERATOR_VERSION << endl; +} + +void usage() +{ + cout << "Version : " << GENERATOR_VERSION << endl; + cout << "Usage : " << EXECUTE_FILENAME << " [OPTION] " << "*." << TC_Common::lower(IDL_TYPE) << " file" << endl; + cout << " --version print " << EXECUTE_FILENAME << " version" << endl; + cout << " --rpc-path=[DIRECTORY] specify the path of rpc module." << endl; + cout << " --stream-path=[DIRECTORY] specify the path of stream module." << endl; + cout << " --allow-reserved-namespace allow you to use reserved word as a namespace." << endl; + cout << " --dir=DIRECTORY generate source file to DIRECTORY." << endl; + cout << " --relative use current path." << endl; + cout << " --base=DIRECTORY where to search " << IDL_TYPE << " files." << endl; + cout << " --r generate source all " << IDL_TYPE << " files." << endl; + cout << " --r-minimal minimize the dependent members." << endl; + cout << " --r-reserved list of names(split by \",\") that should be keeped." << endl; + cout << " --client just for client side source file." << endl; + cout << " --server just for server side source file." << endl; + cout << " --dts generate d.ts file." << endl; + cout << " --use-string-represent use string represent long type." << endl; + cout << " --string-binary-encoding get string raw bytes ." << endl; + cout << " --optimize=[0|s] support \"s\" to reduce code size, default is 0." << endl; + cout << endl; + cout << EXECUTE_FILENAME << " support type: boolean char short int long float double list map" << endl; + + exit(0); +} + +void check(vector &vFiles) +{ + for(size_t i = 0; i < vFiles.size(); i++) + { + string ext = TC_File::extractFileExt(vFiles[i]); + if(ext == TC_Common::lower(IDL_TYPE)) + { + if(!TC_File::isFileExist(vFiles[i])) + { + cerr << "file '" << vFiles[i] << "' not exists" << endl; + usage(); + exit(0); + } + } + else + { + cerr << "only support "<< TC_Common::lower(IDL_TYPE) << " file." << endl; + usage(); + exit(0); + } + } +} + + + +int main(int argc, char* argv[]) +{ + if(argc < 2) + { + usage(); + } + + try + { + TC_Option option; + option.decode(argc, argv); + vector vFiles = option.getSingle(); + check(vFiles); + + if (option.hasParam("version")) + { + version(); + return 0; + } + + if(option.hasParam("help")) + { + usage(); + return 0; + } + + if(option.hasParam("base")) + { + if (::chdir(option.getValue("base").c_str()) != 0) { + return -1; + } + } + + #define ALLOW_USE_RESERVED_NAMESPACE_V(name, keeped) \ + g_parse->set##name(keeped); + #define ALLOW_USE_RESERVED_NAMESPACE_BASE(name, keeped) \ + ALLOW_USE_RESERVED_NAMESPACE_V(name, keeped) + #define ALLOW_USE_RESERVED_NAMESPACE(keeped) \ + ALLOW_USE_RESERVED_NAMESPACE_BASE(IDL_NAMESPACE, keeped) + + ALLOW_USE_RESERVED_NAMESPACE(option.hasParam("allow-reserved-namespace")); + + #undef ALLOW_USE_RESERVED_NAMESPACE + #undef ALLOW_USE_RESERVED_NAMESPACE_BASE + #undef ALLOW_USE_RESERVED_NAMESPACE_V + + g_parse->setUseCurrentPath(option.hasParam("relative")); + + CodeGenerator generator; + generator.setRpcPath(option.hasParam("rpc-path")?option.getValue("rpc-path"):RPC_MODULE_PATH); + generator.setStreamPath(option.hasParam("stream-path")?option.getValue("stream-path"):STREAM_MODULE_PATH); + generator.setEnableClient(option.hasParam("client")); + generator.setEnableServer(option.hasParam("server")); + generator.setTargetPath(option.hasParam("dir")?option.getValue("dir"):"./"); + generator.setUseSpecialPath(option.hasParam("relative")); + generator.setUseStringRepresent(option.hasParam("use-string-represent")); + generator.setStringBinaryEncoding(option.hasParam("string-binary-encoding")); + generator.setEnableDTS(option.hasParam("dts")); + + if (option.hasParam("optimize")) + { + string level = TC_Common::lower(option.getValue("optimize")); + if (level == "s") + { + generator.setOptimize(CodeGenerator::Os); + } + else + { + generator.setOptimize(CodeGenerator::O0); + } + } + + bool _bRecursive = option.hasParam("r"); + bool _bMinimalMembers = option.hasParam("r-minimal"); + + if (option.hasParam("r-reserved")) + { + set vMembers; + vector vReserved = TC_Common::sepstr(option.getValue("r-reserved"), ","); + for (size_t i = 0; i < vReserved.size(); i++) + { + if (vReserved[i].empty()) + { + continue; + } + + if (TC_Common::sepstr(vReserved[i], "::").size() == 2) + { + vMembers.insert(TC_Common::trim(vReserved[i])); + } else { + cerr << "reserved member must be match :: pattern" << endl; + return 0; + } + } + + if (vMembers.size() > 0) + { + _bMinimalMembers = true; + generator.setDependent(vMembers); + } + } + + if (!_bRecursive && _bMinimalMembers) + { + cerr << "Missing --r flag" << endl; + return 0; + } + + generator.setRecursive(_bRecursive); + generator.setMinimalMembers(_bMinimalMembers); + + for (size_t i = 0; i < vFiles.size(); i++) + { + generator.createFile(vFiles[i], true); + } + } + catch(exception& e) + { + cerr< 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN (yy_start) = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START (((yy_start) - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart(yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +extern yy_size_t yyleng; + +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + #define YY_LINENO_REWIND_TO(dst) \ + do {\ + const char *p;\ + for ( p = yy_cp-1; p >= (dst); --p)\ + if ( *p == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = (yy_hold_char); \ + YY_RESTORE_YY_MORE_OFFSET \ + (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, (yytext_ptr) ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* Stack of input buffers. */ +static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ +static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ +static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ + ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; +static int yy_n_chars; /* number of characters read into yy_ch_buf */ +yy_size_t yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 0; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart (FILE *input_file ); +void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); +YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); +void yy_delete_buffer (YY_BUFFER_STATE b ); +void yy_flush_buffer (YY_BUFFER_STATE b ); +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); +void yypop_buffer_state (void ); + +static void yyensure_buffer_stack (void ); +static void yy_load_buffer_state (void ); +static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); + +#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) + +YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); +YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); +YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len ); + +void *yyalloc (yy_size_t ); +void *yyrealloc (void *,yy_size_t ); +void yyfree (void * ); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer(yyin,YY_BUF_SIZE ); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +typedef unsigned char YY_CHAR; + +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; + +typedef int yy_state_type; + +extern int yylineno; + +int yylineno = 1; + +extern char *yytext; +#ifdef yytext_ptr +#undef yytext_ptr +#endif +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state (void ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); +static int yy_get_next_buffer (void ); +#if defined(__GNUC__) && __GNUC__ >= 3 +__attribute__((__noreturn__)) +#endif +static void yy_fatal_error (yyconst char msg[] ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + (yytext_ptr) = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + (yy_hold_char) = *yy_cp; \ + *yy_cp = '\0'; \ + (yy_c_buf_p) = yy_cp; + +#define YY_NUM_RULES 13 +#define YY_END_OF_BUFFER 14 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[52] = + { 0, + 0, 0, 0, 0, 14, 12, 11, 11, 8, 12, + 12, 12, 12, 9, 9, 12, 6, 13, 13, 0, + 0, 9, 9, 10, 5, 4, 10, 9, 0, 0, + 3, 0, 7, 6, 0, 2, 0, 0, 10, 0, + 10, 9, 0, 0, 10, 0, 0, 0, 1, 1, + 0 + } ; + +static yyconst YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 5, 6, 1, 1, 1, 1, 7, + 1, 8, 9, 1, 10, 11, 12, 13, 14, 14, + 14, 14, 14, 14, 14, 15, 15, 16, 1, 1, + 1, 1, 1, 1, 17, 17, 17, 17, 18, 19, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 1, 1, 1, 1, 20, 1, 17, 17, 21, 22, + + 23, 19, 20, 20, 24, 20, 20, 25, 20, 26, + 20, 20, 20, 20, 20, 20, 27, 20, 20, 28, + 20, 20, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst YY_CHAR yy_meta[29] = + { 0, + 1, 2, 3, 2, 1, 1, 2, 1, 4, 4, + 1, 1, 5, 5, 5, 1, 6, 6, 6, 2, + 6, 6, 6, 2, 2, 2, 2, 2 + } ; + +static yyconst flex_uint16_t yy_base[58] = + { 0, + 0, 0, 119, 118, 122, 125, 125, 125, 125, 97, + 18, 21, 29, 31, 25, 104, 48, 125, 114, 83, + 43, 0, 0, 47, 125, 125, 0, 76, 38, 0, + 125, 65, 125, 71, 89, 88, 71, 54, 125, 66, + 69, 0, 52, 72, 76, 49, 49, 20, 38, 28, + 125, 95, 100, 106, 109, 110, 113 + } ; + +static yyconst flex_int16_t yy_def[58] = + { 0, + 51, 1, 52, 52, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 14, 51, 53, 51, 54, 51, + 51, 14, 15, 51, 51, 51, 24, 14, 55, 56, + 51, 51, 51, 53, 54, 54, 51, 57, 51, 51, + 51, 56, 51, 51, 51, 51, 51, 51, 51, 51, + 0, 51, 51, 51, 51, 51, 51 + } ; + +static yyconst flex_uint16_t yy_nxt[154] = + { 0, + 6, 7, 8, 7, 9, 10, 6, 6, 11, 11, + 12, 13, 14, 15, 15, 16, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 21, 50, + 22, 23, 23, 24, 24, 24, 25, 23, 23, 50, + 26, 27, 49, 28, 28, 23, 40, 40, 29, 32, + 32, 32, 51, 29, 33, 24, 24, 24, 30, 24, + 24, 24, 44, 44, 38, 39, 32, 32, 32, 38, + 48, 33, 32, 32, 32, 47, 46, 33, 41, 41, + 41, 41, 41, 41, 45, 45, 45, 39, 45, 45, + 45, 43, 36, 36, 39, 18, 18, 18, 18, 18, + + 18, 34, 34, 51, 34, 34, 35, 35, 37, 35, + 35, 35, 41, 41, 42, 42, 45, 45, 36, 31, + 20, 51, 19, 19, 5, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51 + } ; + +static yyconst flex_int16_t yy_chk[154] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 11, 50, + 11, 11, 11, 12, 12, 12, 13, 15, 15, 49, + 13, 14, 48, 14, 14, 14, 29, 29, 14, 17, + 17, 17, 15, 14, 17, 21, 21, 21, 14, 24, + 24, 24, 38, 38, 24, 24, 32, 32, 32, 24, + 47, 32, 34, 34, 34, 46, 43, 34, 40, 40, + 40, 41, 41, 41, 44, 44, 44, 41, 45, 45, + 45, 37, 36, 35, 45, 52, 52, 52, 52, 52, + + 52, 53, 53, 28, 53, 53, 54, 54, 20, 54, + 54, 54, 55, 55, 56, 56, 57, 57, 19, 16, + 10, 5, 4, 3, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, + 51, 51, 51 + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[14] = + { 0, +0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, }; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +extern int yy_flex_debug; +int yy_flex_debug = 0; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "tars.l" +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ +#line 20 "tars.l" +#include +#include +#include +#include +#include +#include + +#define YYSTYPE GrammarBasePtr + +#include "parse.h" +#include "tars.tab.hpp" + +using namespace std; + +extern "C" +{ + int yywrap() + { + return 1; + } +} + +struct include_file_state +{ + YY_BUFFER_STATE state; + string file; +}; + +#define MAX_INCLUDE_DEPTH 200 +include_file_state include_file_stack[MAX_INCLUDE_DEPTH]; +int include_file_stack_ptr = 0; + + +#line 588 "tars.lex.cpp" + +#define INITIAL 0 +#define INCL 1 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +static int yy_init_globals (void ); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy (void ); + +int yyget_debug (void ); + +void yyset_debug (int debug_flag ); + +YY_EXTRA_TYPE yyget_extra (void ); + +void yyset_extra (YY_EXTRA_TYPE user_defined ); + +FILE *yyget_in (void ); + +void yyset_in (FILE * _in_str ); + +FILE *yyget_out (void ); + +void yyset_out (FILE * _out_str ); + +yy_size_t yyget_leng (void ); + +char *yyget_text (void ); + +int yyget_lineno (void ); + +void yyset_lineno (int _line_number ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap (void ); +#else +extern int yywrap (void ); +#endif +#endif + +#ifndef YY_NO_UNPUT + + static void yyunput (int c,char *buf_ptr ); + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (void ); +#else +static int input (void ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex (void); + +#define YY_DECL int yylex (void) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + + if ( !(yy_init) ) + { + (yy_init) = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! (yy_start) ) + (yy_start) = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_load_buffer_state( ); + } + + { +#line 63 "tars.l" + + +#line 810 "tars.lex.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = (yy_c_buf_p); + + /* Support of yytext. */ + *yy_cp = (yy_hold_char); + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = (yy_start); +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 52 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 125 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + yy_size_t yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + yylineno++; +; + } + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = (yy_hold_char); + yy_cp = (yy_last_accepting_cpos); + yy_current_state = (yy_last_accepting_state); + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 65 "tars.l" +{ BEGIN(INCL); } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 67 "tars.l" +{ + if ( include_file_stack_ptr >= MAX_INCLUDE_DEPTH ) + { + g_parse->error("Includes nested too deeply" ); + } + + string file; + bool b = g_parse->getFilePath( yytext, file); + g_parse->currentContextPtr()->addInclude(file); + + //该文件没解析过 + if(b) + { + include_file_stack[include_file_stack_ptr].state = YY_CURRENT_BUFFER; + include_file_stack[include_file_stack_ptr].file = file; + include_file_stack_ptr++; + + yyin = fopen( file.c_str(), "r" ); + if ( !yyin ) + { + g_parse->error("can't open file:" + file); + } + + yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE ) ); + + g_parse->pushFile(file); + } + BEGIN(INITIAL); +} + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(INCL): +#line 97 "tars.l" +{ + --include_file_stack_ptr; + if ( include_file_stack_ptr < 0 ) + { + include_file_stack_ptr = 0; + yyterminate(); + } + else + { + yy_delete_buffer(YY_CURRENT_BUFFER ); + fclose(yyin); + yy_switch_to_buffer(include_file_stack[include_file_stack_ptr].state ); + g_parse->popFile(); + } +} + YY_BREAK +case 3: +YY_RULE_SETUP +#line 113 "tars.l" +{ + return TARS_SCOPE_DELIMITER; +} + YY_BREAK +case 4: +YY_RULE_SETUP +#line 117 "tars.l" +{ + // C++的注释风格 + bool end = false; + while(!end) + { + int input = yyinput(); + if(input == '\n') + { + g_parse->nextLine(); + } + + if(input == '\n' || input == EOF) + { + end = true; + } + } +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 135 "tars.l" +{ + // C的注释风格 + bool end = false; + string comment = yytext + 2; + while(!end) + { + int input = yyinput(); + switch(input) + { + case '*': + { + int nextInput = yyinput(); + if(nextInput == '/') + { + end = true; + } + else + { + comment += static_cast(input); + unput(nextInput); + } + break; + } + case '\n': + { + comment += static_cast(input); + g_parse->nextLine(); + break; + } + case EOF: + { + //到文件尾部, 但是没有出现*/ + g_parse->error("EOF in comment"); + end = true; + break; + } + default: + { + comment += static_cast(input); + break; + } + } + } + if(comment[0] == '*') + { + //注释内容暂时未处理 + } +} + YY_BREAK +case 6: +YY_RULE_SETUP +#line 184 "tars.l" +{ + StringGrammarPtr ident = new StringGrammar; + ident->v = yytext; + yylval = ident; + return g_parse->checkKeyword(ident->v); +} + YY_BREAK +case 7: +/* rule 7 can match eol */ +YY_RULE_SETUP +#line 191 "tars.l" +{ + StringGrammarPtr ident = new StringGrammar; + ident->v = yytext; + ident->v.erase(ident->v.find_first_of(" \t\v\n\r\f(")); + + yylval = ident; + + return TARS_OP; +} + YY_BREAK +case 8: +YY_RULE_SETUP +#line 201 "tars.l" +{ + StringGrammarPtr str = new StringGrammar; + bool end = false; + while(!end) + { + int input = yyinput(); + switch(input) + { + case '"': + { + end = true; + break; + } + case '\n': + { + g_parse->error("newline in string"); + break; + } + case EOF: + { + g_parse->error("EOF in string"); + break; + } + case '\\': + { + static string specialChars = "nrtvfab?"; + static string octalChars = "0123"; + + char nextInput = static_cast(yyinput()); + if(nextInput == '\\' || nextInput == '"' || nextInput == '\'') + { + str->v += nextInput; + } + else if(specialChars.find(nextInput) != string::npos) + { + str->v += '\\'; + str->v += nextInput; + } + else if(octalChars.find(nextInput) != string::npos) + { + static string octalDigits = "01234567"; + + unsigned short us = nextInput - '0'; + if(octalDigits.find_first_of(nextInput = static_cast(yyinput())) != string::npos) + { + us = us * 8 + nextInput - '0'; + if(octalDigits.find_first_of(nextInput = static_cast(yyinput())) != string::npos) + { + us = us * 8 + nextInput - '0'; + } + else + { + unput(nextInput); + } + } + else + { + unput(nextInput); + } + + if(us == 0) + { + g_parse->error("illegal NUL character in string constant"); + } + str->v += static_cast(us); + } + else if(nextInput == 'x') + { + long long ull = 0; + while(isxdigit(nextInput = static_cast(yyinput()))) + { + ull *= 16; + if(isdigit(nextInput)) + { + ull += nextInput - '0'; + } + else if(islower(nextInput)) + { + ull += nextInput - 'a' + 10; + } + else + { + ull += nextInput - 'A' + 10; + } + } + + unput(nextInput); + + if(ull == 0) + { + g_parse->error("illegal NUL character in string constant"); + } + str->v += static_cast(ull); + } + else + { + str->v += static_cast(input); + } + + break; + } + default: + { + str->v += static_cast(input); + break; + } + } + } + yylval = str; + return TARS_STRING_LITERAL; +} + YY_BREAK +case 9: +YY_RULE_SETUP +#line 313 "tars.l" +{ + errno = 0; + IntergerGrammarPtr ptr = new IntergerGrammar; + yylval = ptr; + + string value = yytext; + const char* beg = value.c_str(); + char* end = 0; + + ptr->v = strtoll(beg, &end, 0); + if(!(errno == 0 && beg != end)) + { + assert(ptr->v != 0); + string err = "integer constant `"; + err += value; + err += "' out of range"; + g_parse->error(err); + } + + return TARS_CONST_INTEGER; +} + YY_BREAK +case 10: +YY_RULE_SETUP +#line 335 "tars.l" +{ + errno = 0; + FloatGrammarPtr ptr = new FloatGrammar; + yylval = ptr; + + string value(yytext); + + char lastChar = value[value.size() - 1]; + if(lastChar == 'f' || lastChar == 'F') + { + value = value.substr(0, value.size() - 1); + } + + ptr->v = strtod(value.c_str(), 0); + if((errno == ERANGE) && (ptr->v == HUGE_VAL || ptr->v == -HUGE_VAL)) + { + string err = "float point constant `"; + err += value; + err += "' too large (overflow)"; + g_parse->error(err); + } + else if(errno == ERANGE && ptr->v == 0) + { + string err = "float point constant `"; + err += value; + err += "' too small (underflow)"; + g_parse->error(err); + } + return TARS_CONST_FLOAT; +} + YY_BREAK +case 11: +/* rule 11 can match eol */ +YY_RULE_SETUP +#line 366 "tars.l" +{ + if(yytext[0] == '\n') + { + g_parse->nextLine(); + } +} + YY_BREAK +case 12: +YY_RULE_SETUP +#line 373 "tars.l" +{ + if(yytext[0] < 32 || yytext[0] > 126) + { + stringstream s; + s << "illegal input character: '\\"; + s.width(3); + s.fill('0'); + s << oct << static_cast(static_cast(yytext[0])); + s << "'"; + + g_parse->error(s.str()); + return BAD_CHAR; + } + return yytext[0]; +} + YY_BREAK +case 13: +YY_RULE_SETUP +#line 389 "tars.l" +ECHO; + YY_BREAK +#line 1247 "tars.lex.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = (yy_hold_char); + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++(yy_c_buf_p); + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = (yy_c_buf_p); + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_END_OF_FILE: + { + (yy_did_buffer_switch_on_eof) = 0; + + if ( yywrap( ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = + (yytext_ptr) + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + (yy_c_buf_p) = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + + yy_current_state = yy_get_previous_state( ); + + yy_cp = (yy_c_buf_p); + yy_bp = (yytext_ptr) + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (void) +{ + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = (yytext_ptr); + yy_size_t number_to_move, i; + int ret_val; + + if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (yy_size_t) ((yy_c_buf_p) - (yytext_ptr)) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) ((yy_c_buf_p) - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + (yy_n_chars), num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + if ( (yy_n_chars) == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart(yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((int) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + int new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + (yy_n_chars) += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + + (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (void) +{ + yy_state_type yy_current_state; + char *yy_cp; + + yy_current_state = (yy_start); + + for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 52 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) +{ + int yy_is_jam; + char *yy_cp = (yy_c_buf_p); + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + (yy_last_accepting_state) = yy_current_state; + (yy_last_accepting_cpos) = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 52 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 51); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + + static void yyunput (int c, char * yy_bp ) +{ + char *yy_cp; + + yy_cp = (yy_c_buf_p); + + /* undo effects of setting up yytext */ + *yy_cp = (yy_hold_char); + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + yy_size_t number_to_move = (yy_n_chars) + 2; + char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + char *source = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + + while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + + if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + if ( c == '\n' ){ + --yylineno; + } + + (yytext_ptr) = yy_bp; + (yy_hold_char) = *yy_cp; + (yy_c_buf_p) = yy_cp; +} + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (void) +#else + static int input (void) +#endif + +{ + int c; + + *(yy_c_buf_p) = (yy_hold_char); + + if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + /* This was really a NUL. */ + *(yy_c_buf_p) = '\0'; + + else + { /* need more input */ + yy_size_t offset = (yy_c_buf_p) - (yytext_ptr); + ++(yy_c_buf_p); + + switch ( yy_get_next_buffer( ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart(yyin ); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( ) ) + return EOF; + + if ( ! (yy_did_buffer_switch_on_eof) ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + (yy_c_buf_p) = (yytext_ptr) + offset; + break; + } + } + } + + c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ + *(yy_c_buf_p) = '\0'; /* preserve yytext */ + (yy_hold_char) = *++(yy_c_buf_p); + + if ( c == '\n' ) + + yylineno++; +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file ) +{ + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer(yyin,YY_BUF_SIZE ); + } + + yy_init_buffer(YY_CURRENT_BUFFER,input_file ); + yy_load_buffer_state( ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) +{ + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + (yy_did_buffer_switch_on_eof) = 1; +} + +static void yy_load_buffer_state (void) +{ + (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + (yy_hold_char) = *(yy_c_buf_p); +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = (yy_size_t)size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer(b,file ); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * + */ + void yy_delete_buffer (YY_BUFFER_STATE b ) +{ + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree((void *) b->yy_ch_buf ); + + yyfree((void *) b ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) + +{ + int oerrno = errno; + + yy_flush_buffer(b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * + */ + void yy_flush_buffer (YY_BUFFER_STATE b ) +{ + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) +{ + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *(yy_c_buf_p) = (yy_hold_char); + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + (yy_buffer_stack_top)++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * + */ +void yypop_buffer_state (void) +{ + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + if ((yy_buffer_stack_top) > 0) + --(yy_buffer_stack_top); + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( ); + (yy_did_buffer_switch_on_eof) = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (void) +{ + yy_size_t num_to_alloc; + + if (!(yy_buffer_stack)) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + (yy_buffer_stack_max) = num_to_alloc; + (yy_buffer_stack_top) = 0; + return; + } + + if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = (yy_buffer_stack_max) + grow_size; + (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc + ((yy_buffer_stack), + num_to_alloc * sizeof(struct yy_buffer_state*) + ); + if ( ! (yy_buffer_stack) ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); + (yy_buffer_stack_max) = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer(b ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) +{ + + return yy_scan_bytes(yystr,strlen(yystr) ); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len ) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) yyalloc(n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer(buf,n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg ) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = (yy_hold_char); \ + (yy_c_buf_p) = yytext + yyless_macro_arg; \ + (yy_hold_char) = *(yy_c_buf_p); \ + *(yy_c_buf_p) = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the current line number. + * + */ +int yyget_lineno (void) +{ + + return yylineno; +} + +/** Get the input stream. + * + */ +FILE *yyget_in (void) +{ + return yyin; +} + +/** Get the output stream. + * + */ +FILE *yyget_out (void) +{ + return yyout; +} + +/** Get the length of the current token. + * + */ +yy_size_t yyget_leng (void) +{ + return yyleng; +} + +/** Get the current token. + * + */ + +char *yyget_text (void) +{ + return yytext; +} + +/** Set the current line number. + * @param _line_number line number + * + */ +void yyset_lineno (int _line_number ) +{ + + yylineno = _line_number; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str ) +{ + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str ) +{ + yyout = _out_str ; +} + +int yyget_debug (void) +{ + return yy_flex_debug; +} + +void yyset_debug (int _bdebug ) +{ + yy_flex_debug = _bdebug ; +} + +static int yy_init_globals (void) +{ + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + /* We do not touch yylineno unless the option is enabled. */ + yylineno = 1; + + (yy_buffer_stack) = 0; + (yy_buffer_stack_top) = 0; + (yy_buffer_stack_max) = 0; + (yy_c_buf_p) = (char *) 0; + (yy_init) = 0; + (yy_start) = 0; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (void) +{ + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer(YY_CURRENT_BUFFER ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(); + } + + /* Destroy the stack itself. */ + yyfree((yy_buffer_stack) ); + (yy_buffer_stack) = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( ); + + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) +{ + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s ) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *yyalloc (yy_size_t size ) +{ + return (void *) malloc( size ); +} + +void *yyrealloc (void * ptr, yy_size_t size ) +{ + + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void yyfree (void * ptr ) +{ + free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 389 "tars.l" + + + + diff --git a/third_partly/tarsgrammar/tars.tab.cpp b/third_partly/tarsgrammar/tars.tab.cpp new file mode 100644 index 0000000..1838737 --- /dev/null +++ b/third_partly/tarsgrammar/tars.tab.cpp @@ -0,0 +1,3083 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison implementation for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "3.0.4" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 0 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + + + + +/* Copy the first part of user declarations. */ +#line 17 "tars.y" /* yacc.c:339 */ + +#include +#include +#include + +using namespace std; + +#define YYSTYPE GrammarBasePtr + +#include "parse.h" +#define YYDEBUG 1 +#define YYINITDEPTH 10000 + +#line 80 "tars.tab.cpp" /* yacc.c:339 */ + +# ifndef YY_NULLPTR +# if defined __cplusplus && 201103L <= __cplusplus +# define YY_NULLPTR nullptr +# else +# define YY_NULLPTR 0 +# endif +# endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* In a future release of Bison, this section will be replaced + by #include "tars.tab.hpp". */ +#ifndef YY_YY_TARS_TAB_HPP_INCLUDED +# define YY_YY_TARS_TAB_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TARS_VOID = 258, + TARS_STRUCT = 259, + TARS_BOOL = 260, + TARS_BYTE = 261, + TARS_SHORT = 262, + TARS_INT = 263, + TARS_DOUBLE = 264, + TARS_FLOAT = 265, + TARS_LONG = 266, + TARS_STRING = 267, + TARS_VECTOR = 268, + TARS_MAP = 269, + TARS_NAMESPACE = 270, + TARS_INTERFACE = 271, + TARS_IDENTIFIER = 272, + TARS_OUT = 273, + TARS_OP = 274, + TARS_KEY = 275, + TARS_ROUTE_KEY = 276, + TARS_REQUIRE = 277, + TARS_OPTIONAL = 278, + TARS_CONST_INTEGER = 279, + TARS_CONST_FLOAT = 280, + TARS_FALSE = 281, + TARS_TRUE = 282, + TARS_STRING_LITERAL = 283, + TARS_SCOPE_DELIMITER = 284, + TARS_CONST = 285, + TARS_ENUM = 286, + TARS_UNSIGNED = 287, + BAD_CHAR = 288 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED */ + +/* Copy the second part of user declarations. */ + +#line 165 "tars.tab.cpp" /* yacc.c:358 */ + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#else +typedef signed char yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if defined YYENABLE_NLS && YYENABLE_NLS +# if ENABLE_NLS +# include /* INFRINGES ON USER NAME SPACE */ +# define YY_(Msgid) dgettext ("bison-runtime", Msgid) +# endif +# endif +# ifndef YY_ +# define YY_(Msgid) Msgid +# endif +#endif + +#ifndef YY_ATTRIBUTE +# if (defined __GNUC__ \ + && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \ + || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C +# define YY_ATTRIBUTE(Spec) __attribute__(Spec) +# else +# define YY_ATTRIBUTE(Spec) /* empty */ +# endif +#endif + +#ifndef YY_ATTRIBUTE_PURE +# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__)) +#endif + +#ifndef YY_ATTRIBUTE_UNUSED +# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__)) +#endif + +#if !defined _Noreturn \ + && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112) +# if defined _MSC_VER && 1200 <= _MSC_VER +# define _Noreturn __declspec (noreturn) +# else +# define _Noreturn YY_ATTRIBUTE ((__noreturn__)) +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(E) ((void) (E)) +#else +# define YYUSE(E) /* empty */ +#endif + +#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__ +/* Suppress an incorrect diagnostic about yylval being uninitialized. */ +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\ + _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"") +# define YY_IGNORE_MAYBE_UNINITIALIZED_END \ + _Pragma ("GCC diagnostic pop") +#else +# define YY_INITIAL_VALUE(Value) Value +#endif +#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN +# define YY_IGNORE_MAYBE_UNINITIALIZED_END +#endif +#ifndef YY_INITIAL_VALUE +# define YY_INITIAL_VALUE(Value) /* Nothing. */ +#endif + + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS +# include /* INFRINGES ON USER NAME SPACE */ + /* Use EXIT_SUCCESS as a witness for stdlib.h. */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's 'empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined EXIT_SUCCESS \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include /* INFRINGES ON USER NAME SPACE */ +# ifndef EXIT_SUCCESS +# define EXIT_SUCCESS 0 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined EXIT_SUCCESS +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined EXIT_SUCCESS +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +# define YYCOPY_NEEDED 1 + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + +#if defined YYCOPY_NEEDED && YYCOPY_NEEDED +/* Copy COUNT objects from SRC to DST. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(Dst, Src, Count) \ + __builtin_memcpy (Dst, Src, (Count) * sizeof (*(Src))) +# else +# define YYCOPY(Dst, Src, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (Dst)[yyi] = (Src)[yyi]; \ + } \ + while (0) +# endif +# endif +#endif /* !YYCOPY_NEEDED */ + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 75 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 565 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 46 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 42 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 137 +/* YYNSTATES -- Number of states. */ +#define YYNSTATES 199 + +/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned + by yylex, with out-of-bounds checking. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 288 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM + as returned by yylex, without out-of-bounds checking. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 41, 42, 2, 37, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 43, 34, + 44, 38, 45, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 39, 2, 40, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 35, 2, 36, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33 +}; + +#if YYDEBUG + /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 68, 68, 75, 74, 79, 78, 83, 88, 95, + 99, 103, 107, 110, 114, 124, 123, 146, 159, 170, + 174, 182, 193, 198, 212, 220, 219, 253, 252, 271, + 284, 304, 303, 337, 341, 352, 355, 358, 363, 370, + 376, 393, 422, 423, 434, 436, 447, 458, 470, 482, + 494, 506, 510, 519, 530, 542, 541, 584, 588, 594, + 603, 607, 612, 621, 630, 648, 671, 694, 711, 715, + 719, 723, 732, 742, 752, 760, 768, 776, 789, 809, + 827, 836, 846, 856, 865, 870, 874, 883, 892, 896, + 905, 909, 913, 917, 921, 925, 929, 933, 937, 941, + 945, 949, 953, 957, 975, 979, 983, 987, 996, 1000, + 1009, 1012, 1018, 1031, 1034, 1037, 1040, 1043, 1046, 1049, + 1052, 1055, 1058, 1061, 1064, 1067, 1070, 1073, 1076, 1079, + 1082, 1085, 1088, 1091, 1094, 1097, 1100, 1103 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || 0 +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TARS_VOID", "TARS_STRUCT", "TARS_BOOL", + "TARS_BYTE", "TARS_SHORT", "TARS_INT", "TARS_DOUBLE", "TARS_FLOAT", + "TARS_LONG", "TARS_STRING", "TARS_VECTOR", "TARS_MAP", "TARS_NAMESPACE", + "TARS_INTERFACE", "TARS_IDENTIFIER", "TARS_OUT", "TARS_OP", "TARS_KEY", + "TARS_ROUTE_KEY", "TARS_REQUIRE", "TARS_OPTIONAL", "TARS_CONST_INTEGER", + "TARS_CONST_FLOAT", "TARS_FALSE", "TARS_TRUE", "TARS_STRING_LITERAL", + "TARS_SCOPE_DELIMITER", "TARS_CONST", "TARS_ENUM", "TARS_UNSIGNED", + "BAD_CHAR", "';'", "'{'", "'}'", "','", "'='", "'['", "']'", "')'", + "'*'", "':'", "'<'", "'>'", "$accept", "start", "definitions", "$@1", + "$@2", "definition", "enum_def", "@3", "enum_id", "enumerator_list", + "enumerator", "namespace_def", "@4", "key_def", "$@5", "key_members", + "interface_def", "@6", "interface_id", "interface_exports", + "interface_export", "operation", "operation_preamble", "return_type", + "parameters", "routekey_qualifier", "out_qualifier", "struct_def", "@7", + "struct_id", "struct_exports", "data_member", "struct_type_id", + "const_initializer", "const_def", "type_id", "type", "type_no", "vector", + "map", "scoped_name", "keyword", YY_NULLPTR +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[NUM] -- (External) token number corresponding to the + (internal) symbol number NUM (which must be that of a token). */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 59, 123, 125, 44, 61, 91, + 93, 41, 42, 58, 60, 62 +}; +# endif + +#define YYPACT_NINF -146 + +#define yypact_value_is_default(Yystate) \ + (!!((Yystate) == (-146))) + +#define YYTABLE_NINF -113 + +#define yytable_value_is_error(Yytable_value) \ + 0 + + /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +static const yytype_int16 yypact[] = +{ + 145, -22, 286, 20, 445, 16, 372, 475, 42, -146, + 26, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 11, -146, -146, -146, -146, -146, -146, -146, + -146, -146, 7, 2, -146, 37, 51, 23, 182, 19, + -146, -146, 35, -146, -146, -146, 31, 32, 33, 49, + 102, 66, -2, -146, 386, 415, -146, -146, -146, -146, + 153, -5, 69, -146, 8, 87, 102, 505, 252, 220, + -146, 120, -146, -146, 5, -146, 29, 78, -146, -146, + -146, -146, -146, -146, 79, 86, 88, -146, -146, -146, + -146, -146, 75, 80, 83, -146, 81, -146, 90, 93, + -146, 12, 112, -146, 372, 372, 314, 98, 103, -146, + -146, 107, 122, -146, -146, 533, 127, 108, -146, 153, + -146, 505, 252, -146, 252, -146, -146, 15, 68, 82, + -146, -146, -146, -146, 372, 372, -146, -146, 220, -146, + -146, -26, 109, 118, -146, -146, -146, -146, -146, 343, + -146, -146, -146, 117, 119, -146, 146, -146, -146, 372, + 372, -146, 153, 153, -146, -146, -146, -146, -146 +}; + + /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. + Performed when YYTABLE does not specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 7, 13, 15, 9, 12, 10, 31, 11, 55, 14, + 5, 59, 114, 113, 115, 116, 117, 118, 120, 119, + 121, 122, 124, 125, 126, 57, 127, 123, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 58, 25, + 33, 34, 0, 86, 90, 91, 93, 95, 99, 98, + 97, 100, 0, 0, 110, 0, 0, 0, 85, 88, + 101, 102, 103, 17, 18, 1, 0, 0, 0, 0, + 0, 0, 0, 107, 0, 0, 111, 92, 94, 96, + 0, 80, 0, 84, 0, 0, 0, 24, 0, 0, + 6, 0, 27, 105, 0, 109, 0, 77, 72, 73, + 75, 76, 74, 79, 0, 0, 0, 82, 89, 87, + 112, 4, 21, 0, 20, 22, 0, 43, 0, 37, + 39, 0, 0, 42, 0, 0, 0, 0, 61, 63, + 71, 0, 0, 106, 104, 0, 0, 0, 83, 0, + 16, 24, 0, 32, 0, 54, 53, 0, 0, 0, + 45, 41, 68, 69, 0, 0, 70, 56, 0, 26, + 29, 0, 0, 78, 81, 23, 19, 36, 35, 0, + 40, 49, 47, 64, 67, 60, 0, 28, 108, 0, + 0, 46, 0, 0, 30, 50, 48, 65, 66 +}; + + /* YYPGOTO[NTERM-NUM]. */ +static const yytype_int16 yypgoto[] = +{ + -146, -146, -65, -146, -146, -146, -146, -146, -146, 13, + -146, -146, -146, -146, -146, -146, -146, -146, -146, -109, + -146, -146, -146, -146, -146, -17, -13, -146, -146, -146, + -1, -146, -146, -145, -146, -6, -82, -146, -146, -146, + -51, 3 +}; + + /* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int16 yydefgoto[] = +{ + -1, 8, 9, 76, 80, 10, 11, 77, 12, 123, + 124, 13, 81, 14, 142, 171, 15, 78, 16, 128, + 129, 130, 131, 132, 157, 158, 159, 17, 79, 18, + 137, 138, 139, 113, 19, 140, 68, 69, 70, 71, + 72, 125 +}; + + /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule whose + number is the opposite. If YYTABLE_NINF, syntax error. */ +static const yytype_int16 yytable[] = +{ + 67, 82, 104, 106, 175, 48, 143, 51, 83, 118, + 74, 186, 20, 53, 187, 100, 133, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 95, 64, 64, + 155, 121, 119, 156, 115, 102, 141, 49, 116, 114, + 65, 65, 75, 177, 66, 178, 85, 197, 198, -44, + 144, 84, 179, -44, 86, 52, 180, 87, 88, 89, + -3, 90, 94, 172, 95, 96, 145, 97, 98, 53, + 133, 93, 133, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 53, 99, 64, 117, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 65, 114, 64, + 66, 101, -8, 1, 120, -52, 2, -110, 146, -52, + 147, 65, 148, 149, 66, 152, 150, 3, 4, -51, + 151, 1, 5, -51, 2, 160, 153, 154, 162, 163, + 166, 161, 6, 7, 167, 3, 4, 168, -8, 170, + 5, 114, 114, 169, 173, -8, 1, -112, 174, 2, + 6, 7, 181, 182, 188, 192, -8, 193, 183, 184, + 3, 4, 189, 194, 176, 5, 190, 185, 0, 0, + 107, 0, 0, 191, 0, 6, 7, 108, 109, 110, + 111, 112, 65, 195, 196, 22, 23, 24, 25, 26, + 27, 28, 29, 0, 30, 31, 32, 33, 34, 91, + 36, 0, 37, 0, 38, 39, 40, 41, 42, 43, + 44, 0, 45, 46, 47, 0, 0, 0, 0, 0, + 0, 53, 0, 0, 92, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 0, 0, 64, 0, 0, + 0, 0, 134, 135, 136, 0, 0, 0, 0, 65, + 0, 0, 66, 126, 0, 127, -62, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 0, 0, 64, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 65, 0, 0, 66, 0, 0, 21, -38, 22, + 23, 24, 25, 26, 27, 28, 29, 0, 30, 31, + 32, 33, 34, 35, 36, 0, 37, 0, 38, 39, + 40, 41, 42, 43, 44, 53, 45, 46, 47, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 0, + 0, 64, 0, 0, 0, 0, 164, 165, 0, 0, + 0, 0, 0, 65, 53, 0, 66, 0, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, + 64, 155, 0, 0, 156, 0, 0, 0, 0, 0, + 0, 0, 65, 53, 0, 66, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 103, 0, 64, + 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 65, 0, 64, 66, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 65, 105, 0, 66, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 65, 0, 0, 66, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 50, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 73, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 22, 23, + 24, 25, 26, 27, 28, 29, 0, 30, 31, 32, + 33, 34, 122, 36, 0, 37, 0, 38, 39, 40, + 41, 42, 43, 44, 0, 45, 46, 47, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 0, 0, + 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 65, 0, 0, 66 +}; + +static const yytype_int16 yycheck[] = +{ + 6, 52, 84, 85, 149, 2, 1, 4, 1, 1, + 7, 37, 34, 1, 40, 80, 98, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 29, 17, 17, + 18, 96, 24, 21, 39, 37, 101, 17, 43, 90, + 29, 29, 0, 152, 32, 154, 44, 192, 193, 37, + 45, 44, 37, 41, 17, 39, 41, 6, 7, 8, + 34, 38, 43, 145, 29, 34, 37, 35, 35, 1, + 152, 68, 154, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 1, 35, 17, 17, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 29, 149, 17, + 32, 35, 0, 1, 17, 37, 4, 29, 29, 41, + 24, 29, 24, 38, 32, 34, 36, 15, 16, 37, + 37, 1, 20, 41, 4, 131, 36, 34, 134, 135, + 136, 19, 30, 31, 36, 15, 16, 34, 36, 17, + 20, 192, 193, 36, 17, 0, 1, 29, 40, 4, + 30, 31, 158, 159, 45, 38, 36, 38, 164, 165, + 15, 16, 179, 17, 151, 20, 179, 168, -1, -1, + 17, -1, -1, 179, -1, 30, 31, 24, 25, 26, + 27, 28, 29, 189, 190, 3, 4, 5, 6, 7, + 8, 9, 10, -1, 12, 13, 14, 15, 16, 17, + 18, -1, 20, -1, 22, 23, 24, 25, 26, 27, + 28, -1, 30, 31, 32, -1, -1, -1, -1, -1, + -1, 1, -1, -1, 42, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, -1, -1, 17, -1, -1, + -1, -1, 22, 23, 24, -1, -1, -1, -1, 29, + -1, -1, 32, 1, -1, 3, 36, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, -1, -1, 17, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 29, -1, -1, 32, -1, -1, 1, 36, 3, + 4, 5, 6, 7, 8, 9, 10, -1, 12, 13, + 14, 15, 16, 17, 18, -1, 20, -1, 22, 23, + 24, 25, 26, 27, 28, 1, 30, 31, 32, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, -1, + -1, 17, -1, -1, -1, -1, 22, 23, -1, -1, + -1, -1, -1, 29, 1, -1, 32, -1, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, + 17, 18, -1, -1, 21, -1, -1, -1, -1, -1, + -1, -1, 29, 1, -1, 32, -1, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 1, -1, 17, + -1, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 29, -1, 17, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 29, 1, -1, 32, -1, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + -1, -1, 17, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 29, -1, -1, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 3, 4, + 5, 6, 7, 8, 9, 10, -1, 12, 13, 14, + 15, 16, 17, 18, -1, 20, -1, 22, 23, 24, + 25, 26, 27, 28, -1, 30, 31, 32, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, -1, -1, + 17, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 29, -1, -1, 32 +}; + + /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 1, 4, 15, 16, 20, 30, 31, 47, 48, + 51, 52, 54, 57, 59, 62, 64, 73, 75, 80, + 34, 1, 3, 4, 5, 6, 7, 8, 9, 10, + 12, 13, 14, 15, 16, 17, 18, 20, 22, 23, + 24, 25, 26, 27, 28, 30, 31, 32, 87, 17, + 17, 87, 39, 1, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 17, 29, 32, 81, 82, 83, + 84, 85, 86, 17, 87, 0, 49, 53, 63, 74, + 50, 58, 86, 1, 44, 44, 17, 6, 7, 8, + 38, 17, 42, 87, 43, 29, 34, 35, 35, 35, + 48, 35, 37, 1, 82, 1, 82, 17, 24, 25, + 26, 27, 28, 79, 86, 39, 43, 17, 1, 24, + 17, 48, 17, 55, 56, 87, 1, 3, 65, 66, + 67, 68, 69, 82, 22, 23, 24, 76, 77, 78, + 81, 48, 60, 1, 45, 37, 29, 24, 24, 38, + 36, 37, 34, 36, 34, 18, 21, 70, 71, 72, + 81, 19, 81, 81, 22, 23, 81, 36, 34, 36, + 17, 61, 82, 17, 40, 79, 55, 65, 65, 37, + 41, 81, 81, 81, 81, 76, 37, 40, 45, 71, + 72, 81, 38, 38, 17, 81, 81, 79, 79 +}; + + /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 46, 47, 49, 48, 50, 48, 48, 48, 51, + 51, 51, 51, 51, 51, 53, 52, 54, 54, 55, + 55, 56, 56, 56, 56, 58, 57, 60, 59, 61, + 61, 63, 62, 64, 64, 65, 65, 65, 65, 66, + 67, 68, 69, 69, 70, 70, 70, 70, 70, 70, + 70, 70, 70, 71, 72, 74, 73, 75, 75, 75, + 76, 76, 76, 77, 78, 78, 78, 78, 78, 78, + 78, 78, 79, 79, 79, 79, 79, 79, 79, 80, + 81, 81, 81, 81, 81, 81, 81, 82, 82, 82, + 83, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, + 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87 +}; + + /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 1, 0, 4, 0, 4, 1, 0, 1, + 1, 1, 1, 1, 1, 0, 5, 2, 2, 3, + 1, 1, 1, 3, 0, 0, 6, 0, 7, 1, + 3, 0, 5, 2, 2, 3, 3, 1, 0, 1, + 3, 2, 1, 1, 0, 1, 3, 2, 4, 2, + 4, 1, 1, 1, 1, 0, 5, 2, 2, 2, + 3, 1, 0, 1, 3, 5, 5, 3, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 3, 4, + 2, 5, 3, 4, 2, 1, 1, 3, 1, 3, + 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 4, 3, 4, 2, 6, 3, + 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 +}; + + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + YYPOPSTACK (yylen); \ + yystate = *yyssp; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (0) + +/* Error token number */ +#define YYTERROR 1 +#define YYERRCODE 256 + + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) + +/* This macro is provided for backward compatibility. */ +#ifndef YY_LOCATION_PRINT +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +#endif + + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (0) + + +/*----------------------------------------. +| Print this symbol's value on YYOUTPUT. | +`----------------------------------------*/ + +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + FILE *yyo = yyoutput; + YYUSE (yyo); + if (!yyvaluep) + return; +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# endif + YYUSE (yytype); +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep) +{ + YYFPRINTF (yyoutput, "%s %s (", + yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (0) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +static void +yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule) +{ + unsigned long int yylno = yyrline[yyrule]; + int yynrhs = yyr2[yyrule]; + int yyi; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, + yystos[yyssp[yyi + 1 - yynrhs]], + &(yyvsp[(yyi + 1) - (yynrhs)]) + ); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyssp, yyvsp, Rule); \ +} while (0) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +yystrlen (const char *yystr) +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +yystpcpy (char *yydest, const char *yysrc) +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into *YYMSG, which is of size *YYMSG_ALLOC, an error message + about the unexpected token YYTOKEN for the state stack whose top is + YYSSP. + + Return 0 if *YYMSG was successfully written. Return 1 if *YYMSG is + not large enough to hold the message. In that case, also set + *YYMSG_ALLOC to the required number of bytes. Return 2 if the + required number of bytes is too large to store. */ +static int +yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg, + yytype_int16 *yyssp, int yytoken) +{ + YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]); + YYSIZE_T yysize = yysize0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + /* Internationalized format string. */ + const char *yyformat = YY_NULLPTR; + /* Arguments of yyformat. */ + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + /* Number of reported tokens (one for the "unexpected", one per + "expected"). */ + int yycount = 0; + + /* There are many possibilities here to consider: + - If this state is a consistent state with a default action, then + the only way this function was invoked is if the default action + is an error action. In that case, don't check for expected + tokens because there are none. + - The only way there can be no lookahead present (in yychar) is if + this state is a consistent state with a default action. Thus, + detecting the absence of a lookahead is sufficient to determine + that there is no unexpected or expected token to report. In that + case, just report a simple "syntax error". + - Don't assume there isn't a lookahead just because this state is a + consistent state with a default action. There might have been a + previous inconsistent state, consistent state with a non-default + action, or user semantic action that manipulated yychar. + - Of course, the expected token list depends on states to have + correct lookahead information, and it depends on the parser not + to perform extra reductions after fetching a lookahead from the + scanner and before detecting a syntax error. Thus, state merging + (from LALR or IELR) and default reductions corrupt the expected + token list. However, the list is correct for canonical LR with + one exception: it will still contain any token that will not be + accepted due to an error action in a later state. + */ + if (yytoken != YYEMPTY) + { + int yyn = yypact[*yyssp]; + yyarg[yycount++] = yytname[yytoken]; + if (!yypact_value_is_default (yyn)) + { + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. In other words, skip the first -YYN actions for + this state because they are default actions. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yyx; + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR + && !yytable_value_is_error (yytable[yyx + yyn])) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + break; + } + yyarg[yycount++] = yytname[yyx]; + { + YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]); + if (! (yysize <= yysize1 + && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + } + } + } + + switch (yycount) + { +# define YYCASE_(N, S) \ + case N: \ + yyformat = S; \ + break + YYCASE_(0, YY_("syntax error")); + YYCASE_(1, YY_("syntax error, unexpected %s")); + YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s")); + YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s")); + YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s")); + YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s")); +# undef YYCASE_ + } + + { + YYSIZE_T yysize1 = yysize + yystrlen (yyformat); + if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM)) + return 2; + yysize = yysize1; + } + + if (*yymsg_alloc < yysize) + { + *yymsg_alloc = 2 * yysize; + if (! (yysize <= *yymsg_alloc + && *yymsg_alloc <= YYSTACK_ALLOC_MAXIMUM)) + *yymsg_alloc = YYSTACK_ALLOC_MAXIMUM; + return 1; + } + + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + { + char *yyp = *yymsg; + int yyi = 0; + while ((*yyp = *yyformat) != '\0') + if (*yyp == '%' && yyformat[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyformat += 2; + } + else + { + yyp++; + yyformat++; + } + } + return 0; +} +#endif /* YYERROR_VERBOSE */ + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) +{ + YYUSE (yyvaluep); + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + YYUSE (yytype); + YY_IGNORE_MAYBE_UNINITIALIZED_END +} + + + + +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; +/* Number of syntax errors so far. */ +int yynerrs; + + +/*----------. +| yyparse. | +`----------*/ + +int +yyparse (void) +{ + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + 'yyss': related to states. + 'yyvs': related to semantic values. + + Refer to the stacks through separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken = 0; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yyssp = yyss = yyssa; + yyvsp = yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yypact_value_is_default (yyn)) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = yylex (); + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yytable_value_is_error (yyn)) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + '$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 3: +#line 75 "tars.y" /* yacc.c:1646 */ + { +} +#line 1469 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 5: +#line 79 "tars.y" /* yacc.c:1646 */ + { + yyerrok; +} +#line 1477 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 7: +#line 84 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("`;' missing after definition"); +} +#line 1485 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 8: +#line 88 "tars.y" /* yacc.c:1646 */ + { +} +#line 1492 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 9: +#line 96 "tars.y" /* yacc.c:1646 */ + { + assert((yyvsp[0]) == 0 || NamespacePtr::dynamicCast((yyvsp[0]))); +} +#line 1500 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 10: +#line 100 "tars.y" /* yacc.c:1646 */ + { + assert((yyvsp[0]) == 0 || InterfacePtr::dynamicCast((yyvsp[0]))); +} +#line 1508 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 11: +#line 104 "tars.y" /* yacc.c:1646 */ + { + assert((yyvsp[0]) == 0 || StructPtr::dynamicCast((yyvsp[0]))); +} +#line 1516 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 12: +#line 108 "tars.y" /* yacc.c:1646 */ + { +} +#line 1523 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 13: +#line 111 "tars.y" /* yacc.c:1646 */ + { + assert((yyvsp[0]) == 0 || EnumPtr::dynamicCast((yyvsp[0]))); +} +#line 1531 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 14: +#line 115 "tars.y" /* yacc.c:1646 */ + { + assert((yyvsp[0]) == 0 || ConstPtr::dynamicCast((yyvsp[0]))); +} +#line 1539 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 15: +#line 124 "tars.y" /* yacc.c:1646 */ + { + (yyval) = (yyvsp[0]); +} +#line 1547 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 16: +#line 128 "tars.y" /* yacc.c:1646 */ + { + if((yyvsp[-2])) + { + g_parse->popContainer(); + (yyval) = (yyvsp[-2]); + } + else + { + (yyval) = 0; + } + + (yyval) = (yyvsp[-3]); +} +#line 1565 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 17: +#line 147 "tars.y" /* yacc.c:1646 */ + { + NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(!c) + { + g_parse->error("enum must define in namespace"); + } + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + EnumPtr e = c->createEnum(ident->v); + g_parse->pushContainer(e); + + (yyval) = e; +} +#line 1582 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 18: +#line 160 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->error("keyword `" + ident->v + "' cannot be used as enumeration name"); + (yyval) = (yyvsp[0]); +} +#line 1592 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 19: +#line 171 "tars.y" /* yacc.c:1646 */ + { + (yyval) = (yyvsp[-1]); +} +#line 1600 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 20: +#line 175 "tars.y" /* yacc.c:1646 */ + { +} +#line 1607 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 21: +#line 183 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + TypeIdPtr tPtr = new TypeId(type, ident->v); + tPtr->disableDefault(); + EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); + assert(e); + e->addMember(tPtr); + (yyval) = e; +} +#line 1622 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 22: +#line 194 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->error("keyword `" + ident->v + "' cannot be used as enumerator"); +} +#line 1631 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 23: +#line 199 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = TypePtr::dynamicCast(g_parse->createBuiltin(Builtin::KindLong)); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-2])); + TypeIdPtr tPtr = new TypeId(type, ident->v); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->checkConstValue(tPtr, sPtr->t); + tPtr->setDefault(sPtr->v); + EnumPtr e = EnumPtr::dynamicCast(g_parse->currentContainer()); + assert(e); + e->addMember(tPtr); + (yyval) = e; +} +#line 1648 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 24: +#line 212 "tars.y" /* yacc.c:1646 */ + { +} +#line 1655 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 25: +#line 220 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + ContainerPtr c = g_parse->currentContainer(); + NamespacePtr n = c->createNamespace(ident->v); + if(n) + { + g_parse->pushContainer(n); + (yyval) = GrammarBasePtr::dynamicCast(n); + } + else + { + (yyval) = 0; + } +} +#line 1674 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 26: +#line 235 "tars.y" /* yacc.c:1646 */ + { + if((yyvsp[-3])) + { + g_parse->popContainer(); + (yyval) = (yyvsp[-3]); + } + else + { + (yyval) = 0; + } +} +#line 1690 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 27: +#line 253 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-1])); + StructPtr sp = StructPtr::dynamicCast(g_parse->findUserType(ident->v)); + if(!sp) + { + g_parse->error("struct '" + ident->v + "' undefined!"); + } + + g_parse->setKeyStruct(sp); +} +#line 1705 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 28: +#line 264 "tars.y" /* yacc.c:1646 */ + { +} +#line 1712 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 29: +#line 272 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StructPtr np = g_parse->getKeyStruct(); + if(np) + { + np->addKey(ident->v); + } + else + { + (yyval) = 0; + } +} +#line 1729 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 30: +#line 285 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + StructPtr np = g_parse->getKeyStruct(); + if(np) + { + np->addKey(ident->v); + } + else + { + (yyval) = 0; + } +} +#line 1746 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 31: +#line 304 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + + NamespacePtr c = NamespacePtr::dynamicCast(g_parse->currentContainer()); + + InterfacePtr cl = c->createInterface(ident->v); + if(cl) + { + g_parse->pushContainer(cl); + (yyval) = GrammarBasePtr::dynamicCast(cl); + } + else + { + (yyval) = 0; + } +} +#line 1767 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 32: +#line 321 "tars.y" /* yacc.c:1646 */ + { + if((yyvsp[-3])) + { + g_parse->popContainer(); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-3])); + } + else + { + (yyval) = 0; + } +} +#line 1783 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 33: +#line 338 "tars.y" /* yacc.c:1646 */ + { + (yyval) = (yyvsp[0]); +} +#line 1791 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 34: +#line 342 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->error("keyword `" + ident->v + "' cannot be used as interface name"); + (yyval) = (yyvsp[0]); +} +#line 1801 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 35: +#line 353 "tars.y" /* yacc.c:1646 */ + { +} +#line 1808 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 36: +#line 356 "tars.y" /* yacc.c:1646 */ + { +} +#line 1815 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 37: +#line 359 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("`;' missing after definition"); +} +#line 1823 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 38: +#line 363 "tars.y" /* yacc.c:1646 */ + { +} +#line 1830 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 40: +#line 377 "tars.y" /* yacc.c:1646 */ + { + if((yyvsp[-2])) + { + g_parse->popContainer(); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + } + else + { + (yyval) = 0; + } +} +#line 1846 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 41: +#line 394 "tars.y" /* yacc.c:1646 */ + { + TypePtr returnType = TypePtr::dynamicCast((yyvsp[-1])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + string name = ident->v; + InterfacePtr cl = InterfacePtr::dynamicCast(g_parse->currentContainer()); + if(cl) + { + OperationPtr op = cl->createOperation(name, returnType); + if(op) + { + g_parse->pushContainer(op); + (yyval) = GrammarBasePtr::dynamicCast(op); + } + else + { + (yyval) = 0; + } + } + else + { + (yyval) = 0; + } +} +#line 1874 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 43: +#line 424 "tars.y" /* yacc.c:1646 */ + { + (yyval) = 0; +} +#line 1882 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 44: +#line 434 "tars.y" /* yacc.c:1646 */ + { +} +#line 1889 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 45: +#line 437 "tars.y" /* yacc.c:1646 */ + { + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, false); + } +} +#line 1904 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 46: +#line 448 "tars.y" /* yacc.c:1646 */ + { + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, false); + } +} +#line 1919 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 47: +#line 459 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, isOutParam->v, false); + } +} +#line 1935 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 48: +#line 471 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr isOutParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, isOutParam->v, false); + } +} +#line 1951 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 49: +#line 483 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, isRouteKeyParam->v); + } +} +#line 1967 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 50: +#line 495 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr isRouteKeyParam = BoolGrammarPtr::dynamicCast((yyvsp[-1])); + TypeIdPtr tsp = TypeIdPtr::dynamicCast((yyvsp[0])); + + OperationPtr op = OperationPtr::dynamicCast(g_parse->currentContainer()); + assert(op); + if(op) + { + op->createParamDecl(tsp, false, isRouteKeyParam->v); + } +} +#line 1983 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 51: +#line 507 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("'out' must be defined with a type"); +} +#line 1991 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 52: +#line 511 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("'routekey' must be defined with a type"); +} +#line 1999 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 53: +#line 520 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr routekey = new BoolGrammar; + routekey->v = true; + (yyval) = GrammarBasePtr::dynamicCast(routekey); +} +#line 2009 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 54: +#line 531 "tars.y" /* yacc.c:1646 */ + { + BoolGrammarPtr out = new BoolGrammar; + out->v = true; + (yyval) = GrammarBasePtr::dynamicCast(out); +} +#line 2019 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 55: +#line 542 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + StructPtr sp = np->createStruct(ident->v); + if(sp) + { + g_parse->pushContainer(sp); + (yyval) = GrammarBasePtr::dynamicCast(sp); + } + else + { + (yyval) = 0; + } + } + else + { + g_parse->error("struct '" + ident->v + "' must definition in namespace"); + } +} +#line 2045 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 56: +#line 564 "tars.y" /* yacc.c:1646 */ + { + if((yyvsp[-3])) + { + g_parse->popContainer(); + } + (yyval) = (yyvsp[-3]); + + //不能有空结构 + StructPtr st = StructPtr::dynamicCast((yyval)); + assert(st); + if(st->getAllMemberPtr().size() == 0) + { + g_parse->error("struct `" + st->getSid() + "' must have at least one member"); + } +} +#line 2065 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 57: +#line 585 "tars.y" /* yacc.c:1646 */ + { + (yyval) = (yyvsp[0]); +} +#line 2073 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 58: +#line 589 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + + g_parse->error("keyword `" + ident->v + "' cannot be used as struct name"); +} +#line 2083 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 59: +#line 595 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("abstract declarator '' used as declaration"); +} +#line 2091 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 60: +#line 604 "tars.y" /* yacc.c:1646 */ + { + +} +#line 2099 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 61: +#line 608 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("';' missing after definition"); +} +#line 2107 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 62: +#line 612 "tars.y" /* yacc.c:1646 */ + { +} +#line 2114 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 63: +#line 622 "tars.y" /* yacc.c:1646 */ + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); +} +#line 2122 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 64: +#line 631 "tars.y" /* yacc.c:1646 */ + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-2])); + g_parse->checkTag(iPtr->v); + + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[0])); + tPtr->setRequire(iPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); + } + else + { + (yyval) = 0; + } +} +#line 2144 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 65: +#line 649 "tars.y" /* yacc.c:1646 */ + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-4])); + g_parse->checkTag(iPtr->v); + + //判断类型和数值类型是否一致 + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[-2])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->checkConstValue(tPtr, sPtr->t); + + tPtr->setRequire(iPtr->v); + tPtr->setDefault(sPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + } + else + { + (yyval) = 0; + } +} +#line 2171 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 66: +#line 672 "tars.y" /* yacc.c:1646 */ + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-4])); + g_parse->checkTag(iPtr->v); + + //判断类型和数值类型是否一致 + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[-2])); + ConstGrammarPtr sPtr = ConstGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->checkConstValue(tPtr, sPtr->t); + + tPtr->setOptional(iPtr->v); + tPtr->setDefault(sPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[-2])); + } + else + { + (yyval) = 0; + } +} +#line 2198 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 67: +#line 695 "tars.y" /* yacc.c:1646 */ + { + StructPtr np = StructPtr::dynamicCast(g_parse->currentContainer()); + if(np) + { + IntergerGrammarPtr iPtr = IntergerGrammarPtr::dynamicCast((yyvsp[-2])); + g_parse->checkTag(iPtr->v); + TypeIdPtr tPtr = TypeIdPtr::dynamicCast((yyvsp[0])); + tPtr->setOptional(iPtr->v); + np->addTypeId(tPtr); + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); + } + else + { + (yyval) = 0; + } +} +#line 2219 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 68: +#line 712 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("struct member need 'tag'"); +} +#line 2227 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 69: +#line 716 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("struct member need 'tag'"); +} +#line 2235 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 70: +#line 720 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("struct member need 'require' or 'optional'"); +} +#line 2243 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 71: +#line 724 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("struct member need 'tag' or 'require' or 'optional'"); +} +#line 2251 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 72: +#line 733 "tars.y" /* yacc.c:1646 */ + { + IntergerGrammarPtr intVal = IntergerGrammarPtr::dynamicCast((yyvsp[0])); + ostringstream sstr; + sstr << intVal->v; + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::VALUE; + c->v = sstr.str(); + (yyval) = c; +} +#line 2265 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 73: +#line 743 "tars.y" /* yacc.c:1646 */ + { + FloatGrammarPtr floatVal = FloatGrammarPtr::dynamicCast((yyvsp[0])); + ostringstream sstr; + sstr << floatVal->v; + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::VALUE; + c->v = sstr.str(); + (yyval) = c; +} +#line 2279 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 74: +#line 753 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::STRING; + c->v = ident->v; + (yyval) = c; +} +#line 2291 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 75: +#line 761 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::BOOL; + c->v = ident->v; + (yyval) = c; +} +#line 2303 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 76: +#line 769 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::BOOL; + c->v = ident->v; + (yyval) = c; +} +#line 2315 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 77: +#line 777 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + + if (g_parse->checkEnum(ident->v) == false) + { + g_parse->error("error enum default value, not defined yet"); + } + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::ENUM; + c->v = ident->v; + (yyval) = c; +} +#line 2332 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 78: +#line 790 "tars.y" /* yacc.c:1646 */ + { + + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[-2])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + + if (g_parse->checkEnum(ident->v) == false) + { + g_parse->error("error enum default value, not defined yet"); + } + ConstGrammarPtr c = new ConstGrammar(); + c->t = ConstGrammar::ENUM; + c->v = scoped->v + "::" + ident->v; + (yyval) = c; +} +#line 2351 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 79: +#line 810 "tars.y" /* yacc.c:1646 */ + { + NamespacePtr np = NamespacePtr::dynamicCast(g_parse->currentContainer()); + if(!np) + { + g_parse->error("const type must define in namespace"); + } + + TypeIdPtr t = TypeIdPtr::dynamicCast((yyvsp[-2])); + ConstGrammarPtr c = ConstGrammarPtr::dynamicCast((yyvsp[0])); + ConstPtr cPtr = np->createConst(t, c); + (yyval) = cPtr; +} +#line 2368 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 80: +#line 828 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = TypePtr::dynamicCast((yyvsp[-1])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +} +#line 2381 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 81: +#line 837 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[-4]))); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[-1])); + g_parse->checkArrayVaid(type,iPtrSize->v); + type->setArray(iPtrSize->v); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-3])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +} +#line 2395 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 82: +#line 847 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = g_parse->createVector(TypePtr::dynamicCast((yyvsp[-2]))); + //IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast($4); + g_parse->checkPointerVaid(type); + type->setPointer(true); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +} +#line 2409 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 83: +#line 857 "tars.y" /* yacc.c:1646 */ + { + TypePtr type = TypePtr::dynamicCast((yyvsp[-3])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[-2])); + TypeIdPtr typeIdPtr = new TypeId(type, ident->v); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[-1])); + g_parse->checkArrayVaid(type,iPtrSize->v); + (yyval) = GrammarBasePtr::dynamicCast(typeIdPtr); +} +#line 2422 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 84: +#line 866 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->error("keyword `" + ident->v + "' cannot be used as data member name"); +} +#line 2431 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 85: +#line 871 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("missing data member name"); +} +#line 2439 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 86: +#line 875 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("unkown type"); +} +#line 2447 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 87: +#line 884 "tars.y" /* yacc.c:1646 */ + { + + TypePtr type = TypePtr::dynamicCast((yyvsp[-2])); + IntergerGrammarPtr iPtrSize = IntergerGrammarPtr::dynamicCast((yyvsp[0])); + g_parse->checkArrayVaid(type,iPtrSize->v); + type->setArray(iPtrSize->v); + (yyval) = type; +} +#line 2460 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 88: +#line 893 "tars.y" /* yacc.c:1646 */ + { + (yyval) = (yyvsp[0]); +} +#line 2468 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 89: +#line 897 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("array missing size"); +} +#line 2476 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 90: +#line 906 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindBool); +} +#line 2484 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 91: +#line 910 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindByte); +} +#line 2492 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 92: +#line 914 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindShort,true); +} +#line 2500 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 93: +#line 918 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindShort); +} +#line 2508 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 94: +#line 922 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindInt,true); +} +#line 2516 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 95: +#line 926 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindInt); +} +#line 2524 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 96: +#line 930 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindLong,true); +} +#line 2532 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 97: +#line 934 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindLong); +} +#line 2540 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 98: +#line 938 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindFloat); +} +#line 2548 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 99: +#line 942 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindDouble); +} +#line 2556 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 100: +#line 946 "tars.y" /* yacc.c:1646 */ + { + (yyval) = g_parse->createBuiltin(Builtin::KindString); +} +#line 2564 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 101: +#line 950 "tars.y" /* yacc.c:1646 */ + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); +} +#line 2572 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 102: +#line 954 "tars.y" /* yacc.c:1646 */ + { + (yyval) = GrammarBasePtr::dynamicCast((yyvsp[0])); +} +#line 2580 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 103: +#line 958 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + TypePtr sp = g_parse->findUserType(ident->v); + if(sp) + { + (yyval) = GrammarBasePtr::dynamicCast(sp); + } + else + { + g_parse->error("'" + ident->v + "' undefined!"); + } +} +#line 2597 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 104: +#line 976 "tars.y" /* yacc.c:1646 */ + { + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createVector(TypePtr::dynamicCast((yyvsp[-1])))); +} +#line 2605 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 105: +#line 980 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("vector error"); +} +#line 2613 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 106: +#line 984 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("vector missing '>'"); +} +#line 2621 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 107: +#line 988 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("vector missing type"); +} +#line 2629 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 108: +#line 997 "tars.y" /* yacc.c:1646 */ + { + (yyval) = GrammarBasePtr::dynamicCast(g_parse->createMap(TypePtr::dynamicCast((yyvsp[-3])), TypePtr::dynamicCast((yyvsp[-1])))); +} +#line 2637 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 109: +#line 1001 "tars.y" /* yacc.c:1646 */ + { + g_parse->error("map error"); +} +#line 2645 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 110: +#line 1010 "tars.y" /* yacc.c:1646 */ + { +} +#line 2652 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 111: +#line 1013 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + ident->v = "::" + ident->v; + (yyval) = GrammarBasePtr::dynamicCast(ident); +} +#line 2662 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 112: +#line 1019 "tars.y" /* yacc.c:1646 */ + { + StringGrammarPtr scoped = StringGrammarPtr::dynamicCast((yyvsp[-2])); + StringGrammarPtr ident = StringGrammarPtr::dynamicCast((yyvsp[0])); + scoped->v += "::"; + scoped->v += ident->v; + (yyval) = GrammarBasePtr::dynamicCast(scoped); +} +#line 2674 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 113: +#line 1032 "tars.y" /* yacc.c:1646 */ + { +} +#line 2681 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 114: +#line 1035 "tars.y" /* yacc.c:1646 */ + { +} +#line 2688 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 115: +#line 1038 "tars.y" /* yacc.c:1646 */ + { +} +#line 2695 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 116: +#line 1041 "tars.y" /* yacc.c:1646 */ + { +} +#line 2702 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 117: +#line 1044 "tars.y" /* yacc.c:1646 */ + { +} +#line 2709 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 118: +#line 1047 "tars.y" /* yacc.c:1646 */ + { +} +#line 2716 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 119: +#line 1050 "tars.y" /* yacc.c:1646 */ + { +} +#line 2723 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 120: +#line 1053 "tars.y" /* yacc.c:1646 */ + { +} +#line 2730 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 121: +#line 1056 "tars.y" /* yacc.c:1646 */ + { +} +#line 2737 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 122: +#line 1059 "tars.y" /* yacc.c:1646 */ + { +} +#line 2744 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 123: +#line 1062 "tars.y" /* yacc.c:1646 */ + { +} +#line 2751 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 124: +#line 1065 "tars.y" /* yacc.c:1646 */ + { +} +#line 2758 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 125: +#line 1068 "tars.y" /* yacc.c:1646 */ + { +} +#line 2765 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 126: +#line 1071 "tars.y" /* yacc.c:1646 */ + { +} +#line 2772 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 127: +#line 1074 "tars.y" /* yacc.c:1646 */ + { +} +#line 2779 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 128: +#line 1077 "tars.y" /* yacc.c:1646 */ + { +} +#line 2786 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 129: +#line 1080 "tars.y" /* yacc.c:1646 */ + { +} +#line 2793 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 130: +#line 1083 "tars.y" /* yacc.c:1646 */ + { +} +#line 2800 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 131: +#line 1086 "tars.y" /* yacc.c:1646 */ + { +} +#line 2807 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 132: +#line 1089 "tars.y" /* yacc.c:1646 */ + { +} +#line 2814 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 133: +#line 1092 "tars.y" /* yacc.c:1646 */ + { +} +#line 2821 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 134: +#line 1095 "tars.y" /* yacc.c:1646 */ + { +} +#line 2828 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 135: +#line 1098 "tars.y" /* yacc.c:1646 */ + { +} +#line 2835 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 136: +#line 1101 "tars.y" /* yacc.c:1646 */ + { +} +#line 2842 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + case 137: +#line 1104 "tars.y" /* yacc.c:1646 */ + { +} +#line 2849 "tars.tab.cpp" /* yacc.c:1646 */ + break; + + +#line 2853 "tars.tab.cpp" /* yacc.c:1646 */ + default: break; + } + /* User semantic actions sometimes alter yychar, and that requires + that yytoken be updated with the new translation. We take the + approach of translating immediately before every use of yytoken. + One alternative is translating here after every semantic action, + but that translation would be missed if the semantic action invokes + YYABORT, YYACCEPT, or YYERROR immediately after altering yychar or + if it invokes YYBACKUP. In the case of YYABORT or YYACCEPT, an + incorrect destructor might then be invoked immediately. In the + case of YYERROR or YYBACKUP, subsequent parser actions might lead + to an incorrect destructor call or verbose syntax error message + before the lookahead is translated. */ + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now 'shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*--------------------------------------. +| yyerrlab -- here on detecting error. | +`--------------------------------------*/ +yyerrlab: + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = yychar == YYEMPTY ? YYEMPTY : YYTRANSLATE (yychar); + + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (YY_("syntax error")); +#else +# define YYSYNTAX_ERROR yysyntax_error (&yymsg_alloc, &yymsg, \ + yyssp, yytoken) + { + char const *yymsgp = YY_("syntax error"); + int yysyntax_error_status; + yysyntax_error_status = YYSYNTAX_ERROR; + if (yysyntax_error_status == 0) + yymsgp = yymsg; + else if (yysyntax_error_status == 1) + { + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yymsg_alloc); + if (!yymsg) + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + yysyntax_error_status = 2; + } + else + { + yysyntax_error_status = YYSYNTAX_ERROR; + yymsgp = yymsg; + } + } + yyerror (yymsgp); + if (yysyntax_error_status == 2) + goto yyexhaustedlab; + } +# undef YYSYNTAX_ERROR +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule whose action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (!yypact_value_is_default (yyn)) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN + *++yyvsp = yylval; + YY_IGNORE_MAYBE_UNINITIALIZED_END + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined yyoverflow || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + { + /* Make sure we have latest lookahead translation. See comments at + user semantic actions for why this is necessary. */ + yytoken = YYTRANSLATE (yychar); + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + } + /* Do not reclaim the symbols of the rule whose action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + return yyresult; +} +#line 1108 "tars.y" /* yacc.c:1906 */ + + + diff --git a/third_partly/tarsgrammar/tars.tab.hpp b/third_partly/tarsgrammar/tars.tab.hpp new file mode 100644 index 0000000..547e017 --- /dev/null +++ b/third_partly/tarsgrammar/tars.tab.hpp @@ -0,0 +1,94 @@ +/* A Bison parser, made by GNU Bison 3.0.4. */ + +/* Bison interface for Yacc-like parsers in C + + Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +#ifndef YY_YY_TARS_TAB_HPP_INCLUDED +# define YY_YY_TARS_TAB_HPP_INCLUDED +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 1 +#endif +#if YYDEBUG +extern int yydebug; +#endif + +/* Token type. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { + TARS_VOID = 258, + TARS_STRUCT = 259, + TARS_BOOL = 260, + TARS_BYTE = 261, + TARS_SHORT = 262, + TARS_INT = 263, + TARS_DOUBLE = 264, + TARS_FLOAT = 265, + TARS_LONG = 266, + TARS_STRING = 267, + TARS_VECTOR = 268, + TARS_MAP = 269, + TARS_NAMESPACE = 270, + TARS_INTERFACE = 271, + TARS_IDENTIFIER = 272, + TARS_OUT = 273, + TARS_OP = 274, + TARS_KEY = 275, + TARS_ROUTE_KEY = 276, + TARS_REQUIRE = 277, + TARS_OPTIONAL = 278, + TARS_CONST_INTEGER = 279, + TARS_CONST_FLOAT = 280, + TARS_FALSE = 281, + TARS_TRUE = 282, + TARS_STRING_LITERAL = 283, + TARS_SCOPE_DELIMITER = 284, + TARS_CONST = 285, + TARS_ENUM = 286, + TARS_UNSIGNED = 287, + BAD_CHAR = 288 + }; +#endif + +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef int YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + +extern YYSTYPE yylval; + +int yyparse (void); + +#endif /* !YY_YY_TARS_TAB_HPP_INCLUDED */ diff --git a/third_partly/tarsparse/element.cpp b/third_partly/tarsparse/element.cpp new file mode 100644 index 0000000..fdd9025 --- /dev/null +++ b/third_partly/tarsparse/element.cpp @@ -0,0 +1,339 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "element.h" +#include +#include +#include "parse.h" +#include "util/tc_file.h" +#include "util/tc_common.h" + +/*************************************************************************************************/ +const char* Builtin::builtinTable[] = + { + "void", + "bool", + "byte", + "short", + "int", + "long", + "float", + "double", + "string", + "vector", + "map" + }; + +Builtin::Builtin(Kind kind,bool isUnsigned = false) : _kind(kind),_isUnsigned(isUnsigned) +{ +} + +Builtin::Kind Builtin::kind() const +{ + return _kind; +} + +bool Builtin::isSimple() const +{ + switch(_kind) + { + case Builtin::KindBool: + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + return true; + default: + return false; + } + + return true; +} + +string Builtin::def() const +{ + switch(_kind) + { + case Builtin::KindBool: + return "true"; + case Builtin::KindByte: + case Builtin::KindShort: + case Builtin::KindInt: + case Builtin::KindLong: + case Builtin::KindFloat: + case Builtin::KindDouble: + return "0"; + case Builtin::KindString: + return ""; + default: + assert(false); + } + + return ""; +} +/*************************************************************************************************/ +Vector::Vector(const TypePtr& ptr) : _ptr(ptr) +{ + +} + +/*************************************************************************************************/ +Map::Map(const TypePtr& pleft, const TypePtr& pright): _pleft(pleft), _pright(pright) +{ + +} + + +/*************************************************************************************************/ + +TypeId::TypeId(const TypePtr& ptr, const string&id) +: _ptr(ptr) +, _id(id) +, _bRequire(true) +, _tag(0) +, _bHasDefault(false) +, _size(0) +, _array(false) + +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr); + if(bPtr) + { + _bHasDefault = true; + _default = bPtr->def(); + } +} + +void TypeId::setRequire(int tag) +{ + _bRequire = true; + _tag = tag; +} + +void TypeId::setDefault(const string &def) +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr); + EnumPtr ePtr = EnumPtr::dynamicCast(_ptr); + assert(bPtr || ePtr); + + + _bHasDefault = true; + _default = def; +} + +void TypeId::disableDefault() +{ + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(_ptr); + assert(bPtr); + _bHasDefault = false; +} + +void TypeId::setOptional(int tag) +{ + _bRequire = false; + _tag = tag; +} + +/*************************************************************************************************/ +NamespacePtr Container::createNamespace(const string &id) +{ + NamespacePtr np = NamespacePtr::dynamicCast(this); + if(np) + { + g_parse->error("namespace can't be nested!"); + } + + _ns.push_back(new Namespace(id)); + + g_parse->currentContextPtr()->addNamespacePtr(_ns.back()); + return _ns.back(); +} + +/*************************************************************************************************/ +ParamDeclPtr Operation::createParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k) +{ + _itag++; + if(_itag > 255) + { + g_parse->error("operation '" + _id + "' can't have more than 255 paramters!"); + } + + if(typeIdPtr->getId() == getId()) + { + g_parse->error("paramters name '" + _id + "' conflicts with operation name!"); + } + + typeIdPtr->setRequire(_itag); + _ps.push_back(new ParamDecl(typeIdPtr, v, k)); + return _ps.back(); +} + +/*************************************************************************************************/ +OperationPtr Interface::createOperation(const string &id, const TypePtr &typePtr) +{ + for(size_t i = 0; i < _ops.size(); i++) + { + if(_ops[i]->getId() == id) + { + g_parse->error("operation '" + id + "' exists in interface '" + _id + "'"); + return NULL; + } + } + + _ops.push_back(new Operation(id, typePtr)); + return _ops.back(); +} + +/*************************************************************************************************/ + +InterfacePtr Namespace::createInterface(const string &id) +{ + for(size_t i = 0; i < _is.size(); i++) + { + if(_is[i]->getId() == id) + { + g_parse->error("interface '" + id + "' exists in namespace '" + _id + "'"); + return NULL; + } + } + + if(id == _id) + { + g_parse->error("interface '" + id + "' must not be same with namespace '" + _id + "'"); + return NULL; + } + + _is.push_back(new Interface(id)); + return _is.back(); +} + +StructPtr Namespace::createStruct(const string& id) +{ + g_parse->checkConflict(_id + "::" + id); + + _ss.push_back(new Struct(id, _id + "::" + id)); + g_parse->addStructPtr(_ss.back()); + + return _ss.back(); +} + +EnumPtr Namespace::createEnum(const string &id) +{ + g_parse->checkConflict(_id + "::" + id); + + _es.push_back(new Enum(id, _id + "::" + id)); + g_parse->addEnumPtr(_es.back()); + + return _es.back(); +} + +ConstPtr Namespace::createConst(TypeIdPtr &pPtr, ConstGrammarPtr &cPtr) +{ + for(size_t i = 0; i < _cs.size(); i++) + { + if(_cs[i]->getTypeIdPtr()->getId() == pPtr->getId()) + { + g_parse->error("const type '" + pPtr->getId() + "' exists in namespace '" + _id + "'"); + return NULL; + } + } + + g_parse->checkConstValue(pPtr, cPtr->t); + _cs.push_back(new Const(pPtr, cPtr)); + + return _cs.back(); +} + +/*************************************************************************************************/ + +void Struct::addTypeId(const TypeIdPtr &typeIdPtr) +{ + StructPtr sp = StructPtr::dynamicCast(typeIdPtr->getTypePtr()); + if(sp) + { + if(sp->getSid() == getSid()) + { + g_parse->error("struct can't take self as member data"); + } + } + + for(size_t i = 0; i < _members.size(); i++) + { + if(_members[i]->getId() == typeIdPtr->getId()) + { + g_parse->error("data member '" + typeIdPtr->getId() + "' duplicate definition"); + } + if(_members[i]->getTag() == typeIdPtr->getTag()) + { + g_parse->error("data member '" + typeIdPtr->getId() + "' has equal tag with '" + _members[i]->getId() + "'"); + } + + if(_members[i]->getTag() > typeIdPtr->getTag()) + { + _members.insert(_members.begin() + i, typeIdPtr); + return; + } + } + + _members.push_back(typeIdPtr); +} + +void Struct::addKey(const string &member) +{ + size_t i; + for(i = 0; i < _members.size(); i++) + { + if(_members[i]->getId() == member) + { + break; + } + } + + if(i == _members.size()) + { + g_parse->error("key member '" + member + "' is not struct member"); + } + + _key.push_back(member); +} +/***********************************************************************************/ + +void Enum::addMember(const TypeIdPtr &typeIdPtr) +{ + for(size_t i = 0; i < _members.size(); i++) + { + if(_members[i]->getId() == typeIdPtr->getId()) + { + g_parse->error("enum member '" + typeIdPtr->getId() + "' duplicate definition"); + } + } + _members.push_back(typeIdPtr); +} + +/***********************************************************************************/ + +void Context::addInclude(const string &incl) +{ + if(incl == _filename) + { + g_parse->error("can't include self"); + } + _includes.push_back(tars::TC_File::excludeFileExt(incl) + ".h"); +} + + diff --git a/third_partly/tarsparse/element.h b/third_partly/tarsparse/element.h new file mode 100644 index 0000000..815c3af --- /dev/null +++ b/third_partly/tarsparse/element.h @@ -0,0 +1,861 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef _ELEMENT_H +#define _ELEMENT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include "errno.h" +#include "util/tc_autoptr.h" + +using namespace std; + + +void yyerror(char const *msg); + +/** + * 语法元素基类 + */ +class GrammarBase : virtual public tars::TC_HandleBase +{ +public: + virtual ~GrammarBase(){}; +}; + +typedef tars::TC_AutoPtr GrammarBasePtr; + +/** + * 解析过程中的字符串 + */ +class StringGrammar : public GrammarBase +{ +public: + + StringGrammar() { } + string v; +}; + +typedef tars::TC_AutoPtr StringGrammarPtr; + +/** + * 解析过程中的整形数 + */ +class IntergerGrammar : public GrammarBase +{ +public: + + IntergerGrammar():v(0) { } + long long v; +}; + +typedef tars::TC_AutoPtr IntergerGrammarPtr; + +/** + * 解析过程中的浮点数 + */ +class FloatGrammar : public GrammarBase +{ +public: + + FloatGrammar():v(0.0f) { } + double v; +}; + +typedef tars::TC_AutoPtr FloatGrammarPtr; + +/** + * 解析过程中的bool类型 + */ +class BoolGrammar : public GrammarBase +{ +public: + + BoolGrammar():v(false) { } + bool v; +}; + +typedef tars::TC_AutoPtr BoolGrammarPtr; + +/** + * 解析过程中的常类型 + */ +class ConstGrammar : public GrammarBase +{ +public: + + ConstGrammar():t(VALUE) { } + + enum + { + VALUE, + STRING, + BOOL, + ENUM + }; + + int t; + string v; +}; + +typedef tars::TC_AutoPtr ConstGrammarPtr; + +/////////////////////////////////////////////// + +/** + * 类型基类 + */ +class Type : virtual public GrammarBase +{ +public: + /** + * 构造函数 + * @param Type + */ + Type():_size(0),_array(false),_pointer(false){}; + + //是否简单类型 + virtual bool isSimple() const { return false;} + + //是否数组类型 + virtual bool isArray() const { return _array;} + virtual void setArray(int size) {_array = true;_size = size;} + virtual int getSize() const {return _size;}; + + //是否指针类型 + virtual bool isPointer() const { return _pointer;} + virtual void setPointer(bool b) {_pointer = b;} +public: + int _size; + bool _array; + bool _pointer; +}; + +typedef tars::TC_AutoPtr TypePtr; + +/** + * 内建类型 + */ +class Builtin : public Type +{ +public: + + enum Kind + { + KindVoid, + KindBool, + KindByte, + KindShort, + KindInt, + KindLong, + KindFloat, + KindDouble, + KindString, + KindVector, + KindMap + }; + + /** + * 构造函数 + * @param kind + */ + Builtin(Kind kind,bool isUnsigned); + + /** + * 类型 + * + * @return Kind + */ + Kind kind() const; + + /** + * 是否是简单类型 + * + * @return bool + */ + bool isSimple() const; + + /** + * 是否是unsined类型 + * + * @return bool + */ + bool isUnsigned() const {return _isUnsigned;} + + /** + * 设置是unsined类型 + * + * @return bool + */ + void setUnsigned(bool isUnsigned = false) {_isUnsigned = isUnsigned;} + + /** + * 缺省值 + * + * @return string + */ + string def() const; + + /** + * 字符串标示 + */ + static const char* builtinTable[]; + +protected: + + Kind _kind; + bool _isUnsigned; +}; + +typedef tars::TC_AutoPtr BuiltinPtr; + +/** + * Vector类型 + */ +class Vector : public Type +{ +public: + /** + * 构造函数 + * @param ptr + */ + Vector(const TypePtr& ptr); + + /** + * 获取类型 + * + * @return TypePtr& + */ + TypePtr& getTypePtr() {return _ptr;} +protected: + TypePtr _ptr; +}; + +typedef tars::TC_AutoPtr VectorPtr; + +/** + * Map类型 + */ +class Map : public Type +{ +public: + /** + * 构造函数 + * @param pleft + * @param pright + */ + Map(const TypePtr& pleft, const TypePtr& pright); + + /** + * 获取左类型 + * + * @return TypePtr& + */ + TypePtr& getLeftTypePtr() {return _pleft;} + + /** + * 获取右类型 + * + * @return TypePtr& + */ + TypePtr& getRightTypePtr() {return _pright;} + +protected: + TypePtr _pleft; + TypePtr _pright; +}; + +typedef tars::TC_AutoPtr MapPtr; + +/** + * 变量定义 + */ +class TypeId : public GrammarBase +{ +public: + /** + * 构造函数 + * @param ptr + * @param id + */ + TypeId(const TypePtr& ptr, const string& id); + + /** + * 变量名称 + * + * @return string + */ + string getId() const { return _id; } + + /** + * 变量类型 + * + * @return Type* + */ + TypePtr& getTypePtr() { return _ptr;} + + /** + * 是否需要该参数 + * + * @return bool + */ + bool isRequire() const { return _bRequire; } + + /** + * 设置必选字段 + * @param tag + */ + void setRequire(int tag); + + /** + * 设置可选字段 + * 只有基本类型才有缺省值 + */ + void setDefault(const string &def); + + /** + * + * 只有基本类型才有缺省值 + */ + void disableDefault(); + + /** + * 设置可选字段 + * @param tag + */ + void setOptional(int tag); + + /** + * tag标识 + */ + int getTag() const { return _tag; } + + /** + * 缺省值 + * + * @return string + */ + string def() const { return _default; } + + /** + * 是否有缺省值 + * + * @return bool + */ + bool hasDefault() const { return _bHasDefault; } + +protected: + TypePtr _ptr; + string _id; + bool _bRequire; + int _tag; + bool _bHasDefault; + string _default; + +public: + int _size; + bool _array; +}; + +typedef tars::TC_AutoPtr TypeIdPtr; + + +//////////////////////////////////////////////////// +// +class Namespace; +typedef tars::TC_AutoPtr NamespacePtr; +/** + * 容器基类, 所有可以包含其他元素的元素都从该基类继承 + */ +class Container : virtual public GrammarBase +{ +public: + /** + * 构造函数 + * @param id + */ + Container(const string &id) : _id(id) + { + } + + /** + * 生成名字空间 + * @param id + * + * @return NamespacePtr + */ + NamespacePtr createNamespace(const string &id); + + /** + * 获取ID + * + * @return string + */ + string getId() const { return _id;} + + /** + * 获取所有的名字空间 + * + * @return vector& + */ + vector &getAllNamespacePtr() { return _ns; } +protected: + string _id; + vector _ns; +}; + +typedef tars::TC_AutoPtr ContainerPtr; + +//////////////////////////////////////////////////// +// +class Const : public GrammarBase +{ +public: + /** + * + * @param tPtr + * @param cPtr + */ + Const(TypeIdPtr &tPtr, ConstGrammarPtr &cPtr) : _tPtr(tPtr), _cPtr(cPtr) + { + } + + /** + * + * + * @return TypePtr& + */ + TypeIdPtr &getTypeIdPtr() { return _tPtr; } + + /** + * + * + * @return ConstGrammarPtr + */ + ConstGrammarPtr getConstGrammarPtr() { return _cPtr; } + +protected: + TypeIdPtr _tPtr; + ConstGrammarPtr _cPtr; +}; + +typedef tars::TC_AutoPtr ConstPtr; + +///////////////////////////////////////////////////////// +// +class Enum : virtual public Container, virtual public Type +{ +public: + Enum(const string &id, const string &sid) : Container(id), _sid(sid) + { + } + + /** + * 添加成员变量 + * @param ptid + */ + void addMember(const TypeIdPtr &ptr); + + /** + * 获取所有的成员变量 + * + * @return vector& + */ + vector& getAllMemberPtr() {return _members;} + + /** + * 获取结构的名称 + * + * @return string + */ + string getSid() const { return _sid; } + + /** + * 是否是简单类型 + * + * @return bool + */ + virtual bool isSimple() const { return true; } + +protected: + + /** + * 每个变量名称 + */ + vector _members; + + /** + * 包含名字的空间的名称 + */ + string _sid; +}; + +typedef tars::TC_AutoPtr EnumPtr; + +//////////////////////////////////////////////////// +// +/** + * 结构 + */ +class Struct : virtual public Container, virtual public Type +{ +public: + /** + * 构造函数 + * @param id + */ + Struct(const string& id, const string &sid) : Container(id), _sid(sid) + { + } + + /** + * 添加成员变量 + * @param ptid + */ + void addTypeId(const TypeIdPtr &ptr); + + /** + * 获取所有的成员变量 + * + * @return vector& + */ + vector& getAllMemberPtr() {return _members;} + + /** + * 获取结构的名称 + * + * @return string + */ + string getSid() const { return _sid; } + + /** + * 增加小于memeber + * @param member + */ + void addKey(const string &member); + + vector getKey() { return _key; } +protected: + vector _members; + vector _key; + string _sid; +}; + +typedef tars::TC_AutoPtr StructPtr; + +//////////////////////////////////////////////////// +// +/** + * 参数描述 + */ +class ParamDecl : public GrammarBase +{ +public: + /** + * 构造 + * @param typeIdPtr + * @param v + */ + ParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k) + : _typeIdPtr(typeIdPtr), _v(v), _k(k) + { + } + + /** + * 变量声明 + * + * @return TypeIdPtr& + */ + TypeIdPtr& getTypeIdPtr() { return _typeIdPtr; } + + /** + * 是否是输出参数 + * + * @return bool + */ + bool isOut() const { return _v; } + + /** + * 是否是需要路由的字段 + * + * @return bool + */ + bool isRouteKey() const { return _k; } + +protected: + TypeIdPtr _typeIdPtr; + bool _v; + bool _k; +}; +typedef tars::TC_AutoPtr ParamDeclPtr; + +/////////////////////////////////////////////////////// +// +/** + * 操作类 + */ +class Operation : public Container +{ +public: + /** + * 构造函数 + * @param id + * @param typePtr + */ + Operation(const string &id, const TypePtr &typePtr) : Container(id), _itag(0) + { + _retPtr = new TypeId(typePtr, "_ret"); + _retPtr->setRequire(_itag); + } + + /** + * 生成一个参数 + * @param typeIdPtr + * @param v + * @param k + * + * @return ParamDeclPtr + */ + ParamDeclPtr createParamDecl(const TypeIdPtr &typeIdPtr, bool v, bool k); + + /** + * 获取返回值类型 + * + * @return TypePtr& + */ + TypeIdPtr &getReturnPtr() { return _retPtr; } + + /** + * 获取所有参数 + * + * @return vector& + */ + vector &getAllParamDeclPtr() { return _ps; } +protected: + int _itag; + TypeIdPtr _retPtr; + vector _ps; +}; + +typedef tars::TC_AutoPtr OperationPtr; +/////////////////////////////////////////////////////// +// +/** + * 接口描述 + */ +class Interface : public Container +{ +public: + /** + * 构造 + * @param id + */ + Interface(const string &id) : Container(id) + { + } + + /** + * 生成一个操作 + * @param id + * @param typePtr + * + * @return OperationPtr + */ + OperationPtr createOperation(const string &id, const TypePtr &typePtr); + + /** + * 获取所有操作 + * + * @return vector& + */ + vector &getAllOperationPtr() { return _ops; } +protected: + vector _ops; +}; + +typedef tars::TC_AutoPtr InterfacePtr; + +///////////////////////////////////////////////////////// +// +/** + * 名字空间 + */ +class Namespace : public Container +{ +public: + /** + * 构造函数 + * @param id + */ + Namespace(const string &id) : Container(id) + { + } + + /** + * 生成接口 + * @param id + * + * @return InterfacePtr + */ + InterfacePtr createInterface(const string &id); + + /** + * 生成结构 + * @param id + * + * @return StructPtr + */ + StructPtr createStruct(const string& id); + + /** + * 生成枚举类型 + * @param id + * + * @return EnumPtr + */ + EnumPtr createEnum(const string &id); + + /** + * + * @param pPtr + * @param cPtr + * + * @return ConstPtr + */ + ConstPtr createConst(TypeIdPtr &pPtr, ConstGrammarPtr &cPtr); + + /** + * 是否有接口 + * + * @return bool + */ + bool hasInterface() const { return !_is.empty(); } + + /** + * 获取所有的接口 + * + * @return vector& + */ + vector &getAllInterfacePtr() { return _is; } + + /** + * 获取所有的结构 + * + * @return vector& + */ + vector &getAllStructPtr() { return _ss; } + + /** + * 生成枚举类型 + * + * @return vector& + */ + vector &getAllEnumPtr() { return _es; } + + /** + * 常量类型 + * + * @return vector& + */ + vector &getAllConstPtr() { return _cs; } + +protected: + vector _is; + vector _ss; + vector _es; + vector _cs; +}; + +///////////////////////////////////////////////////////////////// +/** + * 上下文 + */ +class Context : public tars::TC_HandleBase +{ +public: + /** + * 构造函数 + */ + Context(const string &file) : _currline(1), _filename(file) + { + } + + /** + * 下一行 + */ + void nextLine() { _currline++; } + + /** + * 目前的行 + * + * @return size_t + */ + size_t getCurrLine() { return _currline; } + + /** + * 当前文件名 + * + * @return string + */ + string getFileName() { return _filename; } + + /** + * 添加include的文件 + * @param incl + */ + void addInclude(const string &incl); + + /** + * 添加属于这个文件的名字空间 + * @param c + */ + void addNamespacePtr(const NamespacePtr &c) + { + _namespaces.push_back(c); + } + + /** + * 获取includes的文件 + * + * @return vector + */ + vector getIncludes() { return _includes; } + + /** + * 获取名字空间 + * + * @return vector + */ + vector getNamespaces() { return _namespaces; } + +protected: + size_t _currline; + string _filename; + vector _includes; + vector _namespaces; +}; + +typedef tars::TC_AutoPtr ContextPtr; + +#endif + + diff --git a/third_partly/tarsparse/parse.cpp b/third_partly/tarsparse/parse.cpp new file mode 100644 index 0000000..d39ecea --- /dev/null +++ b/third_partly/tarsparse/parse.cpp @@ -0,0 +1,603 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "parse.h" +#include "tars.tab.hpp" +#include +#include +#include +#include "util/tc_common.h" +#include "util/tc_file.h" + +TarsParsePtr g_parse = new TarsParse(); + +void yyerror(char const *msg) +{ + g_parse->error(msg); +} + +TarsParse::TarsParse() +{ + _bWithTars = false; + _bUseCurrentPath = false; + _itab = 0; + _bUseCurrentPathFirst = false; + initScanner(); +} + +void TarsParse::setTars(bool bWithTars) +{ + _bWithTars = bWithTars; +} + +void TarsParse::setHeader(const string &sHeader) +{ + _sHeader = sHeader; +} + +void TarsParse::setCurrentPriority(bool bFlag) +{ + _bUseCurrentPathFirst = bFlag; +} + +string TarsParse::getHeader() +{ + if(_sHeader.empty()) + return _sHeader; + return _sHeader + "/"; +} + +void TarsParse::clear() +{ + while(!_contexts.empty()) _contexts.pop(); + while(!_contains.empty()) _contains.pop(); + _vcontexts.clear(); + _structs.clear(); + _enums.clear(); + _namespaces.clear(); +} + +void TarsParse::parse(const string& sFileName) +{ + if (_bUseCurrentPath) + { + std::string sTemp = sFileName; + bool isExist = tars::TC_File::isFileExist(sFileName); + + if (!isExist) + { + sTemp = tars::TC_File::extractFileName(sFileName); + } + + clear(); + + _contains.push(new Container("")); + if(!(yyin = fopen(sTemp.c_str(), "r"))) + { + error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno))); + } + + pushFile(sFileName); + + yyparse(); + + return ; + } + + if (_bUseCurrentPathFirst) + { + std::string sTemp = tars::TC_File::extractFileName(sFileName); + bool isExist = tars::TC_File::isFileExist(sTemp); + + if (!isExist) + { + sTemp = sFileName; + } + + clear(); + + _contains.push(new Container("")); + if(!(yyin = fopen(sTemp.c_str(), "r"))) + { + error("open file '" + sFileName + "(" + sTemp + ")" + "' error :" + string(strerror(errno))); + } + + pushFile(sFileName); + + yyparse(); + + return ; + } + + { + clear(); + + _contains.push(new Container("")); + if(!(yyin = fopen(sFileName.c_str(), "r"))) + { + error("open file '" + sFileName + "' error :" + string(strerror(errno))); + } + + pushFile(sFileName); + + yyparse(); + } +} + +void TarsParse::pushFile(const string &file) +{ + ContextPtr c = new Context(file); + _contexts.push(c); + _vcontexts.push_back(c); +} + +ContextPtr TarsParse::popFile() +{ + ContextPtr c = _contexts.top(); + _contexts.pop(); + return c; +} + +bool TarsParse::getFilePath(const string &s, string &file) +{ + if (_bUseCurrentPath) + { + if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"') + { + error("#include need \"FILENAME\""); + } + + file = s.substr(1, s.length() - 2); + + std::string sTemp = file; + bool isExist = tars::TC_File::isFileExist(file); + + if (!isExist) + { + file = tars::TC_File::extractFileName(file); + } + + for(size_t i = 0; i < _vcontexts.size(); i++) + { + if(_vcontexts[i]->getFileName() == file) + { + return false; + } + } + + return true; + } + + if(_bUseCurrentPathFirst) + { + if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"') + { + error("#include need \"FILENAME\""); + } + + file = s.substr(1, s.length() - 2); + + std::string sTemp = tars::TC_File::extractFileName(file); + bool isExist = tars::TC_File::isFileExist(sTemp); + + if (isExist) + { + file = sTemp; + } + + for(size_t i = 0; i < _vcontexts.size(); i++) + { + if(_vcontexts[i]->getFileName() == file) + { + return false; + } + } + + return true; + } + + if(s.length() < 2 || s[0] != '\"' || s[s.length()-1] != '\"') + { + error("#include need \"FILENAME\""); + } + + file = s.substr(1, s.length() - 2); + + if (!tars::TC_File::isFileExist(file)) + { + for (size_t i = 0; i < _vIncludePath.size(); i++) + { + if (tars::TC_File::isFileExist(_vIncludePath[i] + "/" + file)) + { + file = _vIncludePath[i] + "/" + file; + break; + } + } + } + + for(size_t i = 0; i < _vcontexts.size(); i++) + { + if(_vcontexts[i]->getFileName() == file) + { + return false; + } + } + + return true; +} + +string TarsParse::getCurrFileName() +{ + return _contexts.top()->getFileName(); +} + +void TarsParse::nextLine() +{ + _contexts.top()->nextLine(); +} + +ContextPtr TarsParse::currentContextPtr() +{ + return _contexts.top(); +} + +void TarsParse::error(const string &msg) +{ + cerr << _contexts.top()->getFileName() << ": " << _contexts.top()->getCurrLine() << ": error: " << msg << endl; + exit(-1); +} + +int TarsParse::checkKeyword(const string& s) +{ + std::map::const_iterator it = _keywordMap.find(s); + if(it != _keywordMap.end()) + { + return it->second; + } + + if(!_bWithTars) + { + string sPrefix = "tars"; + //不能以tars开头 + if((s.length() >= sPrefix.length()) && (s.substr(0, sPrefix.length()) == sPrefix)) + { + error("identifier can't start with 'tars'"); + } + } + + return TARS_IDENTIFIER; +} + +void TarsParse::initScanner() +{ + _keywordMap["void"] = TARS_VOID; + _keywordMap["struct"] = TARS_STRUCT; + _keywordMap["bool"] = TARS_BOOL; + _keywordMap["byte"] = TARS_BYTE; + _keywordMap["short"] = TARS_SHORT; + _keywordMap["int"] = TARS_INT; + _keywordMap["double"] = TARS_DOUBLE; + _keywordMap["float"] = TARS_FLOAT; + _keywordMap["long"] = TARS_LONG; + _keywordMap["string"] = TARS_STRING; + _keywordMap["vector"] = TARS_VECTOR; + _keywordMap["map"] = TARS_MAP; + _keywordMap["key"] = TARS_KEY; + _keywordMap["routekey"] = TARS_ROUTE_KEY; + _keywordMap["module"] = TARS_NAMESPACE; + _keywordMap["interface"]= TARS_INTERFACE; + _keywordMap["out"] = TARS_OUT; + _keywordMap["require"] = TARS_REQUIRE; + _keywordMap["optional"] = TARS_OPTIONAL; + _keywordMap["false"] = TARS_FALSE; + _keywordMap["true"] = TARS_TRUE; + _keywordMap["enum"] = TARS_ENUM; + _keywordMap["const"] = TARS_CONST; + _keywordMap["unsigned"] = TARS_UNSIGNED; +} + +string TarsParse::getTab() +{ + ostringstream s; + for(int i = 0; i < _itab; i++) + { + s << " "; + } + + return s.str(); +} + +BuiltinPtr TarsParse::createBuiltin(Builtin::Kind kind,bool isUnsigned) +{ + return new Builtin(kind,isUnsigned); +} + +VectorPtr TarsParse::createVector(const TypePtr &ptr) +{ + return new Vector(ptr); +} + +MapPtr TarsParse::createMap(const TypePtr &pleft, const TypePtr &pright) +{ + return new Map(pleft, pright); +} + +void TarsParse::addNamespacePtr(const NamespacePtr &nPtr) +{ + _namespaces.push_back(nPtr); +} + +NamespacePtr TarsParse::findNamespace(const string &id) +{ + for(size_t i = 0; i < _namespaces.size(); i++) + { + if(_namespaces[i]->getId() == id) + { + return _namespaces[i]; + } + } + + return NULL; +} + +NamespacePtr TarsParse::currentNamespace() +{ + return _namespaces.back(); +} + +void TarsParse::addStructPtr(const StructPtr &sPtr) +{ + _structs.push_back(sPtr); +} + +void TarsParse::addEnumPtr(const EnumPtr &ePtr) +{ + _enums.push_back(ePtr); +} + +StructPtr TarsParse::findStruct(const string &sid) +{ + string ssid = sid; + + //在当前namespace中查找 + NamespacePtr np = currentNamespace(); + if(ssid.find("::") == string::npos) + { + ssid = np->getId() + "::" + ssid; + } + + for(size_t i = 0; i < _structs.size(); i++) + { + if(_structs[i]->getSid() == ssid) + { + return _structs[i]; + } + } + + return NULL; +} + +EnumPtr TarsParse::findEnum(const string &sid) +{ + string ssid = sid; + + //在当前namespace中查找 + NamespacePtr np = currentNamespace(); + if(ssid.find("::") == string::npos) + { + ssid = np->getId() + "::" + sid; + } + + for(size_t i = 0; i < _enums.size(); i++) + { + if(_enums[i]->getSid() == ssid) + { + return _enums[i]; + } + } + + return NULL; +} + +bool TarsParse::checkEnum(const string &idName) +{ + for(size_t i = 0; i < _enums.size(); i++) + { + vector & list = _enums[i]->getAllMemberPtr(); + + for (size_t j = 0; j < list.size(); j++) + { + if (list[j]->getId() == idName) + { + return true; + } + } + } + + return false; +} +void TarsParse::checkConflict(const string &sid) +{ + //是否和枚举重名 + if(findEnum(sid)) + { + error("conflicts with enum '" + sid + "'"); + } + + //是否和结构重名 + if(findStruct(sid)) + { + error("conflicts with struct '" + sid + "'"); + } +} + +TypePtr TarsParse::findUserType(const string &sid) +{ + StructPtr sPtr = findStruct(sid); + if(sPtr) return sPtr; + + EnumPtr ePtr = findEnum(sid); + if(ePtr) return ePtr; + + return NULL; +} + +ContainerPtr TarsParse::currentContainer() +{ + return _contains.top(); +} + +void TarsParse::pushContainer(const ContainerPtr &c) +{ + _contains.push(c); + NamespacePtr np = NamespacePtr::dynamicCast(c); + if(np) + { + addNamespacePtr(np); + } +} + +ContainerPtr TarsParse::popContainer() +{ + ContainerPtr c = _contains.top(); + _contains.pop(); + + return c; +} + +void TarsParse::checkTag(int i) +{ + if(i >= 256) + { + error("struct memeber tag can't beyond 256"); + } + if(i < 0) + { + error("struct memeber tag can't less then 0"); + } +} + +void TarsParse::checkSize(int i) +{ + if(i >= 1024*1024) + { + error("struct memeber size can't beyond 1M"); + } + if(i < 1) + { + error("struct memeber size can't less than 1"); + } +} + +void TarsParse::checkArrayVaid(TypePtr &tPtr,int size) +{ + checkSize(size); + //只有string/vector可以为array类型 + //vector不可以嵌套array类型 例如不允许vector:2; + + VectorPtr vPtr = VectorPtr::dynamicCast(tPtr); + if(vPtr ) + { + if(vPtr->getTypePtr()->isArray()) + { + error("fixed array type can not be nested"); + } + return; + } + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr); + if(bPtr && bPtr->kind()== Builtin::KindString) + { + return; + } + error("only string or vector can use fix array"); +} + +void TarsParse::checkPointerVaid(TypePtr &tPtr) +{ + //必须为vector类型 + + VectorPtr vPtr = VectorPtr::dynamicCast(tPtr); + if(vPtr) + { + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); + if( bPtr && bPtr->kind()== Builtin::KindByte) + return; + } + error("only 'byte *' can be pointer type"); +} + +void TarsParse::checkConstValue(TypeIdPtr &tPtr, int c) +{ + //只有内建类型才能有缺省值 + BuiltinPtr bPtr = BuiltinPtr::dynamicCast(tPtr->getTypePtr()); + EnumPtr ePtr = EnumPtr::dynamicCast(tPtr->getTypePtr()); + if(!bPtr && !ePtr) + { + error("only base/enum type can have default value"); + } + + if (ePtr) + { + if (c != ConstGrammar::VALUE && c != ConstGrammar::ENUM) + { + error("default value of enum only be int or enum_type"); + } + + return ; + } + + int b = bPtr->kind(); + + if(c == ConstGrammar::VALUE) + { + if(b == Builtin::KindBool) + { + error("default value of bool can only be true or false"); + } + if(b == Builtin::KindString) + { + error("default value of string can only be \"string\""); + } + } + else if(c == ConstGrammar::BOOL) + { + if(b != Builtin::KindBool) + { + error("only bool type can be true or false"); + } + } + else if(c == ConstGrammar::STRING) + { + if(b != Builtin::KindString) + { + error("only string type can be \"string\""); + } + } +} + +string TarsParse::printHeaderRemark() +{ + ostringstream s; + s << "// **********************************************************************" << endl; + s << "// This file was generated by a TARS parser!" << endl; + s << "// TARS version " << TARS_VERSION << "." << endl; + s << "// **********************************************************************" << endl; + s << endl; + + return s.str(); +} + + diff --git a/third_partly/tarsparse/parse.h b/third_partly/tarsparse/parse.h new file mode 100644 index 0000000..f47863c --- /dev/null +++ b/third_partly/tarsparse/parse.h @@ -0,0 +1,368 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TARS_PARSE_H_ +#define __TARS_PARSE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "element.h" +#include "util/tc_common.h" +#include "util/tc_autoptr.h" + +using namespace std; + +/** + * Tars文件解析类 + * + */ +class TarsParse : public tars::TC_HandleBase +{ +public: + /** + * 构造函数 + */ + TarsParse(); + + /** + * 是否支持tars开头的标识 + * @param bWithTars + */ + void setTars(bool bWithTars); + + /** + * 头文件路径 + * @param sHeader + */ + void setHeader(const string &sHeader); + + /** + * 是否支持优先使用当前tars文件 + * @param bWithTars + */ + void setCurrentPriority(bool bFlag); + + /** + * 获取头文件路径 + */ + string getHeader(); + + /** + * 解析某一个文件 + * @param sFileName + */ + void parse(const string &sFileName); + + /** + * 错误提示 + * @param msg + */ + void error(const string &msg); + + /** + * 检查关键字 + * @param s + * + * @return int + */ + int checkKeyword(const string &s); + + /** + * 下一行 + */ + void nextLine(); + + /** + * 目前解析的文件名称 + * + * @return string + */ + string getCurrFileName(); + + /** + * tab + * + * @return string + */ + string getTab(); + + /** + * 增加tab数 + */ + void incTab() { _itab++; } + + /** + * 减少tab数 + */ + void delTab() { _itab--; } + + /** + * 解析文件 + * @param file + */ + void pushFile(const string &file); + + /** + * 弹出解析文件 + */ + ContextPtr popFile(); + + /** + * 获取所有的上下文 + * + * @return std::vector + */ + std::vector getContexts() { return _vcontexts; } + + /** + * 获取目前的容器 + * + * @return ContainerPtr + */ + ContainerPtr currentContainer(); + + /** + * push容器 + * @param c + */ + void pushContainer(const ContainerPtr &c); + + /** + * 目前的上下文 + * + * @return ContextPtr + */ + ContextPtr currentContextPtr(); + + /** + * 弹出容器 + * + * @return ContainerPtr + */ + ContainerPtr popContainer(); + + /** + * 生成Builtin元素 + * @param kind + * + * @return BuiltinPtr + */ + BuiltinPtr createBuiltin(Builtin::Kind kind,bool isUnsigned = false); + + /** + * 生成Vector元素 + * @param ptr + * + * @return VectorPtr + */ + VectorPtr createVector(const TypePtr &ptr); + + /** + * 生成Map元素 + * @param pleft + * @param pright + * + * @return MapPtr + */ + MapPtr createMap(const TypePtr &pleft, const TypePtr &pright); + + /** + * 添加结构元素 + * @param sPtr + */ + void addStructPtr(const StructPtr &sPtr); + + /** + * 查找结构 + * @param id + * + * @return StructPtr + */ + StructPtr findStruct(const string &sid); + + /** + * 添加枚举元素 + * @param ePtr + */ + void addEnumPtr(const EnumPtr &ePtr); + + /** + * 查找结构 + * @param id + * + * @return EnumPtr + */ + EnumPtr findEnum(const string &sid); + + /** + * 检查冲突 + * @param id + */ + void checkConflict(const string &sid); + + /** + * 查找自定义类型 + * @param sid + * + * @return TypePtr + */ + TypePtr findUserType(const string &sid); + + /** + * 查找名字空间 + * @param id + * + * @return NamespacePtr + */ + NamespacePtr findNamespace(const string &id); + + /** + * 目前的名字空间 + * + * @return NamespacePtr + */ + NamespacePtr currentNamespace(); + + /** + * 检查tag的合法性 + * @param i + */ + void checkTag(int i); + + + /** + * 检查szie的合法性 + * @param i + */ + void checkSize(int i); + + /** + * 检查array的合法性 + * @param i + */ + void checkArrayVaid(TypePtr &tPtr,int size); + + /** + * 检查pointer的合法性 + * @param i + */ + void checkPointerVaid(TypePtr &tPtr); + + /** + * 检查常量类型和值是否一致 + * @param c + * @param b + */ + void checkConstValue(TypeIdPtr &tPtr, int b); + + /** + * 获取文件名 + * @param s + * + * @return string + */ + bool getFilePath(const string &s, string &file); + + void setKeyStruct(const StructPtr& key) + { + _key = key; + } + + StructPtr getKeyStruct() + { + return _key; + } + + /** + * 打印文件开头注释 + */ + string printHeaderRemark(); + + + /** + * 判断当前的标识符是否是枚举变量 + */ + bool checkEnum(const string &idName); + + /** + + * 设置include的tars文件全部从当前文件搜寻 + */ + void setUseCurrentPath(const bool & bEnable) { _bUseCurrentPath = bEnable; } + + /** + * 查找tars文件时,设置include路径 + */ + void addIncludePath(const string &include) + { + vector v = tars::TC_Common::sepstr(include, "; ,", false); + + _vIncludePath.insert(_vIncludePath.end(), v.begin(), v.end()); + } + +protected: + /** + * 添加名字空间 + * @param nPtr + */ + void addNamespacePtr(const NamespacePtr &nPtr); + + /** + * 初始化 + */ + void initScanner(); + + /** + * 清除 + */ + void clear(); + +protected: + bool _bWithTars; + std::map _keywordMap; + int _itab; + StructPtr _key; + std::stack _contexts; + std::stack _contains; + std::vector _vcontexts; + std::vector _structs; + std::vector _enums; + std::vector _namespaces; + string _sHeader; + bool _bUseCurrentPath; + bool _bUseCurrentPathFirst; + std::vector _vIncludePath; +}; + +extern int yyparse(); +extern int yylex(); +extern FILE *yyin, *yyout; + +typedef tars::TC_AutoPtr TarsParsePtr; + +extern TarsParsePtr g_parse; + +#endif + + diff --git a/third_partly/util/include/util/tc_atomic.h b/third_partly/util/include/util/tc_atomic.h new file mode 100644 index 0000000..9733980 --- /dev/null +++ b/third_partly/util/include/util/tc_atomic.h @@ -0,0 +1,199 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_ATOMIC_H +#define __TC_ATOMIC_H + +#include + +namespace tars +{ + +///////////////////////////////////////////////// +/** + * @file tc_atomic.h + * @brief 原子计数类. + */ + +__BEGIN_DECLS + +#define TARS_LOCK "lock ; " + +typedef struct { volatile int counter; } tars_atomic_t; + +#define tars_atomic_read(v) ((v)->counter) + +#define tars_atomic_set(v,i) (((v)->counter) = (i)) + +__END_DECLS + +/** + * @brief 原子操作类,对int做原子操作 + */ +class TC_Atomic +{ +public: + + /** + * 原子类型 + */ + typedef int atomic_type; + + /** + * @brief 构造函数,初始化为0 + */ + TC_Atomic(atomic_type at = 0) + { + set(at); + } + + TC_Atomic& operator++() + { + inc(); + return *this; + } + + TC_Atomic& operator--() + { + dec(); + return *this; + } + + operator atomic_type() const + { + return get(); + } + + TC_Atomic& operator+=(atomic_type n) + { + add(n); + return *this; + } + + TC_Atomic& operator-=(atomic_type n) + { + sub(n); + return *this; + } + + TC_Atomic& operator=(atomic_type n) + { + set(n); + return *this; + } + + /** + * @brief 获取值 + * + * @return int + */ + atomic_type get() const { return _value.counter; } + + /** + * @brief 添加 + * @param i + * + * @return int + */ + atomic_type add(atomic_type i) { return add_and_return(i); } + + /** + * @brief 减少 + * @param i + * + * @return int + */ + atomic_type sub(atomic_type i) { return add_and_return(-i); } + + /** + * @brief 自加1 + * + * @return int + */ + atomic_type inc() { return add(1); } + + /** + * @brief 自减1 + */ + atomic_type dec() { return sub(1); } + + /** + * @brief 自加1 + * + * @return void + */ + void inc_fast() + { + __asm__ __volatile__( + TARS_LOCK "incl %0" + :"=m" (_value.counter) + :"m" (_value.counter)); + } + + /** + * @brief 自减1 + * Atomically decrements @_value by 1 and returns true if the + * result is 0, or false for all other + */ + bool dec_and_test() + { + unsigned char c; + + __asm__ __volatile__( + TARS_LOCK "decl %0; sete %1" + :"=m" (_value.counter), "=qm" (c) + :"m" (_value.counter) : "memory"); + + return c != 0; + } + + /** + * @brief 设置值 + */ + atomic_type set(atomic_type i) + { + _value.counter = i; + + return i; + } + +protected: + + /** + * @brief 增加并返回值 + */ + int add_and_return(int i) + { + /* Modern 486+ processor */ + int __i = i; + __asm__ __volatile__( + TARS_LOCK "xaddl %0, %1;" + :"=r"(i) + :"m"(_value.counter), "0"(i)); + return i + __i; + } + +protected: + + /** + * 值 + */ + tars_atomic_t _value; +}; + +} + +#endif diff --git a/third_partly/util/include/util/tc_autoptr.h b/third_partly/util/include/util/tc_autoptr.h new file mode 100644 index 0000000..f10dfd6 --- /dev/null +++ b/third_partly/util/include/util/tc_autoptr.h @@ -0,0 +1,508 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_AUTOPTR_H +#define __TC_AUTOPTR_H + +#include "util/tc_atomic.h" +#include "util/tc_ex.h" + +namespace tars +{ +/////////////////////////////////////////////////////// +/** +* @file tc_autoptr.h +* @brief 智能指针类(智能指针不能相互引用, 否则内存泄漏). +*/ +////////////////////////////////////////////////////// + +/** +* @brief 空指针异常 +*/ +struct TC_AutoPtrNull_Exception : public TC_Exception +{ + TC_AutoPtrNull_Exception(const string &buffer) : TC_Exception(buffer){}; + ~TC_AutoPtrNull_Exception() throw(){}; +}; + +/** + * @brief 智能指针基类. + * + * 所有需要智能指针支持的类都需要从该对象继承, + * + * 内部采用引用计数TC_Atomic实现,对象可以放在容器中; + */ +template +class TC_HandleBaseT +{ +public: + + /** 原子计数类型*/ + typedef T atomic_type; + + /** + * @brief 复制. + * + * @return TC_HandleBase& + */ + TC_HandleBaseT& operator=(const TC_HandleBaseT&) + { + return *this; + } + + /** + * @brief 增加计数 + */ + void incRef() { _atomic.inc_fast(); } + + /** + * @brief 减少计数, 当计数==0时, 且需要删除数据时, 释放对象 + */ + void decRef() + { + if(_atomic.dec_and_test() && !_bNoDelete) + { + _bNoDelete = true; + delete this; + } + } + + /** + * @brief 获取计数. + * + * @return int 计数值 + */ + int getRef() const { return _atomic.get(); } + + /** + * @brief 设置不自动释放. + * + * @param b 是否自动删除,true or false + */ + void setNoDelete(bool b) { _bNoDelete = b; } + +protected: + + /** + * @brief 构造函数 + */ + TC_HandleBaseT() : _atomic(0), _bNoDelete(false) + { + } + + /** + * @brief 拷贝构造 + */ + TC_HandleBaseT(const TC_HandleBaseT&) : _atomic(0), _bNoDelete(false) + { + } + + /** + * @brief 析够 + */ + virtual ~TC_HandleBaseT() + { + } + +protected: + + /** + * 计数 + */ + atomic_type _atomic; + + /** + * 是否自动删除 + */ + bool _bNoDelete; +}; + +template<> +inline void TC_HandleBaseT::incRef() +{ + //__sync_fetch_and_add(&_atomic,1); + ++_atomic; +} + +template<> +inline void TC_HandleBaseT::decRef() +{ + //int c = __sync_fetch_and_sub(&_atomic, 1); + //if(c == 1 && !_bNoDelete) + if(--_atomic == 0 && !_bNoDelete) + { + _bNoDelete = true; + delete this; + } +} + +template<> +inline int TC_HandleBaseT::getRef() const +{ + //return __sync_fetch_and_sub(const_cast(&_atomic), 0); + return _atomic; +} + +typedef TC_HandleBaseT TC_HandleBase; + +/** + * @brief 智能指针模板类. + * + * 可以放在容器中,且线程安全的智能指针. + * + * 通过它定义智能指针,该智能指针通过引用计数实现, + * + * 可以放在容器中传递. + * + * template T必须继承于TC_HandleBase + */ +template +class TC_AutoPtr +{ +public: + + /** + * 元素类型 + */ + typedef T element_type; + + /** + * @brief 用原生指针初始化, 计数+1. + * + * @param p + */ + TC_AutoPtr(T* p = 0) + { + _ptr = p; + + if(_ptr) + { + _ptr->incRef(); + } + } + + /** + * @brief 用其他智能指针r的原生指针初始化, 计数+1. + * + * @param Y + * @param r + */ + template + TC_AutoPtr(const TC_AutoPtr& r) + { + _ptr = r._ptr; + + if(_ptr) + { + _ptr->incRef(); + } + } + + /** + * @brief 拷贝构造, 计数+1. + * + * @param r + */ + TC_AutoPtr(const TC_AutoPtr& r) + { + _ptr = r._ptr; + + if(_ptr) + { + _ptr->incRef(); + } + } + + /** + * @brief 析构 + */ + ~TC_AutoPtr() + { + if(_ptr) + { + _ptr->decRef(); + } + } + + /** + * @brief 赋值, 普通指针. + * + * @param p + * @return TC_AutoPtr& + */ + TC_AutoPtr& operator=(T* p) + { + if(_ptr != p) + { + if(p) + { + p->incRef(); + } + + T* ptr = _ptr; + _ptr = p; + + if(ptr) + { + ptr->decRef(); + } + } + return *this; + } + + /** + * @brief 赋值, 其他类型智能指针. + * + * @param Y + * @param r + * @return TC_AutoPtr& + */ + template + TC_AutoPtr& operator=(const TC_AutoPtr& r) + { + if(_ptr != r._ptr) + { + if(r._ptr) + { + r._ptr->incRef(); + } + + T* ptr = _ptr; + _ptr = r._ptr; + + if(ptr) + { + ptr->decRef(); + } + } + return *this; + } + + /** + * @brief 赋值, 该类型其他执政指针. + * + * @param r + * @return TC_AutoPtr& + */ + TC_AutoPtr& operator=(const TC_AutoPtr& r) + { + if(_ptr != r._ptr) + { + if(r._ptr) + { + r._ptr->incRef(); + } + + T* ptr = _ptr; + _ptr = r._ptr; + + if(ptr) + { + ptr->decRef(); + } + } + return *this; + } + + /** + * @brief 将其他类型的智能指针换成当前类型的智能指针. + * + * @param Y + * @param r + * @return TC_AutoPtr + */ + template + static TC_AutoPtr dynamicCast(const TC_AutoPtr& r) + { + return TC_AutoPtr(dynamic_cast(r._ptr)); + } + + /** + * @brief 将其他原生类型的指针转换成当前类型的智能指针. + * + * @param Y + * @param p + * @return TC_AutoPtr + */ + template + static TC_AutoPtr dynamicCast(Y* p) + { + return TC_AutoPtr(dynamic_cast(p)); + } + + /** + * @brief 获取原生指针. + * + * @return T* + */ + T* get() const + { + return _ptr; + } + + /** + * @brief 调用. + * + * @return T* + */ + T* operator->() const + { + if(!_ptr) + { + throwNullHandleException(); + } + + return _ptr; + } + + /** + * @brief 引用. + * + * @return T& + */ + T& operator*() const + { + if(!_ptr) + { + throwNullHandleException(); + } + + return *_ptr; + } + + /** + * @brief 是否有效. + * + * @return bool + */ + operator bool() const + { + return _ptr ? true : false; + } + + /** + * @brief 交换指针. + * + * @param other + */ + void swap(TC_AutoPtr& other) + { + std::swap(_ptr, other._ptr); + } + +protected: + + /** + * @brief 抛出异常 + */ + void throwNullHandleException() const; + +public: + T* _ptr; + +}; + +/** + * @brief 抛出异常. + * + * @param T + * @param file + * @param line + */ +template inline void +TC_AutoPtr::throwNullHandleException() const +{ + throw TC_AutoPtrNull_Exception("autoptr null handle error"); +} + +/** + * @brief ==判断. + * + * @param T + * @param U + * @param lhs + * @param rhs + * + * @return bool + */ +template +inline bool operator==(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) +{ + T* l = lhs.get(); + U* r = rhs.get(); + if(l && r) + { + return *l == *r; + } + else + { + return !l && !r; + } +} + +/** + * @brief 不等于判断. + * + * @param T + * @param U + * @param lhs + * @param rhs + * + * @return bool + */ +template +inline bool operator!=(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) +{ + T* l = lhs.get(); + U* r = rhs.get(); + if(l && r) + { + return *l != *r; + } + else + { + return l || r; + } +} + +/** + * @brief 小于判断, 用于放在map等容器中. + * + * @param T + * @param U + * @param lhs + * @param rhs + * + * @return bool + */ +template +inline bool operator<(const TC_AutoPtr& lhs, const TC_AutoPtr& rhs) +{ + T* l = lhs.get(); + U* r = rhs.get(); + if(l && r) + { + return *l < *r; + } + else + { + return !l && r; + } +} + +} + +#endif diff --git a/third_partly/util/include/util/tc_common.h b/third_partly/util/include/util/tc_common.h new file mode 100644 index 0000000..29375c9 --- /dev/null +++ b/third_partly/util/include/util/tc_common.h @@ -0,0 +1,785 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_COMMON_H +#define __TC_COMMON_H + +#ifndef __USE_XOPEN +#define __USE_XOPEN +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +namespace tars +{ +///////////////////////////////////////////////// +/** +* @file tc_common.h +* @brief 帮助类,都是静态函数,提供一些常用的函数 . +* +*/ +///////////////////////////////////////////////// + + /** + * @brief 基础工具类,提供了一些非常基本的函数使用. + * + * 这些函数都是以静态函数提供。 包括以下几种函数: + * + * Trim类函数,大小写转换函数,分隔字符串函数(直接分隔字符串, + * + * 数字等),时间相关函数,字符串转换函数,二进制字符串互转函数, + * + * 替换字符串函数,Ip匹配函数,判断一个数是否是素数等 + */ +class TC_Common +{ +public: + + /** + * @brief 去掉头部以及尾部的字符或字符串. + * + * @param sStr 输入字符串 + * @param s 需要去掉的字符 + * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @return string 返回去掉后的字符串 + */ + static string trim(const string &sStr, const string &s = " \r\n\t", bool bChar = true); + + /** + * @brief 去掉左边的字符或字符串. + * + * @param sStr 输入字符串 + * @param s 需要去掉的字符 + * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @return string 返回去掉后的字符串 + */ + static string trimleft(const string &sStr, const string &s = " \r\n\t", bool bChar = true); + + /** + * @brief 去掉右边的字符或字符串. + * + * @param sStr 输入字符串 + * @param s 需要去掉的字符 + * @param bChar 如果为true, 则去掉s中每个字符; 如果为false, 则去掉s字符串 + * @return string 返回去掉后的字符串 + */ + static string trimright(const string &sStr, const string &s = " \r\n\t", bool bChar = true); + + /** + * @brief 字符串转换成小写. + * + * @param sString 字符串 + * @return string 转换后的字符串 + */ + static string lower(const string &sString); + + /** + * @brief 字符串转换成大写. + * + * @param sString 字符串 + * @return string 转换后的大写的字符串 + */ + static string upper(const string &sString); + + /** + * @brief 字符串是否都是数字的. + * + * @param sString 字符串 + * @return bool 是否是数字 + */ + static bool isdigit(const string &sInput); + + /** + * @brief 字符串转换成时间结构. + * + * @param sString 字符串时间格式 + * @param sFormat 格式 + * @param stTm 时间结构 + * @return 0: 成功, -1:失败 + */ + static int str2tm(const string &sString, const string &sFormat, struct tm &stTm); + + /** + * @brief GMT格式的时间转化为时间结构 + * + * eg.Sat, 06 Feb 2010 09:29:29 GMT, %a, %d %b %Y %H:%M:%S GMT + * + * 可以用mktime换成time_t, 但是注意时区 可以用mktime(&stTm) + * + * - timezone换成本地的秒(time(NULL)值相同) timezone是系统的 , + * + * 需要extern long timezone; + * + * @param sString GMT格式的时间 + * @param stTm 转换后的时间结构 + * @return 0: 成功, -1:失败 + */ + static int strgmt2tm(const string &sString, struct tm &stTm); + + /** + * @brief 时间转换成字符串. + * + * @param stTm 时间结构 + * @param sFormat 需要转换的目标格式,默认为紧凑格式 + * @return string 转换后的时间字符串 + */ + static string tm2str(const struct tm &stTm, const string &sFormat = "%Y%m%d%H%M%S"); + + /** + * @brief 时间转换成字符串. + * + * @param t 时间结构 + * @param sFormat 需要转换的目标格式,默认为紧凑格式 + * @return string 转换后的时间字符串 + */ + static string tm2str(const time_t &t, const string &sFormat = "%Y%m%d%H%M%S"); + + /** + * @brief 当前时间转换成紧凑格式字符串 + * @param sFormat 格式,默认为紧凑格式 + * @return string 转换后的时间字符串 + */ + static string now2str(const string &sFormat = "%Y%m%d%H%M%S"); + + /** + * @brief 时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @param stTm 时间结构 + * @return string GMT格式的时间字符串 + */ + static string tm2GMTstr(const struct tm &stTm); + + /** + * @brief 时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @param stTm 时间结构 + * @return string GMT格式的时间字符串 + */ + static string tm2GMTstr(const time_t &t); + + /** + * @brief 当前时间转换成GMT字符串,GMT格式:Fri, 12 Jan 2001 18:18:18 GMT + * @return string GMT格式的时间字符串 + */ + static string now2GMTstr(); + + /** + * @brief 当前的日期(年月日)转换成字符串(%Y%m%d). + * + * @return string (%Y%m%d)格式的时间字符串 + */ + static string nowdate2str(); + + /** + * @brief 当前的时间(时分秒)转换成字符串(%H%M%S). + * + * @return string (%H%M%S)格式的时间字符串 + */ + static string nowtime2str(); + + /** + * @brief 获取当前时间的的毫秒数. + * + * @return int64_t 当前时间的的毫秒数 + */ + static int64_t now2ms(); + + /** + * @brief 取出当前时间的微秒. + * + * @return int64_t 取出当前时间的微秒 + */ + static int64_t now2us(); + + /** + * @brief 字符串转化成T型,如果T是数值类型, 如果str为空,则T为0. + * + * @param sStr 要转换的字符串 + * @return T T型类型 + */ + template + static T strto(const string &sStr); + + /** + * @brief 字符串转化成T型. + * + * @param sStr 要转换的字符串 + * @param sDefault 缺省值 + * @return T 转换后的T类型 + */ + template + static T strto(const string &sStr, const string &sDefault); + + /** + * @brief 解析字符串,用分隔符号分隔,保存在vector里 + * + * 例子: |a|b||c| + * + * 如果withEmpty=true时, 采用|分隔为:"","a", "b", "", "c", "" + * + * 如果withEmpty=false时, 采用|分隔为:"a", "b", "c" + * + * 如果T类型为int等数值类型, 则分隔的字符串为"", 则强制转化为0 + * + * @param sStr 输入字符串 + * @param sSep 分隔字符串(每个字符都算为分隔符) + * @param withEmpty true代表空的也算一个元素, false时空的过滤 + * @return 解析后的字符vector + */ + template + static vector sepstr(const string &sStr, const string &sSep, bool withEmpty = false); + + /** + * @brief T型转换成字符串,只要T能够使用ostream对象用<<重载,即可以被该函数支持 + * @param t 要转换的数据 + * @return 转换后的字符串 + */ + template + static string tostr(const T &t); + + /** + * @brief vector转换成string. + * + * @param t 要转换的vector型的数据 + * @return 转换后的字符串 + */ + template + static string tostr(const vector &t); + + /** + * @brief 把map输出为字符串. + * + * @param map 要转换的map对象 + * @return string 输出的字符串 + */ + template + static string tostr(const map &t); + + /** + * @brief map输出为字符串. + * + * @param multimap map对象 + * @return 输出的字符串 + */ + template + static string tostr(const multimap &t); + + /** + * @brief pair 转化为字符串,保证map等关系容器可以直接用tostr来输出 + * @param pair pair对象 + * @return 输出的字符串 + */ + template + static string tostr(const pair &itPair); + + /** + * @brief container 转换成字符串. + * + * @param iFirst 迭代器 + * @param iLast 迭代器 + * @param sSep 两个元素之间的分隔符 + * @return 转换后的字符串 + */ + template + static string tostr(InputIter iFirst, InputIter iLast, const string &sSep = "|"); + + /** + * @brief 二进制数据转换成字符串. + * + * @param buf 二进制buffer + * @param len buffer长度 + * @param sSep 分隔符 + * @param lines 多少个字节换一行, 默认0表示不换行 + * @return 转换后的字符串 + */ + static string bin2str(const void *buf, size_t len, const string &sSep = "", size_t lines = 0); + + /** + * @brief 二进制数据转换成字符串. + * + * @param sBinData 二进制数据 + * @param sSep 分隔符 + * @param lines 多少个字节换一行, 默认0表示不换行 + * @return 转换后的字符串 + */ + static string bin2str(const string &sBinData, const string &sSep = "", size_t lines = 0); + + /** + * @brief 字符串转换成二进制. + * + * @param psAsciiData 字符串 + * @param sBinData 二进制数据 + * @param iBinSize 需要转换的字符串长度 + * @return 转换长度,小于等于0则表示失败 + */ + static int str2bin(const char *psAsciiData, unsigned char *sBinData, int iBinSize); + + /** + * @brief 字符串转换成二进制. + * + * @param sBinData 要转换的字符串 + * @param sSep 分隔符 + * @param lines 多少个字节换一行, 默认0表示不换行 + * @return 转换后的二进制数据 + */ + static string str2bin(const string &sBinData, const string &sSep = "", size_t lines = 0); + + /** + * @brief 替换字符串. + * + * @param sString 输入字符串 + * @param sSrc 原字符串 + * @param sDest 目的字符串 + * @return string 替换后的字符串 + */ + static string replace(const string &sString, const string &sSrc, const string &sDest); + + /** + * @brief 批量替换字符串. + * + * @param sString 输入字符串 + * @param mSrcDest map<原字符串,目的字符串> + * @return string 替换后的字符串 + */ + static string replace(const string &sString, const map& mSrcDest); + + /** + * @brief 匹配以.分隔的字符串,pat中*则代表通配符,代表非空的任何字符串 + * s为空, 返回false ,pat为空, 返回true + * @param s 普通字符串 + * @param pat 带*则被匹配的字符串,用来匹配ip地址 + * @return 是否匹配成功 + */ + static bool matchPeriod(const string& s, const string& pat); + + /** + * @brief 匹配以.分隔的字符串. + * + * @param s 普通字符串 + * @param pat vector中的每个元素都是带*则被匹配的字符串,用来匹配ip地址 + * @return 是否匹配成功 + */ + static bool matchPeriod(const string& s, const vector& pat); + + /** + * @brief 判断一个数是否为素数. + * + * @param n 需要被判断的数据 + * @return true代表是素数,false表示非素数 + */ + static bool isPrimeNumber(size_t n); + + /** + * @brief daemon + */ + static void daemon(); + + /** + * @brief 忽略管道异常 + */ + static void ignorePipe(); + + /** + * @brief 将一个string类型转成一个字节 . + * + * @param sWhat 要转换的字符串 + * @return char 转换后的字节 + */ + static char x2c(const string &sWhat); + + /** + * @brief 大小字符串换成字节数,支持K, M, G两种 例如: 1K, 3M, 4G, 4.5M, 2.3G + * @param s 要转换的字符串 + * @param iDefaultSize 格式错误时, 缺省的大小 + * @return 字节数 + */ + static size_t toSize(const string &s, size_t iDefaultSize); + + /** + * @brief 生成基于16进制字符的随机串 + * @param p 存储随机字符串 + * @param len 字符串大小 + */ + static void getRandomHexChars(char* p, unsigned int len); +}; + +namespace p +{ + template + struct strto1 + { + D operator()(const string &sStr) + { + string s = "0"; + + if(!sStr.empty()) + { + s = sStr; + } + + istringstream sBuffer(s); + + D t; + sBuffer >> t; + + return t; + } + }; + + template<> + struct strto1 + { + char operator()(const string &sStr) + { + if(!sStr.empty()) + { + return sStr[0]; + } + return 0; + } + }; + + template<> + struct strto1 + { + short operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atoi(sStr.c_str()); + } + return 0; + } + }; + + template<> + struct strto1 + { + unsigned short operator()(const string &sStr) + { + if(!sStr.empty()) + { + return strtoul(sStr.c_str(), NULL, 10); + } + return 0; + } + }; + + template<> + struct strto1 + { + int operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atoi(sStr.c_str()); + } + return 0; + } + }; + + template<> + struct strto1 + { + unsigned int operator()(const string &sStr) + { + if(!sStr.empty()) + { + return strtoul(sStr.c_str(), NULL, 10); + } + return 0; + } + }; + + template<> + struct strto1 + { + long operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atol(sStr.c_str()); + } + return 0; + } + }; + + template<> + struct strto1 + { + long long operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atoll(sStr.c_str()); + } + return 0; + } + }; + + template<> + struct strto1 + { + unsigned long operator()(const string &sStr) + { + if(!sStr.empty()) + { + return strtoul(sStr.c_str(), NULL, 10); + } + return 0; + } + }; + + template<> + struct strto1 + { + float operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atof(sStr.c_str()); + } + return 0; + } + }; + + template<> + struct strto1 + { + double operator()(const string &sStr) + { + if(!sStr.empty()) + { + return atof(sStr.c_str()); + } + return 0; + } + }; + + template + struct strto2 + { + D operator()(const string &sStr) + { + istringstream sBuffer(sStr); + + D t; + sBuffer >> t; + + return t; + } + }; + + template<> + struct strto2 + { + string operator()(const string &sStr) + { + return sStr; + } + }; + +} + +template +T TC_Common::strto(const string &sStr) +{ + using strto_type = typename std::conditional::value, p::strto1, p::strto2>::type; + + return strto_type()(sStr); +} + +template +T TC_Common::strto(const string &sStr, const string &sDefault) +{ + string s; + + if(!sStr.empty()) + { + s = sStr; + } + else + { + s = sDefault; + } + + return strto(s); +} + + +template +vector TC_Common::sepstr(const string &sStr, const string &sSep, bool withEmpty) +{ + vector vt; + + string::size_type pos = 0; + string::size_type pos1 = 0; + + while(true) + { + string s; + pos1 = sStr.find_first_of(sSep, pos); + if(pos1 == string::npos) + { + if(pos + 1 <= sStr.length()) + { + s = sStr.substr(pos); + } + } + else if(pos1 == pos) + { + s = ""; + } + else + { + s = sStr.substr(pos, pos1 - pos); + pos = pos1; + } + + if(withEmpty) + { + vt.push_back(strto(s)); + } + else + { + if(!s.empty()) + { + T tmp = strto(s); + vt.push_back(tmp); + } + } + + if(pos1 == string::npos) + { + break; + } + + pos++; + } + + return vt; +} +template +string TC_Common::tostr(const T &t) +{ + ostringstream sBuffer; + sBuffer << t; + return sBuffer.str(); +} + +template +string TC_Common::tostr(const vector &t) +{ + string s; + for(size_t i = 0; i < t.size(); i++) + { + s += tostr(t[i]); + s += " "; + } + return s; +} + +template +string TC_Common::tostr(const map &t) +{ + string sBuffer; + typename map::const_iterator it = t.begin(); + while(it != t.end()) + { + sBuffer += " ["; + sBuffer += tostr(it->first); + sBuffer += "]=["; + sBuffer += tostr(it->second); + sBuffer += "] "; + ++it; + } + return sBuffer; +} + +template +string TC_Common::tostr(const multimap &t) +{ + string sBuffer; + typename multimap::const_iterator it = t.begin(); + while(it != t.end()) + { + sBuffer += " ["; + sBuffer += tostr(it->first); + sBuffer += "]=["; + sBuffer += tostr(it->second); + sBuffer += "] "; + ++it; + } + return sBuffer; +} + +template +string TC_Common::tostr(const pair &itPair) +{ + string sBuffer; + sBuffer += "["; + sBuffer += tostr(itPair.first); + sBuffer += "]=["; + sBuffer += tostr(itPair.second); + sBuffer += "]"; + return sBuffer; +} + +template +string TC_Common::tostr(InputIter iFirst, InputIter iLast, const string &sSep) +{ + string sBuffer; + InputIter it = iFirst; + + while(it != iLast) + { + sBuffer += tostr(*it); + ++it; + + if(it != iLast) + { + sBuffer += sSep; + } + else + { + break; + } + } + + return sBuffer; +} + +} +#endif + diff --git a/third_partly/util/include/util/tc_encoder.h b/third_partly/util/include/util/tc_encoder.h new file mode 100644 index 0000000..a365790 --- /dev/null +++ b/third_partly/util/include/util/tc_encoder.h @@ -0,0 +1,143 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_ENCODER_H_ +#define __TC_ENCODER_H_ + +#include + +#include "util/tc_ex.h" + +namespace tars +{ +///////////////////////////////////////////////// +/** +* @file tc_encoder.h +* @brief 转码类 +* +* +*/ +///////////////////////////////////////////////// + +/** +* @brief 转码异常类 +*/ +struct TC_Encoder_Exception : public TC_Exception +{ + TC_Encoder_Exception(const string &buffer) : TC_Exception(buffer){}; + TC_Encoder_Exception(const string &buffer, int err) : TC_Exception(buffer, err){}; + ~TC_Encoder_Exception() throw(){}; +}; + +/** +* @brief 该类提供基本常用编码的转换. +* +* Gbk到utf8之间的相互转码函数,通过静态函数提供. +* +* 1:GBK ==> UTF8的转换 +* +* 2:UTF8 ==> GBK的转换 +*/ +class TC_Encoder +{ +public: + /** + * @brief gbk 转换到 utf8. + * + * @param sOut 输出buffer + * @param iMaxOutLen 输出buffer最大的长度/sOut的长度 + * @param sIn 输入buffer + * @param iInLen 输入buffer长度 + * @throws TC_Encoder_Exception + * @return + */ + static void gbk2utf8(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen); + + /** + * @brief gbk 转换到 utf8. + * + * @param sIn 输入buffer* + * @throws TC_Encoder_Exception + * @return 转换后的utf8编码 + */ + static string gbk2utf8(const string &sIn); + + /** + * @brief gbk 转换到 utf8. + * + * @param sIn 输入buffer + * @param vtStr 输出gbk的vector + * @throws TC_Encoder_Exception + * @return + */ + static void gbk2utf8(const string &sIn, vector &vtStr); + + /** + * @brief utf8 转换到 gbk. + * + * @param sOut 输出buffer + * @param iMaxOutLen 输出buffer最大的长度/sOut的长度 + * @param sIn 输入buffer + * @param iInLen 输入buffer长度 + * @throws TC_Encoder_Exception + * @return + */ + static void utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen); + + /** + * @brief utf8 转换到 gbk. + * + * @param sIn 输入buffer + * @throws TC_Encoder_Exception + * @return 转换后的gbk编码 + */ + static string utf82gbk(const string &sIn); + + /** + * @brief 将string的\n替换掉,转义字符串中的某个字符 + * + * 缺省:\n 转换为 \r\0; \r转换为\, + * + * 主要用于将string记录在一行,通常用于写bin-log的地方; + * @param str 待转换字符串 + * @param f 需要转义的字符 + * @param t 转义后的字符 + * @param u 借用的转义符 + * @return str 转换后的字符串 + */ + static string transTo(const string& str, char f = '\n', char t = '\r', char u = '\0'); + + /** + * @brief 从替换的数据恢复源数据,将 transTo 的字符串还原, + * + * 缺省:\r\0 还原为\n,\r\r还原为, + * + * 主要用于将string记录在一行,通常用于写bin-log的地方 + * @param str 待还原的字符串(必须是transTo后得到的字符串) + * @param f 被转义的字符 + * @param t 转义后的字符 + * @param u 借用的转义符 + * @return str 还原后的字符串 + */ + static string transFrom(const string& str, char f = '\n', char t = '\r', char u = '\0'); +}; + +} + + +#endif + + diff --git a/third_partly/util/include/util/tc_ex.h b/third_partly/util/include/util/tc_ex.h new file mode 100644 index 0000000..ac88af5 --- /dev/null +++ b/third_partly/util/include/util/tc_ex.h @@ -0,0 +1,94 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_EX_H +#define __TC_EX_H + +#include +using namespace std; + +namespace tars +{ +///////////////////////////////////////////////// +/** +* @file tc_ex.h +* @brief 异常类 +*/ +///////////////////////////////////////////////// + +/** +* @brief 异常类. +*/ +class TC_Exception : public exception +{ +public: + /** + * @brief 构造函数,提供了一个可以传入errno的构造函数, + * + * 异常抛出时直接获取的错误信息 + * + * @param buffer 异常的告警信息 + */ + explicit TC_Exception(const string &buffer); + + /** + * @brief 构造函数,提供了一个可以传入errno的构造函数, + * + * 异常抛出时直接获取的错误信息 + * + * @param buffer 异常的告警信息 + * @param err 错误码, 可用strerror获取错误信息 + */ + TC_Exception(const string &buffer, int err); + + /** + * @brief 析够数函 + */ + virtual ~TC_Exception() throw(); + + /** + * @brief 错误信息. + * + * @return const char* + */ + virtual const char* what() const throw(); + + /** + * @brief 获取错误码 + * + * @return 成功获取返回0 + */ + int getErrCode() { return _code; } + +private: + void getBacktrace(); + +private: + /** + * 异常的相关信息 + */ + string _buffer; + + /** + * 错误码 + */ + int _code; + +}; + +} +#endif + diff --git a/third_partly/util/include/util/tc_file.h b/third_partly/util/include/util/tc_file.h new file mode 100644 index 0000000..309f7ad --- /dev/null +++ b/third_partly/util/include/util/tc_file.h @@ -0,0 +1,289 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_FILE_H_ +#define __TC_FILE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "util/tc_ex.h" +#include "util/tc_common.h" + +namespace tars +{ +///////////////////////////////////////////////// +/** + * @file tc_file.h + * @brief 文件处理类. + * + */ +///////////////////////////////////////////////// + + +/** +* @brief 文件异常类. +* +*/ +struct TC_File_Exception : public TC_Exception +{ + TC_File_Exception(const string &buffer) : TC_Exception(buffer){}; + TC_File_Exception(const string &buffer, int err) : TC_Exception(buffer, err){}; + ~TC_File_Exception() throw(){}; +}; + +/** +* @brief 常用文件名处理函数. +* +*/ +class TC_File +{ +public: + + /** + * @brief 获取文件大小, 如果文件不存在, 则返回-1. + * + * @param sFullFileName 文件全路径(所在目录和文件名) + * @return ofstream::pos_type类型文件大小 + */ + static ifstream::pos_type getFileSize(const string &sFullFileName); + + /** + * @brief 判断是否为绝对路径, 忽略空格以'/'开头. + * + * @param sFullFileName 文件全路径(所在目录和文件名) + * @return ture是绝对路径,false代表非绝对路径 + */ + static bool isAbsolute(const string &sFullFileName); + + /** + * @brief 判断给定路径的文件是否存在. + * 如果文件是符号连接,则以符号连接判断而不是以符号连接指向的文件判断 + * @param sFullFileName 文件全路径 + * @param iFileType 文件类型, 缺省S_IFREG + * @return true代表存在,fals代表不存在 + */ + static bool isFileExist(const string &sFullFileName, mode_t iFileType = S_IFREG); + + /** + * @brief 判断给定路径的文件是否存在. + * 注意: 如果文件是符号连接,则以符号连接指向的文件判断 + * @param sFullFileName 文件全路径 + * @param iFileType 文件类型, 缺省S_IFREG + * @return true-存在,fals-不存在 + */ + static bool isFileExistEx(const string &sFullFileName, mode_t iFileType = S_IFREG); + + /** + * @brief 规则化目录名称, 把一些不用的去掉, 例如./等. + * + * @param path 目录名称 + * @return 规范后的目录名称 + */ + static string simplifyDirectory(const string& path); + + /** + * @brief 创建目录, 如果目录已经存在, 则也返回成功. + * + * @param sFullPath 要创建的目录名称 + * @param iFlag 权限, 默认 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP| S_IXGRP | S_IROTH | S_IXOTH + * @return bool true-创建成功 ,false-创建失败 + */ + static bool makeDir(const string &sDirectoryPath, mode_t iFlag = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + /** + *@brief 循环创建目录, 如果目录已经存在, 则也返回成功. + * + * @param sFullPath 要创建的目录名称 + * @param iFlag 权限, 默认 S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH + * @return true-创建成功,false-创建失败 + */ + + static bool makeDirRecursive(const string &sDirectoryPath, mode_t iFlag = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + + /** + * @brief 设置文件是否可执行. + * + * @param sFullFileName 文件全路径 + * @param canExecutable true表示可执行, false代表不可之行 + * @return 成功返回0, 其他失败 + */ + static int setExecutable(const string &sFullFileName, bool canExecutable); + + /** + * @brief 判断文件是否可执行. + * + * @param sFullFileName 文件全路径 + * @return true-可执行, false-不可执行 + */ + static bool canExecutable(const string &sFullFileName); + + /** + * @brief 删除一个文件或目录. + * + * @param sFullFileName 文件或者目录的全路径 + * @param bRecursive 如果是目录是否递归删除 + * @return 0-成功,失败可以通过errno查看失败的原因 + */ + static int removeFile(const string &sFullFileName, bool bRecursive); + + /** + * @brief 读取文件到string + * 文件存在则返回文件数据,不存在或者读取文件错误的时候, 返回为空 + * @param sFullFileName 文件名称 + * @return 文件数据 + */ + static string load2str(const string &sFullFileName); + + /** + * @brief 读取文件到vector + * 文件存在则返回文件数据,不存在或者读取文件错误的时候, 返回为空 + * @param sFullFileName 文件名称 + */ + static void load2str(const string &sFullFileName, vector &buffer); + + /** + * @brief 写文件. + * + * @param sFullFileName 文件名称 + * @param sFileData 文件内容 + * @return + */ + static void save2file(const string &sFullFileName, const string &sFileData); + + /** + * @brief 写文件. + * + * @param sFullFileName 文件名 + * @param sFileData 数据指针 + * @param length 写入长度 + * @return 0-成功,-1-失败 + */ + static int save2file(const string &sFullFileName, const char *sFileData, size_t length); + + /** + * @brief 获取前当可执行文件路径. + * + * @return string 可执行文件的路径全名称 + */ + static string getExePath(); + + /** + * @brief 提取文件名称 + *从一个完全文件名中去掉路径,例如:/usr/local/temp.gif获取temp.gif + *@param sFullFileName 文件的完全名称 + *@return string 提取后的文件名称 + */ + static string extractFileName(const string &sFullFileName); + + /** + * @brief 从一个完全文件名中提取文件的路径. + * + * 例如1: "/usr/local/temp.gif" 获取"/usr/local/" + * 例如2: "temp.gif" 获取 "./" + * @param sFullFileName 文件的完全名称 + * @return 提取后的文件路径 + */ + static string extractFilePath(const string &sFullFileName); + + /** + * @brief 提取文件扩展名. + * + * 例如1: "/usr/local/temp.gif" 获取"gif" + * 例如2: "temp.gif" 获取"gif" + *@param sFullFileName 文件名称 + *@return 文件扩展名 + */ + static string extractFileExt(const string &sFullFileName); + + /** + * @brief 提取文件名称,去掉扩展名. + * 例如1: "/usr/local/temp.gif" 获取"/usr/local/temp" + * 例如2: "temp.gif" 获取"temp" + * @param sFullFileName 文件名称 + * @return 去掉扩展名的文件名称 + */ + static string excludeFileExt(const string &sFullFileName); + + /** + * @brief 替换文件扩展名 + * + * 改变文件类型,如果无扩展名,则加上扩展名 =?1: + * 例如1:"/usr/temp.gif" 替 换 "jpg" 得到"/usr/temp.jpg" + * 例如2: "/usr/local/temp" 替 换 "jpg" 得到"/usr/local/temp.jpg" + * @param sFullFileName 文件名称 + * @param sExt 扩展名 + * @return 替换扩展名后的文件名 + */ + static string replaceFileExt(const string &sFullFileName, const string &sExt); + + /** + * @brief 从一个url中获取完全文件名. + * + * 获取除http://外,第一个'/'后面的所有字符 + * 例如1:http://www.qq.com/tmp/temp.gif 获取tmp/temp.gif + * 例如2:www.qq.com/tmp/temp.gif 获取tmp/temp.gif + * 例如3:/tmp/temp.gif 获取tmp/temp.gif + * @param sUrl url字符串 + * @return 文件名称 + */ + static string extractUrlFilePath(const string &sUrl); + + /** + * @brief 遍历文件时确定是否选择. + * + * @return 1-选择, 0-不选择 + */ + typedef int (*FILE_SELECT)(const dirent *); + + /** + * @brief 扫描一个目录. + * + * @param sFilePath 需要扫描的路径 + * @param vtMatchFiles 返回的文件名矢量表 + * @param f 匹配函数,为NULL表示所有文件都获取 + * @param iMaxSize 最大文件个数,iMaxSize <=0时,返回所有匹配文件 + * @return 文件个数 + */ + static size_t scanDir(const string &sFilePath, vector &vtMatchFiles, FILE_SELECT f = NULL, int iMaxSize = 0); + + /** + * @brief 遍历目录, 获取目录下面的所有文件和子目录. + * + * @param path 需要遍历的路径 + * @param files 目标路径下面所有文件 + * @param bRecursive 是否递归子目录 + * + **/ + static void listDirectory(const string &path, vector &files, bool bRecursive); + + /** + * @brief 复制文件或目录. + * 将文件或者目录从sExistFile复制到sNewFile + * @param sExistFile 复制的文件或者目录源路径 + * @param sNewFile 复制的文件或者目录目标路径 + * @param bRemove 是否先删除sNewFile再copy ,防止Textfile busy导致复制失败 + * @return + */ + static void copyFile(const string &sExistFile, const string &sNewFile,bool bRemove = false); +}; + +} +#endif // TC_FILE_H diff --git a/third_partly/util/include/util/tc_option.h b/third_partly/util/include/util/tc_option.h new file mode 100644 index 0000000..ad707f2 --- /dev/null +++ b/third_partly/util/include/util/tc_option.h @@ -0,0 +1,111 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#ifndef __TC_OPTION_H +#define __TC_OPTION_H + +#include +#include +#include +#include +using namespace std; + +namespace tars +{ +///////////////////////////////////////////////// +/** + * @file tc_option.h + * @brief 命令行参数解析类. + * + */ +///////////////////////////////////////////////// +/** + * @brief 命令解析类,通常用于解析命令行参数 + * + * 支持以下形式的参数: ./main.exe --name=value --with abc def + */ +class TC_Option +{ +public: + /** + * @brief 构造函数 + */ + TC_Option(){}; + + /** + * @brief 解码. + * + * @param argc 参数个数 + * @param argv 参数数组 + * + */ + void decode(int argc, char *argv[]); + + /** + * @brief 是否存在某个--标识的参数. + * + * @param sName 要判断的标识 + * @return bool 存在返回true,否则返回false + */ + bool hasParam(const string &sName); + + /** + * @brief 获取某个--表示的参数,如果参数不存在或者参数值为空 , + * 都返回"" + * @param sName 标识 + * @return string 标识的参数值 + */ + string getValue(const string &sName); + + /** + * @brief 获取所有--标识的参数. + * + * @return map map类型的标识和参数值的对应关系 + */ + map& getMulti(); + + /** + * @brief 获取所有普通的参数, 例子中的abc, + * def,参数按照顺序在vector中 + * @return vector 顺序存放参数的vector + */ + vector& getSingle(); + +protected: + + /** + * @brief 解析字符串,取出标识和其对应的参数值, + * 对型如--name=value 的字符串进行解析,取出name和vaue + * @param s 要解析的字符串 + */ + void parse(const string &s); + +protected: + /** + *存放标识和其对应参数的对应关系,例如:对于--name=value,存放name和value + */ + map _mParam; + + /** + *存放普通参数的vetor + */ + vector _vSingle; +}; + +} + +#endif + diff --git a/third_partly/util/src/tc_common.cpp b/third_partly/util/src/tc_common.cpp new file mode 100644 index 0000000..af6b9d1 --- /dev/null +++ b/third_partly/util/src/tc_common.cpp @@ -0,0 +1,757 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "util/tc_common.h" +#include +#include +#include +#include + +namespace tars +{ +template <> +string TC_Common::tostr(const bool &t) +{ + char buf[2]; + buf[0] = t ? '1' : '0'; + buf[1] = '\0'; + return string(buf); +} + + +template <> +string TC_Common::tostr(const char &t) +{ + char buf[2]; + snprintf(buf, 2, "%c", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const unsigned char &t) +{ + char buf[2]; + snprintf(buf, 2, "%c", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const short &t) +{ + char buf[16]; + snprintf(buf, 16, "%d", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const unsigned short &t) +{ + char buf[16]; + snprintf(buf, 16, "%u", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const int &t) +{ + char buf[16]; + snprintf(buf, 16, "%d", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const unsigned int &t) +{ + char buf[16]; + snprintf(buf, 16, "%u", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const long &t) +{ + char buf[32]; + snprintf(buf, 32, "%ld", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const long long &t) +{ + char buf[32]; + snprintf(buf, 32, "%lld", t); + return string(buf); +} + + +template <> +string TC_Common::tostr(const unsigned long &t) +{ + char buf[32]; + snprintf(buf, 32, "%lu", t); + return string(buf); +} + +template <> +string TC_Common::tostr(const float &t) +{ + char buf[32]; + snprintf(buf, 32, "%.5f", t); + string s(buf); + + //去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1 + bool bFlag = false; + int pos = int(s.size() - 1); + for(; pos > 0; --pos) + { + if(s[pos] == '0') + { + bFlag = true; + if(s[pos-1] == '.') + { + //-2为了去掉"."号 + pos -= 2; + break; + } + } + else + { + break; + } + } + + if(bFlag) + s = s.substr(0, pos+1); + + return s; +} + +template <> +string TC_Common::tostr(const double &t) +{ + char buf[32]; + snprintf(buf, 32, "%.5f", t); + string s(buf); + + //去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1 + bool bFlag = false; + int pos = int(s.size() - 1); + for(; pos > 0; --pos) + { + if(s[pos] == '0') + { + bFlag = true; + if(s[pos-1] == '.') + { + //-2为了去掉"."号 + pos -= 2; + break; + } + } + else + { + break; + } + } + + if(bFlag) + s = s.substr(0, pos+1); + + return s; + +} + +template <> +string TC_Common::tostr(const long double &t) +{ + char buf[32]; + snprintf(buf, 32, "%Lf", t); + string s(buf); + + //去掉无效0, eg. 1.0300 -> 1.03;1.00 -> 1 + bool bFlag = false; + int pos = int(s.size() - 1); + for(; pos > 0; --pos) + { + if(s[pos] == '0') + { + bFlag = true; + if(s[pos-1] == '.') + { + //-2为了去掉"."号 + pos -= 2; + break; + } + } + else + { + break; + } + } + + if(bFlag) + s = s.substr(0, pos+1); + + return s; + +} + +template <> +string TC_Common::tostr(const std::string &t) +{ + return t; +} + +string TC_Common::trim(const string &sStr, const string &s, bool bChar) +{ + if(sStr.empty()) + { + return sStr; + } + + /** + * 将完全与s相同的字符串去掉 + */ + if(!bChar) + { + return trimright(trimleft(sStr, s, false), s, false); + } + + return trimright(trimleft(sStr, s, true), s, true); +} + +string TC_Common::trimleft(const string &sStr, const string &s, bool bChar) +{ + if(sStr.empty()) + { + return sStr; + } + + /** + * 去掉sStr左边的字符串s + */ + if(!bChar) + { + if(sStr.length() < s.length()) + { + return sStr; + } + + if(sStr.compare(0, s.length(), s) == 0) + { + return sStr.substr(s.length()); + } + + return sStr; + } + + /** + * 去掉sStr左边的 字符串s中的字符 + */ + string::size_type pos = 0; + while(pos < sStr.length()) + { + if(s.find_first_of(sStr[pos]) == string::npos) + { + break; + } + + pos++; + } + + if(pos == 0) return sStr; + + return sStr.substr(pos); +} + +string TC_Common::trimright(const string &sStr, const string &s, bool bChar) +{ + if(sStr.empty()) + { + return sStr; + } + + /** + * 去掉sStr右边的字符串s + */ + if(!bChar) + { + if(sStr.length() < s.length()) + { + return sStr; + } + + if(sStr.compare(sStr.length() - s.length(), s.length(), s) == 0) + { + return sStr.substr(0, sStr.length() - s.length()); + } + + return sStr; + } + + /** + * 去掉sStr右边的 字符串s中的字符 + */ + string::size_type pos = sStr.length(); + while(pos != 0) + { + if(s.find_first_of(sStr[pos-1]) == string::npos) + { + break; + } + + pos--; + } + + if(pos == sStr.length()) return sStr; + + return sStr.substr(0, pos); +} + +string TC_Common::lower(const string &s) +{ + string sString = s; + for (string::iterator iter = sString.begin(); iter != sString.end(); ++iter) + { + *iter = tolower(*iter); + } + + return sString; +} + +string TC_Common::upper(const string &s) +{ + string sString = s; + + for (string::iterator iter = sString.begin(); iter != sString.end(); ++iter) + { + *iter = toupper(*iter); + } + + return sString; +} + +bool TC_Common::isdigit(const string &sInput) +{ + string::const_iterator iter = sInput.begin(); + + if(sInput.empty()) + { + return false; + } + + while(iter != sInput.end()) + { + if (!::isdigit(*iter)) + { + return false; + } + ++iter; + } + return true; +} + +int TC_Common::str2tm(const string &sString, const string &sFormat, struct tm &stTm) +{ + char *p = strptime(sString.c_str(), sFormat.c_str(), &stTm); + return (p != NULL) ? 0 : -1; +} + +int TC_Common::strgmt2tm(const string &sString, struct tm &stTm) +{ + return str2tm(sString, "%a, %d %b %Y %H:%M:%S GMT", stTm); +} + +string TC_Common::tm2str(const struct tm &stTm, const string &sFormat) +{ + char sTimeString[255] = "\0"; + + strftime(sTimeString, sizeof(sTimeString), sFormat.c_str(), &stTm); + + return string(sTimeString); +} + +string TC_Common::tm2str(const time_t &t, const string &sFormat) +{ + struct tm tt; + localtime_r(&t, &tt); + + return tm2str(tt, sFormat); +} + +string TC_Common::now2str(const string &sFormat) +{ + time_t t = time(NULL); + return tm2str(t, sFormat.c_str()); +} + +string TC_Common::now2GMTstr() +{ + time_t t = time(NULL); + return tm2GMTstr(t); +} + +string TC_Common::tm2GMTstr(const time_t &t) +{ + struct tm tt; + gmtime_r(&t, &tt); + return tm2str(tt, "%a, %d %b %Y %H:%M:%S GMT"); +} + +string TC_Common::tm2GMTstr(const struct tm &stTm) +{ + return tm2str(stTm, "%a, %d %b %Y %H:%M:%S GMT"); +} + +string TC_Common::nowdate2str() +{ + return now2str("%Y%m%d"); +} + +string TC_Common::nowtime2str() +{ + return now2str("%H%M%S"); +} + +int64_t TC_Common::now2ms() +{ + struct timeval tv; + + gettimeofday(&tv, 0); + + return tv.tv_sec * (int64_t)1000 + tv.tv_usec/1000; +} + +int64_t TC_Common::now2us() +{ + struct timeval tv; + + gettimeofday(&tv, 0); + + return tv.tv_sec * (int64_t)1000000 + tv.tv_usec; +} + +//参照phorix的优化 +static char c_b2s[256][4]={"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f","10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f","20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f","30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f","40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f","50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f","60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f","70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f","80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f","90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f","a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af","b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf","c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf","d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df","e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef","f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff"}; + +string TC_Common::bin2str(const void *buf, size_t len, const string &sSep, size_t lines) +{ + if(buf == NULL || len <=0 ) + { + return ""; + } + + string sOut; + const unsigned char *p = (const unsigned char *) buf; + + for (size_t i = 0; i < len; ++i, ++p) + { + sOut += c_b2s[*p][0]; + sOut += c_b2s[*p][1]; + sOut += sSep; + + //换行 + if ((lines != 0) && ((i+1) % lines == 0)) + { + sOut += "\n"; + } + } + + return sOut; +} + +string TC_Common::bin2str(const string &sBinData, const string &sSep, size_t lines) +{ + return bin2str((const void *)sBinData.data(), sBinData.length(), sSep, lines); +} + +int TC_Common::str2bin(const char *psAsciiData, unsigned char *sBinData, int iBinSize) +{ + int iAsciiLength = strlen(psAsciiData); + + int iRealLength = (iAsciiLength/2 > iBinSize)?iBinSize:(iAsciiLength/2); + for (int i = 0 ; i < iRealLength ; i++) + { + sBinData[i] = x2c(psAsciiData + i*2); + } + return iRealLength; +} + +string TC_Common::str2bin(const string &sString, const string &sSep, size_t lines) +{ + const char *psAsciiData = sString.c_str(); + + int iAsciiLength = sString.length(); + string sBinData; + for (int i = 0 ; i < iAsciiLength ; i++) + { + sBinData += x2c(psAsciiData + i); + i++; + i += sSep.length(); //过滤掉分隔符 + + if (lines != 0 && sBinData.length()%lines == 0) + { + i++; //过滤掉回车 + } + } + + return sBinData; +} + +char TC_Common::x2c(const string &sWhat) +{ + register char digit; + + if(sWhat.length() < 2) + { + return '\0'; + } + + digit = (sWhat[0] >= 'A' ? ((sWhat[0] & 0xdf) - 'A')+10 : (sWhat[0] - '0')); + digit *= 16; + digit += (sWhat[1] >= 'A' ? ((sWhat[1] & 0xdf) - 'A')+10 : (sWhat[1] - '0')); + + return(digit); +} + +string TC_Common::replace(const string &sString, const string &sSrc, const string &sDest) +{ + if(sSrc.empty()) + { + return sString; + } + + string sBuf = sString; + + string::size_type pos = 0; + + while( (pos = sBuf.find(sSrc, pos)) != string::npos) + { + sBuf.replace(pos, sSrc.length(), sDest); + pos += sDest.length(); + } + + return sBuf; +} + +string TC_Common::replace(const string &sString, const map& mSrcDest) +{ + if(sString.empty()) + { + return sString; + } + + string tmp = sString; + map::const_iterator it = mSrcDest.begin(); + + while(it != mSrcDest.end()) + { + + string::size_type pos = 0; + while((pos = tmp.find(it->first, pos)) != string::npos) + { + tmp.replace(pos, it->first.length(), it->second); + pos += it->second.length(); + } + + ++it; + } + + return tmp; +} + +bool TC_Common::matchPeriod(const string& s, const string& pat) +{ + if(s.empty()) + { + return false; + } + + if(pat.empty()) + { + return true; + } + + if(pat.find('*') == string::npos) + { + return s == pat; + } + + string::size_type sIndex = 0; + string::size_type patIndex = 0; + do + { + if(pat[patIndex] == '*') + { + if(s[sIndex] == '.') + { + return false; + } + + while(sIndex < s.size() && s[sIndex] != '.') + { + ++sIndex; + } + patIndex++; + } + else + { + if(pat[patIndex] != s[sIndex]) + { + return false; + } + ++sIndex; + ++patIndex; + } + } + while(sIndex < s.size() && patIndex < pat.size()); + + return sIndex == s.size() && patIndex == pat.size(); +} + +bool TC_Common::matchPeriod(const string& s, const vector& pat) +{ + for(size_t i = 0; i < pat.size(); i++) + { + if(TC_Common::matchPeriod(s,pat[i])) + { + return true; + } + } + return false; +} + +void TC_Common::daemon() +{ + pid_t pid; + + if ((pid = fork()) != 0) + { + exit(0); + } + + setsid(); + + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGQUIT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGTTOU, SIG_IGN); + signal(SIGTTIN, SIG_IGN); + signal(SIGCHLD, SIG_IGN); + signal(SIGTERM, SIG_IGN); + ignorePipe(); + + if((pid = fork()) != 0) + { + //父进程结束,变成daemon + exit(0); + } + + umask(0); + + // chdir("/"); +} + +void TC_Common::ignorePipe() +{ + struct sigaction sig; + + memset(&sig,0,sizeof(struct sigaction)); + + sig.sa_handler = SIG_IGN; + sig.sa_flags = 0; + sigemptyset(&sig.sa_mask); + sigaction(SIGPIPE,&sig,NULL); +} + +bool TC_Common::isPrimeNumber(size_t n) +{ + size_t nn = (size_t)sqrt((double)n); + for(size_t i = 2; i < nn;i++) + { + if(n % i == 0) + { + return false; + } + } + return true; +} + +size_t TC_Common::toSize(const string &s, size_t iDefaultSize) +{ + if (s.empty()) + { + return iDefaultSize; + } + + char c = s[s.length()-1]; + if(c != 'K' && c != 'M' && c != 'G' && TC_Common::trim(s) == TC_Common::tostr(TC_Common::strto(s))) + { + //没有后缀, 且转换是正确的 + return (size_t)(TC_Common::strto(s)); + } + else if(c == 'K' || c == 'M' || c == 'G') + { + if (s.length() == 1) + { + return iDefaultSize; + } + + float n = TC_Common::strto(s.substr(0, s.length()-1)); + + if(TC_Common::trim(s.substr(0, s.length()-1)) != TC_Common::tostr(n)) + { + return iDefaultSize; + } + + if(c == 'K') + { + return (size_t)(n * 1024); + } + if(c == 'M') + { + return (size_t)(n * 1024*1024); + } + if(c == 'G') + { + return (size_t)(n * 1024 * 1024 * 1024); + } + } + + return iDefaultSize; +} + +// Generate the randome string, a SHA1-sized random number +void TC_Common::getRandomHexChars(char* p, unsigned int len) +{ + const char* const chars = "0123456789abcdef"; + FILE *fp = fopen("/dev/urandom","r"); + if (!fp || fread(p,len,1,fp) == 0) + { + for (unsigned int j = 0; j < len; j++) + p[j] ^= rand(); + } + + if (fp) fclose(fp); + + for (unsigned int j = 0; j < len; j++) + p[j] = chars[p[j] & 0x0F]; + +} + +} + diff --git a/third_partly/util/src/tc_encoder.cpp b/third_partly/util/src/tc_encoder.cpp new file mode 100644 index 0000000..abfc3af --- /dev/null +++ b/third_partly/util/src/tc_encoder.cpp @@ -0,0 +1,310 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include +#include +#include +#include "util/tc_encoder.h" + +namespace tars +{ + +void TC_Encoder::gbk2utf8(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen) +{ + char * pIn = (char*)sIn; + char * pEnd = pIn+iInLen; + char * pOut = sOut; + size_t iLeftLen; + size_t iGbkLen; + iconv_t cd; + + if (iInLen > iMaxOutLen) + { + throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iInLen > iMaxOutLen error : ", errno); + } + + cd = iconv_open("UTF-8","GBK"); + if (cd == (iconv_t)-1) + { + throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error : ", errno); + } + + iLeftLen = iMaxOutLen; + while(pIn < pEnd) + { + if((unsigned char)(*pIn)==0x80) + { + //注意GBK的0x80转换为UTF-8时为E2 82 AC + *pOut = 0xe2; pOut++; iLeftLen--; + *pOut = 0x82; pOut++; iLeftLen--; + *pOut = 0xac; pOut++; iLeftLen--; + pIn++; + } + else if((unsigned char)(*pIn)<0x80) + { + //单字节(GBK: 0x00-0x7F) + *pOut = *pIn; + pIn++;pOut++;iLeftLen--; + } + else + { + //双字节 + iGbkLen=2; + int iRet=iconv(cd, &pIn, (size_t *)&iGbkLen, (char **)&pOut, (size_t *)&iLeftLen); + if(iRet < 0) + { + *pOut = ' '; //转换不了替换为空格 + pIn+=2; pOut++; iLeftLen--; + } + } + } + + iconv_close(cd); + sOut[iMaxOutLen - iLeftLen] = '\0'; + iMaxOutLen = iMaxOutLen - iLeftLen; +} + +string TC_Encoder::gbk2utf8(const string &sIn) +{ + iconv_t cd; + + cd = iconv_open("UTF-8","GBK"); + if (cd == (iconv_t)-1) + { + throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", errno); + } + + string sOut; + + for(string::size_type pos = 0; pos < sIn.length(); ++pos) + { + if((unsigned char)sIn[pos] == 0x80) + { + //注意GBK的0x80转换为UTF-8时为E2 82 AC + sOut += 0xe2; + sOut += 0x82; + sOut += 0xac; + } + else if((unsigned char)sIn[pos] < 0x80) + { + //单字节(GBK: 0x00-0x7F) + sOut += sIn[pos]; + } + else + { + //双字节 + size_t sizeGbkLen = 2; + char pIn[128] = "\0"; + + strncpy(pIn, sIn.c_str() + pos, sizeGbkLen); + char *p = pIn; + + size_t sizeLeftLen = 128; + char pOut[128] = "\0"; + char *o = pOut; + int iRet = iconv(cd, &p, &sizeGbkLen, (char **)&o, &sizeLeftLen); + if(iRet < 0) + { + //转换不了, 暂时替换为空格 + sOut += ' '; + } + else + { + sOut += pOut; + } + + ++pos; + + } + } + + iconv_close(cd); + return sOut; +} + +void TC_Encoder::gbk2utf8(const string &sIn, vector &vtStr) +{ + iconv_t cd; + + cd = iconv_open("UTF-8","GBK"); + if (cd == (iconv_t)-1) + { + throw TC_Encoder_Exception("[TC_Encoder::gbk2utf8] iconv_open error", errno); + } + + vtStr.clear(); + + for(string::size_type pos = 0; pos < sIn.length(); ++pos) + { + string sOut; + + if((unsigned char)sIn[pos] == 0x80) + { + //注意GBK的0x80转换为UTF-8时为E2 82 AC + sOut += 0xe2; + sOut += 0x82; + sOut += 0xac; + } + else if((unsigned char)sIn[pos] < 0x80) + { + //单字节(GBK: 0x00-0x7F) + sOut += sIn[pos]; + } + else + { + //双字节 + size_t iGbkLen = 2; + char pIn[128] = "\0"; + + strncpy(pIn, sIn.c_str() + pos, iGbkLen); + char *p = pIn; + + size_t iLeftLen = 128; + char pOut[128] = "\0"; + char *o = pOut; + int iRet = iconv(cd, &p, (size_t *)&iGbkLen, (char **)&o, (size_t *)&iLeftLen); + if(iRet < 0) + { + //转换不了, 暂时替换为空格 + sOut += ' '; + } + else + { + sOut += pOut; + } + + ++pos; + + } + + vtStr.push_back(sOut); + } + + iconv_close(cd); +} + +void TC_Encoder::utf82gbk(char *sOut, int &iMaxOutLen, const char *sIn, int iInLen) +{ + iconv_t cd; + + cd = iconv_open("GBK","UTF-8"); + if (cd == (iconv_t)-1) + { + throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv_open error", errno); + } + + char * pIn = (char*)sIn; + size_t sizeLeftLen = iMaxOutLen; + size_t sizeInLen = iInLen; + char* pOut = sOut; + + size_t ret = iconv(cd, &pIn, &sizeInLen, (char **)&sOut, &sizeLeftLen); + if (ret == (size_t) - 1) + { + iMaxOutLen = 0; + iconv_close(cd); + throw TC_Encoder_Exception("[TC_Encoder::utf82gbk] iconv error", errno); + return; + } + + iconv_close(cd); + + pOut[iMaxOutLen - (int)sizeLeftLen] = '\0'; + + iMaxOutLen = iMaxOutLen - (int)sizeLeftLen; +} + +string TC_Encoder::utf82gbk(const string &sIn) +{ + if(sIn.length() == 0) + { + return ""; + } + + string sOut; + + int iLen = sIn.length() * 2 + 1; + char *pOut = new char[iLen]; + + try + { + utf82gbk(pOut, iLen, sIn.c_str(), sIn.length()); + } + catch (TC_Encoder_Exception& e) + { + delete[] pOut; + + throw e; + } + + sOut.assign(pOut, iLen); + + delete[] pOut; + + return sOut; +} + +/** + * \n -> \r\0 + * \r -> \r\r + */ +string TC_Encoder::transTo(const string& str, char f /*='\n'*/, char t /*= '\r'*/, char u /*= '\0'*/) +{ + string ret = str; + + for (size_t i = 0; i < ret.length(); ++i) + { + if (ret[i] == f) + { + ret[i] = t; + + ret.insert(++i, 1, u); + } + else if (ret[i] == t) + { + ret.insert(++i, 1, t); + } + } + return ret; +} + +/** + * \r\0 -> \n + * \r\r -> \r + */ +string TC_Encoder::transFrom(const string& str, char f /*= '\n'*/, char t /*= '\r'*/, char u /*= '\0'*/) +{ + string ret = ""; + + for (string::const_iterator it = str.begin() + ; it != str.end() + ; ++it) + { + ret.append(1, *it); + + if (*it == t) + { + if (*(++it) == u) + { + *ret.rbegin() = f; + } + } + } + return ret; +} + +} + diff --git a/third_partly/util/src/tc_ex.cpp b/third_partly/util/src/tc_ex.cpp new file mode 100644 index 0000000..9a8d3bb --- /dev/null +++ b/third_partly/util/src/tc_ex.cpp @@ -0,0 +1,62 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "util/tc_ex.h" +#include +#include +#include +#include + +namespace tars +{ + +TC_Exception::TC_Exception(const string &buffer) +:_buffer(buffer), _code(0) +{ +// getBacktrace(); +} + +TC_Exception::TC_Exception(const string &buffer, int err) +{ + _buffer = buffer + " :" + strerror(err); + _code = err; +// getBacktrace(); +} + +TC_Exception::~TC_Exception() throw() +{ +} + +const char* TC_Exception::what() const throw() +{ + return _buffer.c_str(); +} + +void TC_Exception::getBacktrace() +{ + void * array[64]; + int nSize = backtrace(array, 64); + char ** symbols = backtrace_symbols(array, nSize); + + for (int i = 0; i < nSize; i++) + { + _buffer += symbols[i]; + _buffer += "\n"; + } + free(symbols); +} + +} diff --git a/third_partly/util/src/tc_file.cpp b/third_partly/util/src/tc_file.cpp new file mode 100644 index 0000000..6ada8fe --- /dev/null +++ b/third_partly/util/src/tc_file.cpp @@ -0,0 +1,514 @@ +/** + * Tencent is pleased to support the open source community by making Tars available. + * + * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. + * + * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * https://opensource.org/licenses/BSD-3-Clause + * + * Unless required by applicable law or agreed to in writing, software distributed + * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR + * CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +#include "util/tc_file.h" +#include + +namespace tars +{ + +ifstream::pos_type TC_File::getFileSize(const string &sFullFileName) +{ + ifstream ifs(sFullFileName.c_str()); + ifs.seekg(0, ios_base::end); + return ifs.tellg(); +} + +bool TC_File::isAbsolute(const string &sFullFileName) +{ + if(sFullFileName.empty()) + { + return false; + } + + unsigned i = 0; + while(isspace(sFullFileName[i])) + { + ++i; + } + + return sFullFileName[i] == '/'; +} + +bool TC_File::isFileExist(const string &sFullFileName, mode_t iFileType) +{ + struct stat f_stat; + + if (lstat(sFullFileName.c_str(), &f_stat) == -1) + { + return false; + } + + if (!(f_stat.st_mode & iFileType)) + { + return false; + } + + return true; +} + +bool TC_File::isFileExistEx(const string &sFullFileName, mode_t iFileType) +{ + struct stat f_stat; + + if (stat(sFullFileName.c_str(), &f_stat) == -1) + { + return false; + } + + if (!(f_stat.st_mode & iFileType)) + { + return false; + } + + return true; +} + +bool TC_File::makeDir(const string &sDirectoryPath, mode_t iFlag) +{ + int iRetCode = mkdir(sDirectoryPath.c_str(), iFlag); + if(iRetCode < 0 && errno == EEXIST) + { + return isFileExistEx(sDirectoryPath, S_IFDIR); + } + + return iRetCode == 0; +} + +bool TC_File::makeDirRecursive(const string &sDirectoryPath, mode_t iFlag) +{ + string simple = simplifyDirectory(sDirectoryPath); + + string::size_type pos = 0; + for(; pos != string::npos; ) + { + pos = simple.find("/", pos + 1); + string s; + if(pos == string::npos) + { + s = simple.substr(0, simple.size()); + return makeDir(s.c_str(), iFlag); + } + else + { + s = simple.substr(0, pos); + if(!makeDir(s.c_str(), iFlag)) return false; + } + } + return true; +} + +int TC_File::setExecutable(const string &sFullFileName, bool canExecutable) +{ + struct stat f_stat; + + if (stat(sFullFileName.c_str(), &f_stat) == -1) + { + return -1; + } + + return chmod(sFullFileName.c_str(), canExecutable ? f_stat.st_mode | S_IXUSR : f_stat.st_mode & ~S_IXUSR); +} + +bool TC_File::canExecutable(const string &sFullFileName) +{ + struct stat f_stat; + + if (stat(sFullFileName.c_str(), &f_stat) == -1) + { + return false; + } + + return f_stat.st_mode & S_IXUSR; +} + +int TC_File::removeFile(const string &sFullFileName, bool bRecursive) +{ + string path = simplifyDirectory(sFullFileName); + + if(isFileExist(path, S_IFDIR)) + { + if(bRecursive) + { + vector files; + listDirectory(path, files, false); + for(size_t i = 0; i < files.size(); i++) + { + removeFile(files[i], bRecursive); + } + + if(path != "/") + { + if(::rmdir(path.c_str()) == -1) + { + return -1; + } + return 0; + } + } + else + { + if(::rmdir(path.c_str()) == -1) + { + return -1; + } + } + } + else + { + if(::remove(path.c_str()) == -1) + { + return -1; + } + } + + return 0; +} + +string TC_File::simplifyDirectory(const string& path) +{ + string result = path; + + string::size_type pos; + + pos = 0; + while((pos = result.find("//", pos)) != string::npos) + { + result.erase(pos, 1); + } + + pos = 0; + while((pos = result.find("/./", pos)) != string::npos) + { + result.erase(pos, 2); + } + + while(result.substr(0, 4) == "/../") + { + result.erase(0, 3); + } + + if(result == "/.") + { + return result.substr(0, result.size() - 1); + } + + if(result.size() >= 2 && result.substr(result.size() - 2, 2) == "/.") + { + result.erase(result.size() - 2, 2); + } + + if(result == "/") + { + return result; + } + + if(result.size() >= 1 && result[result.size() - 1] == '/') + { + result.erase(result.size() - 1); + } + + if(result == "/..") + { + result = "/"; + } + + return result; +} + +string TC_File::load2str(const string &sFullFileName) +{ + FILE* fp = fopen(sFullFileName.data(), "rb"); + if (!fp) + return ""; + + fseek(fp, 0L, SEEK_END); + long size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + string s(size, '\0'); + fread((void*)s.data(), size, 1, fp); + fclose(fp); + + return s; +} + +void TC_File::load2str(const string &sFullFileName, vector &buffer) +{ + buffer.clear(); + + FILE* fp = fopen(sFullFileName.data(), "rb"); + if (!fp) + return; + + fseek(fp, 0L, SEEK_END); + long size = ftell(fp); + fseek(fp, 0L, SEEK_SET); + + buffer.resize(size); + fread((void*)&buffer[0], size, 1, fp); + fclose(fp); +} + +void TC_File::save2file(const string &sFullFileName, const string &sFileData) +{ + ofstream ofs((sFullFileName).c_str()); + ofs << sFileData; + ofs.close(); +} + +int TC_File::save2file(const string &sFullFileName, const char *sFileData, size_t length) +{ + FILE *fp = fopen(sFullFileName.c_str(), "wb"); + if(fp == NULL) + { + return -1; + } + + size_t ret = fwrite((void*)sFileData, 1, length, fp); + fclose(fp); + + if(ret == length) + { + return 0; + } + return -1; +} + +string TC_File::getExePath() +{ + string proc = "/proc/self/exe"; + char buf[2048] = "\0"; + + int bufsize = sizeof(buf)/sizeof(char); + + int count = readlink(proc.c_str(), buf,bufsize); + + if ( count < 0 ) + { + throw TC_File_Exception("[TC_File::getExePath] could not get exe path error", errno); + } + + count = (count>=bufsize)?(bufsize-1):count; + + buf[count] = '\0'; + return buf; +} + +string TC_File::extractFileName(const string &sFullFileName) +{ + if(sFullFileName.length() <= 0) + { + return ""; + } + + string::size_type pos = sFullFileName.rfind('/'); + if(pos == string::npos) + { + return sFullFileName; + } + + return sFullFileName.substr(pos + 1); +} + +string TC_File::extractFilePath(const string &sFullFileName) +{ + if(sFullFileName.length() <= 0) + { + return "./"; + } + + string::size_type pos = 0; + + for(pos = sFullFileName.length(); pos != 0 ; --pos) + { + if(sFullFileName[pos-1] == '/') + { + return sFullFileName.substr(0, pos); + } + } + + return "./"; +} + +string TC_File::extractFileExt(const string &sFullFileName) +{ + string::size_type pos; + if ((pos = sFullFileName.rfind('.')) == string::npos) + { + return string(""); + } + + return sFullFileName.substr(pos+1); +} + +string TC_File::excludeFileExt(const string &sFullFileName) +{ + string::size_type pos; + if ((pos = sFullFileName.rfind('.')) == string::npos) + { + return sFullFileName; + } + + return sFullFileName.substr(0, pos); +} + +string TC_File::replaceFileExt(const string &sFullFileName, const string &sExt) +{ + return excludeFileExt(sFullFileName) + "." + sExt; +} + +string TC_File::extractUrlFilePath(const string &sUrl) +{ + string sLowerUrl = TC_Common::lower(sUrl); + string::size_type pos = sLowerUrl.find("http://"); + + if(pos == 0) + { + pos += strlen("http://"); + } + else if(pos == string::npos) + { + pos = 0; + } + + for( ; pos < sUrl.length(); ++pos) + { + if(sUrl[pos] == '/') + { + if(pos < sUrl.length() - 1) + { + pos++; + break; + } + else + { + return ""; + } + } + } + + if(pos == string::npos || pos == sUrl.length()) + { + pos = 0; + } + + return sUrl.substr(pos); +} + +size_t TC_File::scanDir(const string &sFilePath, vector &vtMatchFiles, FILE_SELECT f, int iMaxSize ) +{ + vtMatchFiles.clear(); + + struct dirent **namelist; + int n = scandir(sFilePath.c_str(), &namelist, f, alphasort); + + if (n < 0) + { + return 0; + } + else + { + while(n-- ) + { + if(iMaxSize > 0 && vtMatchFiles.size() >= (size_t)iMaxSize ) + { + free(namelist[n]); + break; + } + else + { + vtMatchFiles.push_back(namelist[n]->d_name); + free(namelist[n]); + } + } + free(namelist); + } + + return vtMatchFiles.size(); +} + +void TC_File::listDirectory(const string &path, vector &files, bool bRecursive) +{ + vector tf; + scanDir(path, tf, 0, 0); + + for(size_t i = 0; i < tf.size(); i++) + { + if(tf[i] == "." || tf[i] == "..") + continue; + + string s = path + "/" + tf[i]; + + if(isFileExist(s, S_IFDIR)) + { + files.push_back(simplifyDirectory(s)); + if(bRecursive) + { + listDirectory(s, files, bRecursive); + } + } + else + { + files.push_back(simplifyDirectory(s)); + } + } +} + +void TC_File::copyFile(const string &sExistFile, const string &sNewFile,bool bRemove) +{ + if(TC_File::isFileExist(sExistFile, S_IFDIR)) + { + TC_File::makeDir(sNewFile); + vector tf; + TC_File::scanDir(sExistFile,tf, 0, 0); + for(size_t i = 0; i v; + for(int i = 1; i < argc; i++) + { + v.push_back(argv[i]); + } + + for(size_t i = 0; i < v.size(); i++) + { + if(v[i].length() > 2 && v[i].substr(0,2) == "--") + { + parse(v[i]); + } + else + { + _vSingle.push_back(v[i]); + } + } +} + +void TC_Option::parse(const string &s) +{ + string::size_type pos = s.find('='); + if( pos != string::npos) + { + _mParam[s.substr(2, pos-2)] = s.substr(pos+1); + } + else + { + _mParam[s.substr(2, pos-2)] = ""; + } +} + +string TC_Option::getValue(const string &sName) +{ + if(_mParam.find(sName) != _mParam.end()) + { + return _mParam[sName]; + } + return ""; +} + +bool TC_Option::hasParam(const string &sName) +{ + return _mParam.find(sName) != _mParam.end(); +} + +vector& TC_Option::getSingle() +{ + return _vSingle; +} + +map& TC_Option::getMulti() +{ + return _mParam; +} + +} + +