├── .github └── workflows │ └── cmake.yml ├── .gitignore ├── .idea ├── .gitignore ├── .name ├── codeStyles │ └── codeStyleConfig.xml ├── dataSources.xml ├── encodings.xml ├── llvm-kaleidoscope.iml ├── misc.xml ├── modules.xml └── vcs.xml ├── CMakeLists.txt ├── ErrHelper.cpp ├── ErrHelper.h ├── Global.cpp ├── Global.h ├── README.md ├── args ├── all.hpp ├── api.hpp ├── arg.hpp ├── arg_iface.hpp ├── args_parser.cpp ├── args_parser.h ├── cmd_line.hpp ├── command.hpp ├── context.hpp ├── enums.hpp ├── exceptions.hpp ├── group_iface.hpp ├── groups.hpp ├── help.hpp ├── help_printer.hpp ├── help_printer_iface.hpp ├── multi_arg.hpp ├── types.hpp ├── utils.hpp └── value_utils.hpp ├── ast ├── NodeAST.cpp └── NodeAST.hpp ├── codegen ├── CodeGen.cpp └── CodeGen.h ├── compiler ├── Compiler.cpp └── Compiler.h ├── extern ├── ExternFunctionHandler.cpp ├── ExternFunctionHandler.h ├── ExternFunctionLinker.cpp └── ExternFunctionLinker.h ├── imgs └── ide.png ├── main.cpp ├── module ├── CMakeLists.txt ├── README.md ├── json │ ├── CMakeLists.txt │ └── src │ │ ├── kjson.cpp │ │ ├── kjson.h │ │ └── kjsondemo.cpp ├── sql │ ├── CMakeLists.txt │ └── src │ │ ├── ksql.cpp │ │ ├── ksql.h │ │ └── ksqldemo.cpp ├── string │ ├── CMakeLists.txt │ └── src │ │ ├── kstring.cpp │ │ └── kstring.h ├── time │ ├── CMakeLists.txt │ └── src │ │ └── time.c └── web │ ├── CMakeLists.txt │ ├── cert │ ├── ca.crt │ ├── ca.csr │ ├── ca.key │ ├── ca.pem │ ├── demoCA │ │ ├── index.txt │ │ ├── index.txt.attr │ │ ├── index.txt.old │ │ ├── newcerts │ │ │ └── 01.pem │ │ ├── serial │ │ └── serial.old │ ├── server.crt │ ├── server.csr │ ├── server.key │ └── server.pem │ └── src │ ├── serverdemo.cpp │ ├── web.cpp │ ├── web.hpp │ └── webdemo.cpp ├── parser ├── FileReader.cpp ├── FileReader.h ├── IFileReader.h ├── Lexer.cpp ├── Lexer.h ├── NetworkReader.cpp ├── NetworkReader.h ├── Parser.cpp ├── Parser.hpp ├── Parser.y ├── StringReader.cpp └── StringReader.h ├── pass ├── RecursiveToLoopPass.cpp ├── RecursiveToLoopPass.h ├── TimeAnalysisPass.cpp └── TimeAnalysisPass.h ├── stat.cpp ├── stat.h ├── test.kl ├── test ├── case │ └── webc_test │ │ ├── gcd.webc │ │ ├── helloserver.webc │ │ ├── qsort.webc │ │ ├── sleeptest.webc │ │ ├── sqltest.webc │ │ └── toStr.webc ├── server.crt ├── server.key ├── test.webc └── test1.cpp └── ui ├── css └── main.css ├── ui └── main.glade ├── widgets.cpp └── widgets.h /.github/workflows/cmake.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | on: [push] 4 | 5 | env: 6 | # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.) 7 | BUILD_TYPE: Release 8 | 9 | jobs: 10 | build: 11 | # The CMake configure and build commands are platform agnostic and should work equally 12 | # well on Windows or Mac. You can convert this to a matrix build if you need 13 | # cross-platform coverage. 14 | # See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix 15 | runs-on: ubuntu-20.04 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Installing LLVM 11 21 | run: sudo apt remove -y llvm* libclang* clang* && sudo apt install -y llvm-12-dev libclang-12-dev clang-12 22 | 23 | - name: Installing libedit 24 | run: sudo apt install -y libedit-dev 25 | 26 | - name: Installing libboost 27 | run: sudo apt install -y libboost-dev libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-thread-dev libboost-regex-dev 28 | 29 | - name: Installing libgtkmm-3 30 | run: sudo apt install -y libgtk-3-dev libgtkmm-3.0-dev libgtksourceviewmm-3.0-dev 31 | 32 | - name: Installing mysql-connector-c++ 33 | run: sudo apt install -y libmysqlcppconn-dev 34 | 35 | - name: Installing openssl 36 | run: sudo apt install -y openssl libssl-dev 37 | 38 | - name: Installing pkgconfig 39 | run: sudo apt install -y pkg-config 40 | 41 | - name: Installing ninja 42 | run: sudo apt install -y ninja-build 43 | 44 | - name: Create Build Environment 45 | # Some projects don't allow in-source building, so create a separate build directory 46 | # We'll use this as our working directory for all subsequent commands 47 | run: cmake -E make_directory ${{runner.workspace}}/build 48 | 49 | - name: Configure CMake 50 | # Use a bash shell so we can use the same syntax for environment variable 51 | # access regardless of the host operating system 52 | shell: bash 53 | working-directory: ${{runner.workspace}}/build 54 | # Note the current convention is to use the -S and -B options here to specify source 55 | # and build directories, but this is only available with CMake 3.13 and higher. 56 | # The CMake binaries on the Github Actions machines are (as of this writing) 3.12 57 | run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=${{ env.BUILD_TYPE }} -G "Ninja" 58 | 59 | - name: Build 60 | working-directory: ${{runner.workspace}}/build 61 | shell: bash 62 | # Execute the build. You can specify a specific target with "--target " 63 | run: cmake --build . 64 | 65 | - name: Create Release 66 | id: create_release 67 | if: startsWith(github.ref, 'refs/tags/') 68 | uses: ncipollo/release-action@v1 69 | with: 70 | artifacts: "${{runner.workspace}}/build/webc_compiler,${{runner.workspace}}/build/module/json/libkjson.a,${{runner.workspace}}/build/module/sql/libksql.a,${{runner.workspace}}/build/module/string/libkstring.a,${{runner.workspace}}/build/module/time/libktime.a,${{runner.workspace}}/build/module/web/libkweb.a" 71 | body: ${{ github.ref }} 72 | token: ${{ secrets.GITHUB_TOKEN }} 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project exclude paths 2 | /cmake-build-debug/ 3 | /build/ 4 | /CMakeFiles/ 5 | CMakeCache.txt 6 | *.log 7 | *.cbp 8 | *.output 9 | .vscode/** 10 | Makefile 11 | module/lib/** 12 | module/CMakeFiles/** 13 | module/time/CMakeFiles/** -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | webc_compiler -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mysql.8 6 | true 7 | com.mysql.cj.jdbc.Driver 8 | jdbc:mysql://localhost:3306 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/llvm-kaleidoscope.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(webc_compiler) 3 | if(WIN32) 4 | set(CMAKE_CXX_STANDARD 14) 5 | else() 6 | set(CMAKE_CXX_STANDARD 17) 7 | endif() 8 | 9 | # 始终选择最高版本依赖 10 | SET(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL) 11 | SET(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC) 12 | 13 | find_package(LLVM REQUIRED CONFIG) 14 | include_directories(${LLVM_INCLUDE_DIRS}) 15 | add_definitions(${LLVM_DEFINITIONS}) 16 | message(STATUS "Found llvm in ${LLVM_INCLUDE_DIRS}") 17 | 18 | find_package(Clang REQUIRED CONFIG) 19 | include_directories(${CLANG_INCLUDE_DIRS}) 20 | add_definitions(${ClANG_DEFINITIONS}) 21 | message(STATUS "clang: ${CLANG_INCLUDE_DIRS}") 22 | 23 | #find_package(LLD REQUIRED CONFIG) 24 | #message(STATUS "find lld ${LLD_INCLUDE_DIRS}") 25 | #include_directories(${LLD_INCLUDE_DIRS}) 26 | #add_definitions(${LLD_DEFINITIONS}) 27 | 28 | message(STATUS "查找Boost框架") 29 | find_package(Boost COMPONENTS system filesystem thread chrono regex REQUIRED) 30 | include_directories(${Boost_INCLUDE_DIR}) 31 | link_directories(${Boost_LIBRARY_DIR}) 32 | 33 | find_package(PkgConfig REQUIRED) 34 | pkg_check_modules(GTK3 REQUIRED gtk+-3.0) 35 | include_directories(${GTK3_INCLUDE_DIRS}) 36 | link_directories(${GTK3_LIBRARY_DIRS}) 37 | add_definitions(${GTK3_CFLAGS_OTHER}) 38 | # 处理语法分析器 39 | #find_package(BISON) 40 | #BISON_TARGET(Parser parser/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser/Parser.cpp 41 | # DEFINES_FILE ${CMAKE_CURRENT_BINARY_DIR}/parser/Parser.h) 42 | 43 | # C++静态链接 44 | #set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") 45 | 46 | message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") 47 | message(STATUS "GTK3_INCLUDE_DIRS: ${GTK3_INCLUDE_DIRS}") 48 | message(STATUS "GKT3_LIBRARIES: ${GTK3_LIBRARIES}") 49 | message(STATUS "GTK3_LINK_LIBRARIES: ${GTK3_LINK_LIBRARIES}") 50 | message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") 51 | message(STATUS "Using defs in: ${LLVM_DEFINITIONS}") 52 | message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}") 53 | 54 | # import LLVM 55 | include_directories(${LLVM_INCLUDE_DIRS}) 56 | add_definitions(${LLVM_DEFINITIONS}) 57 | 58 | # import gtk 59 | #include_directories(${GTK3_INCLUDE_DIRS}) 60 | #link_directories(${GTK3_LIBRARY_DIRS}) 61 | 62 | 63 | # import gtkmm, for linux use 3.0, for macos use 4.0 for test 64 | FIND_PACKAGE(PkgConfig REQUIRED) 65 | pkg_check_modules(GTKMM gtkmm-3.0 gtksourceviewmm-3.0) 66 | link_directories(${GTKMM_LIBRARY_DIRS}) 67 | include_directories(${GTKMM_INCLUDE_DIRS}) 68 | message(STATUS "GTKMM Lib ${GTKMM_LIBRARY_DIRS}") 69 | message(STATUS "GTKMM Inc ${GTKMM_INCLUDE_DIRS}") 70 | aux_source_directory(ui UI) 71 | message(STATUS "窗口实现:${UI}") 72 | 73 | # 导入头文件 74 | include_directories( 75 | . 76 | parser 77 | codegen 78 | args 79 | ) 80 | 81 | aux_source_directory(. ROOT) 82 | message(STATUS "根目录含有:${ROOT}") 83 | aux_source_directory(parser PARSER) 84 | message(STATUS "解释器文件含有:${PARSER}") 85 | aux_source_directory(ast AST) 86 | message(STATUS "语法树定义:${AST}") 87 | aux_source_directory(codegen CodeGen) 88 | message(STATUS "代码生成:${CodeGen}") 89 | aux_source_directory(args ARGS) 90 | message(STATUS "Console Parser:${ARGS}") 91 | aux_source_directory(pass PASS) 92 | message(STATUS "外部声明:${EXT}") 93 | aux_source_directory(extern EXT) 94 | message(STATUS "Pass:${PASS}") 95 | message(STATUS "编译器:${COMPILER}") 96 | aux_source_directory(compiler COMPILER) 97 | message(STATUS "Pass:${COMPILER}") 98 | 99 | add_executable(webc_compiler 100 | ${ROOT} ${AST} ${PARSER} 101 | # ${BISON_Parser_OUTPUTS} 102 | ${CodeGen} ${UI} ${ARGS} ${PASS} ${EXT} ${COMPILER} 103 | args/all.hpp args/api.hpp args/arg.hpp args/arg_iface.hpp 104 | args/cmd_line.hpp args/command.hpp args/context.hpp args/enums.hpp 105 | args/exceptions.hpp args/group_iface.hpp args/groups.hpp args/help_printer.hpp 106 | args/help_printer.hpp args/help_printer_iface.hpp args/multi_arg.hpp args/types.hpp 107 | args/utils.hpp args/value_utils.hpp 108 | ) 109 | # 平台公用宏定义 110 | add_compile_definitions(webc_compiler PUBLIC ASM_SUFFIX=".s") 111 | # CGUI存在则生成可视化界面 DEBUG_FLAG开启调试模式 CLANG_SUPPORT开启可执行文件输出 112 | add_compile_definitions(webc_compiler PUBLIC CLANG_SUPPORT=1) 113 | 114 | if (WIN32) 115 | add_compile_definitions(webc_compiler PUBLIC EXECUTABLE_SUFFIX=".exe" OBJ_SUFFIX=".obj") 116 | else () 117 | add_compile_definitions(webc_compiler PUBLIC EXECUTABLE_SUFFIX=".out" OBJ_SUFFIX=".o") 118 | endif () 119 | 120 | message(STATUS "host system is ${CMAKE_HOST_SYSTEM_PROCESSOR}") 121 | 122 | if (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "aarch64") 123 | add_compile_definitions(webc_compiler PUBLIC SYSY_AARCH64=0) 124 | llvm_map_components_to_libnames(llvm_libs support core irreader 125 | aarch64info aarch64asmparser aarch64desc aarch64codegen aarch64disassembler #X86 126 | ) 127 | elseif (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "arm") 128 | add_compile_definitions(webc_compiler PUBLIC SYSY_ARM=0) 129 | llvm_map_components_to_libnames(llvm_libs support core irreader 130 | arminfo armasmparser armdesc armcodegen armdisassembler #X86 131 | ) 132 | else () 133 | add_compile_definitions(webc_compiler PUBLIC SYSY_X86=0) 134 | llvm_map_components_to_libnames(llvm_libs support core irreader 135 | x86info x86asmparser x86desc x86codegen x86disassembler #X86 136 | ) 137 | endif () 138 | 139 | message(STATUS "Found ${llvm_libs}") 140 | 141 | find_package(PkgConfig REQUIRED) 142 | pkg_check_modules(SSLLib openssl) 143 | message(STATUS "found ssl lib in ${SSLLib_INCLUDE_DIRS}") 144 | message(STATUS "found ssl lib in ${SSLLib_LIBRARY_DIRS}") 145 | include_directories(${SSLLib_INCLUDE_DIRS}) 146 | link_directories(${SSLLib_LIBRARY_DIRS}) 147 | 148 | # Link against LLVM libraries 149 | #target_link_libraries(webc_compiler ${llvm_libs}) 150 | if (WIN32) 151 | target_link_libraries(webc_compiler 152 | LLVM 153 | ${GTKMM_LIBRARIES} 154 | ${SSLLib_LIBRARIES} 155 | Boost::thread Boost::chrono Boost::regex 156 | clangDriver 157 | wsock32 158 | ) 159 | else() 160 | target_link_libraries(webc_compiler 161 | LLVM 162 | ${GTKMM_LIBRARIES} 163 | ${SSLLib_LIBRARIES} 164 | Boost::thread Boost::chrono Boost::regex 165 | clangDriver 166 | ) 167 | endif() 168 | 169 | install(TARGETS webc_compiler) 170 | 171 | #message(STATUS "UI逻辑:复制UI:${CMAKE_SOURCE_DIR}/ui/ui -> ${CMAKE_CURRENT_BINARY_DIR}/ui") 172 | #add_custom_command(TARGET webc_compiler PRE_BUILD 173 | # COMMAND ${CMAKE_COMMAND} -E copy_directory 174 | # ${CMAKE_SOURCE_DIR}/ui/ui ${CMAKE_CURRENT_BINARY_DIR}/ui) 175 | 176 | message(STATUS "配置目标库") 177 | #add_subdirectory(module) 178 | 179 | # time module 180 | #aux_source_directory(module/time/src TIME_MODULE) 181 | #message(STATUS "${TIME_MODULE}") 182 | #add_library(time "${TIME_MODULE}") 183 | add_subdirectory(module) 184 | 185 | # Web 186 | #aux_source_directory(module/web/src WEB_MODULE) 187 | #message(STATUS "${WEB_MODULE}") 188 | #add_library(web "${WEB_MODULE}") 189 | 190 | # test.cpp 191 | #add_executable(test test/test1.c) -------------------------------------------------------------------------------- /ErrHelper.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/22. 3 | // 4 | 5 | #include "ErrHelper.h" 6 | 7 | // CGUI 8 | #ifdef CGUI 9 | 10 | extern void logOnUi(const char *Str); 11 | 12 | #endif 13 | 14 | std::unique_ptr LogError(const char *Str) { 15 | fprintf(stderr, "Error: %s\n", Str); 16 | #ifdef CGUI 17 | logOnUi(Str); 18 | #endif 19 | return nullptr; 20 | } 21 | 22 | std::unique_ptr LogInfo(const char *Str) { 23 | fprintf(stdout, "Info: %s\n", Str); 24 | #ifdef CGUI 25 | logOnUi(Str); 26 | #endif 27 | return nullptr; 28 | } 29 | 30 | std::unique_ptr LogErrorP(const char *Str) { 31 | LogError(Str); 32 | return nullptr; 33 | } 34 | 35 | llvm::Value *LogErrorV(const char *Str) { 36 | LogError(Str); 37 | return nullptr; 38 | } 39 | 40 | llvm::Value *LogWarn(const char *Str) { 41 | LogError(Str); 42 | return nullptr; 43 | } 44 | 45 | llvm::Type *LogErrorTy(const char *Str) { 46 | LogError(Str); 47 | return nullptr; 48 | } 49 | -------------------------------------------------------------------------------- /ErrHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/22. 3 | // 4 | 5 | #ifndef LLVM_KALEIDOSCOPE_ERRHELPER_H 6 | #define LLVM_KALEIDOSCOPE_ERRHELPER_H 7 | 8 | #include 9 | #include "ast/NodeAST.hpp" 10 | #include "Global.h" 11 | 12 | std::unique_ptr LogInfo(const char *Str); 13 | 14 | /// LogError* - These are little helper functions for error handling. 15 | std::unique_ptr LogError(const char *Str); 16 | 17 | std::unique_ptr LogErrorP(const char *Str); 18 | 19 | llvm::Value *LogErrorV(const char *Str); 20 | 21 | llvm::Value *LogWarn(const char *Str); 22 | 23 | llvm::Type *LogErrorTy(const char *Str); 24 | 25 | #endif //LLVM_KALEIDOSCOPE_ERRHELPER_H 26 | -------------------------------------------------------------------------------- /Global.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/22. 3 | // 4 | 5 | #include "codegen/CodeGen.h" 6 | 7 | /// 全局变量 8 | // TheContext 是一个不透明的对象,拥有许多核心LLVM数据结构,例如类型和常量值表。 9 | std::unique_ptr TheContext = std::make_unique(); 10 | /// 该Builder对象是一个辅助对象,可以轻松生成LLVM指令。IRBuilder 类模板的实例 跟踪插入指令的当前位置,并具有创建新指令的方法。 11 | std::unique_ptr> Builder = std::make_unique>(*TheContext); 12 | /// TheModule是一个包含函数和全局变量的LLVM构造。在许多方面,它是LLVM IR用于包含代码的顶级结构。它将拥有我们生成的所有IR的内存,这就是codegen()方法返回原始值*而不是unique_ptr 的原因。 13 | std::unique_ptr TheModule = std::make_unique("Kingtous JIT", *TheContext); 14 | /// 代码生成上下文 15 | std::unique_ptr TheCodeGenContext = std::make_unique(); -------------------------------------------------------------------------------- /Global.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/21. 3 | // 4 | 5 | #ifndef LLVM_KALEIDOSCOPE_GLOBAL_H 6 | #define LLVM_KALEIDOSCOPE_GLOBAL_H 7 | 8 | #include "llvm/ADT/ArrayRef.h" 9 | #include "llvm/ADT/APFloat.h" 10 | #include "llvm/ADT/Optional.h" 11 | #include "llvm/ADT/STLExtras.h" 12 | #include "llvm/IR/BasicBlock.h" 13 | #include "llvm/IR/Constants.h" 14 | #include "llvm/IR/DerivedTypes.h" 15 | #include "llvm/IR/Function.h" 16 | #include "llvm/IR/IRBuilder.h" 17 | #include "llvm/IR/LLVMContext.h" 18 | #include "llvm/IR/LegacyPassManager.h" 19 | #include "llvm/IR/Module.h" 20 | #include "llvm/IR/Type.h" 21 | #include "llvm/IR/Verifier.h" 22 | #include "llvm/Support/TargetSelect.h" 23 | #include "llvm/Support/FileSystem.h" 24 | #include "llvm/Support/Host.h" 25 | #include "llvm/Support/raw_ostream.h" 26 | #include "llvm/Support/TargetRegistry.h" 27 | #include "llvm/Target/TargetMachine.h" 28 | #include "llvm/Transforms/Scalar.h" 29 | #include "llvm/Transforms/Scalar/GVN.h" 30 | #include "llvm/Target/TargetMachine.h" 31 | #include "llvm/Target/TargetOptions.h" 32 | #include 33 | 34 | /// 状态字 35 | #define ROK 0 36 | #define RERR -1 37 | #define RINVALID -2 38 | 39 | /// 初始化数字 40 | #define INIT_NUM -1 41 | #define INIT_IOBUF 4096 42 | 43 | /// 特性前缀 44 | #define LabelPrefix "__neuq_kingtous_" 45 | #define FuncPrefix "__sysyplus_" 46 | #define APPNAME "cn.kingtous.sysycompiler" 47 | /// 全局变量 48 | #define HASLOCALS (TheCodeGenContext->get_current_locals() != nullptr) 49 | #define LOCALS TheCodeGenContext->get_current_locals() 50 | #define LOCALSVARS TheCodeGenContext->get_current_locals()->localVars 51 | #define INSERTLOCAL(identifier, llvmValue) TheCodeGenContext->get_current_locals()->localVars.insert(std::make_pair(identifier,llvmValue)) 52 | #define FINDLOCAL(x) TheCodeGenContext->findValue(x) 53 | #define ABORT_COMPILE TheCodeGenContext->setIsAborted(true) 54 | #define IS_COMPILE_ABORTED TheCodeGenContext->isAborted() 55 | #define NIL nullptr 56 | #define END_OF_FILE -1 57 | 58 | extern void yyerror(const char *s); 59 | 60 | /// 全局变量 61 | /// TheContext 是一个不透明的对象,拥有许多核心LLVM数据结构,例如类型和常量值表。 62 | extern std::unique_ptr TheContext; 63 | /// 该Builder对象是一个辅助对象,可以轻松生成LLVM指令。IRBuilder 类模板的实例 跟踪插入指令的当前位置,并具有创建新指令的方法。 64 | extern std::unique_ptr> Builder; 65 | /// TheModule是一个包含函数和全局变量的LLVM构造。在许多方面,它是LLVM IR用于包含代码的顶级结构。它将拥有我们生成的所有IR的内存,这就是codegen()方法返回原始值*而不是unique_ptr 的原因。 66 | extern std::unique_ptr TheModule; 67 | 68 | class CodeGenContext; 69 | 70 | /// 代码生成上下文 71 | extern std::unique_ptr TheCodeGenContext; 72 | 73 | namespace network { 74 | extern boost::regex url_regex; 75 | } 76 | #endif //LLVM_KALEIDOSCOPE_GLOBAL_H 77 | -------------------------------------------------------------------------------- /args/all.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__ALL_HPP__INCLUDED 32 | #define ARGS__ALL_HPP__INCLUDED 33 | 34 | #include "cmd_line.hpp" 35 | #include "types.hpp" 36 | 37 | #endif // ARGS__ALL_HPP__INCLUDED 38 | -------------------------------------------------------------------------------- /args/arg_iface.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__ARG_IFACE_HPP__INCLUDED 32 | #define ARGS__ARG_IFACE_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "utils.hpp" 36 | #include "types.hpp" 37 | #include "enums.hpp" 38 | 39 | 40 | namespace Args { 41 | 42 | class Context; 43 | class CmdLine; 44 | 45 | 46 | // 47 | // ArgIface 48 | // 49 | 50 | //! Interface for arguments. 51 | class ArgIface { 52 | 53 | friend class CmdLine; 54 | friend class GroupIface; 55 | friend class Command; 56 | 57 | public: 58 | ArgIface() 59 | : m_cmdLine( nullptr ) 60 | { 61 | } 62 | 63 | virtual ~ArgIface() 64 | { 65 | } 66 | 67 | //! \return Type of the argument. 68 | virtual ArgType type() const = 0; 69 | 70 | /*! 71 | \return Name of the argument. 72 | 73 | If name is empty returned value should be a flag. 74 | I.e. for example "-t" or "--timeout" 75 | */ 76 | virtual String name() const = 0; 77 | 78 | //! \return Is this argument with value? 79 | virtual bool isWithValue() const = 0; 80 | 81 | //! \return Is this argument required? 82 | virtual bool isRequired() const = 0; 83 | 84 | //! \return Is this argument defined? 85 | virtual bool isDefined() const = 0; 86 | 87 | //! \return Flag. 88 | virtual const String & flag() const = 0; 89 | 90 | //! \return Argument name. 91 | virtual const String & argumentName() const = 0; 92 | 93 | //! \return Value specifier. 94 | virtual const String & valueSpecifier() const = 0; 95 | 96 | //! \return Description of the argument. 97 | virtual const String & description() const = 0; 98 | 99 | //! \return Long description of the argument. 100 | virtual const String & longDescription() const = 0; 101 | 102 | //! \return Command line parser. 103 | CmdLine * cmdLine() const 104 | { 105 | return m_cmdLine; 106 | } 107 | 108 | //! \return Is given name a misspelled name of the argument. 109 | virtual bool isMisspelledName( 110 | //! Name to check (misspelled). 111 | const String & name, 112 | //! List of possible names for the given misspelled name. 113 | StringList & possibleNames ) const = 0; 114 | 115 | //! Clear state of the argument. 116 | virtual void clear() = 0; 117 | 118 | protected: 119 | /*! 120 | \return Argument for the given name. 121 | 122 | \retval Pointer to the ArgIface if this argument handles 123 | argument with the given name. 124 | \retval nullptr if this argument doesn't know about 125 | argument with name. 126 | */ 127 | virtual ArgIface * findArgument( 128 | /*! 129 | Name of the argument. Can be for example "-t" or 130 | "--timeout". 131 | */ 132 | const String & name ) = 0; 133 | 134 | /*! 135 | Process argument's staff, for example take values from 136 | context. This method invokes exactly at that moment when 137 | parser has found this argument. 138 | */ 139 | virtual void process( 140 | //! Context of the command line. 141 | Context & context ) = 0; 142 | 143 | /*! 144 | Check correctness of the argument before parsing. 145 | 146 | Implementation of this method must add his flag 147 | and name to the flags and names. 148 | */ 149 | virtual void checkCorrectnessBeforeParsing( 150 | //! All known flags. 151 | StringList & flags, 152 | //! All known names. 153 | StringList & names ) const = 0; 154 | 155 | //! Check correctness of the argument after parsing. 156 | virtual void checkCorrectnessAfterParsing() const = 0; 157 | 158 | //! Set command line parser. 159 | virtual void setCmdLine( CmdLine * cmdLine ) 160 | { 161 | m_cmdLine = cmdLine; 162 | } 163 | 164 | private: 165 | DISABLE_COPY( ArgIface ) 166 | 167 | //! Command line parser. 168 | CmdLine * m_cmdLine; 169 | }; // class ArgIface 170 | 171 | } /* namespace Args */ 172 | 173 | #endif // ARGS__ARG_IFACE_HPP__INCLUDED 174 | -------------------------------------------------------------------------------- /args/args_parser.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/2/23. 3 | // 4 | 5 | #include "args_parser.h" 6 | #include 7 | 8 | using namespace Args; 9 | 10 | CmdLine *cmd; 11 | MultiArg *input_arg; 12 | Arg *output_arg; 13 | Arg *is_target_arg; 14 | Arg *is_obj_arg; 15 | Arg *time_analysis_arg; 16 | Help *help_arg; 17 | 18 | ArgsParser::ArgsParser() { 19 | 20 | } 21 | 22 | ArgsParser *ArgsParser::inst(int args, char **argv) { 23 | auto ap = new ArgsParser(); 24 | if (ap->verify(args, argv)) { 25 | for (const auto &v : input_arg->values()) { 26 | ap->files.push_back(v); 27 | } 28 | ap->output_path = output_arg->value(); 29 | if (is_target_arg->isDefined()) { 30 | ap->opts.insert(Options::OUTPUT_LLVMAS_FILE); 31 | } else if (is_obj_arg->isDefined()) { 32 | ap->opts.insert(Options::OUTPUT_OBJ_FILE); 33 | } else { 34 | ap->opts.insert(Options::OUTPUT_EXECUTABLE); 35 | } 36 | // 是否加入时间分析 37 | if (time_analysis_arg->isDefined()){ 38 | ap->opts.insert(Options::PASS_TIME_ANALYSIS); 39 | } 40 | return ap; 41 | } else { 42 | return nullptr; 43 | } 44 | } 45 | 46 | bool ArgsParser::verify(int args, char **argv) { 47 | cmd = new CmdLine(args, argv); 48 | // 49 | input_arg = new MultiArg('i',"input",true,true); 50 | input_arg->setDescription(String("输入源文件")); 51 | input_arg->setLongDescription(String("输入源文件(支持多文件)")); 52 | cmd->addArg(input_arg); 53 | 54 | output_arg = new Arg('o', "output", true, true); 55 | input_arg->setDescription(String("输出文件")); 56 | input_arg->setLongDescription(String("输出文件")); 57 | cmd->addArg(output_arg); 58 | 59 | is_target_arg = new Arg('s', "as", false, false); 60 | is_target_arg->setDescription("是否生成可读汇编文件"); 61 | is_target_arg->setLongDescription("source code -> llvm ir -> assembly file(可视化)"); 62 | cmd->addArg(is_target_arg); 63 | 64 | is_obj_arg = new Arg('j', "object", false, false); 65 | is_obj_arg->setDescription("是否只生成目标文件"); 66 | is_obj_arg->setLongDescription("source code -> llvm ir -> assembly file(可视化) -> object file"); 67 | cmd->addArg(is_obj_arg); 68 | 69 | time_analysis_arg = new Arg('t', "time_analysis", false, false); 70 | time_analysis_arg->setDescription("是否在每个函数内加入时间分析"); 71 | time_analysis_arg->setLongDescription("add time analysis into every function"); 72 | cmd->addArg(time_analysis_arg); 73 | 74 | help_arg = new Help(); 75 | help_arg->setExecutable(argv[0]); 76 | help_arg->setAppDescription("WebC Compiler By Kingtous."); 77 | cmd->addArg(help_arg); 78 | try { 79 | cmd->parse(); 80 | auto re = cmd != nullptr && 81 | input_arg->isDefined() && output_arg->isDefined(); 82 | if (!re) { 83 | fprintf(stderr, "输入输出未定义"); 84 | return false; 85 | } else { 86 | return true; 87 | } 88 | } catch (const HelpHasBeenPrintedException &) { 89 | return false; 90 | } 91 | catch (const BaseException &x) { 92 | outStream() << x.desc() << "\n使用-h/--help查看帮助\n"; 93 | return false; 94 | } 95 | } 96 | 97 | const vector &ArgsParser::getFiles() const { 98 | return files; 99 | } 100 | 101 | const set &ArgsParser::getOpts() const { 102 | return opts; 103 | } 104 | 105 | const string &ArgsParser::getOutputPath() const { 106 | return output_path; 107 | } 108 | -------------------------------------------------------------------------------- /args/args_parser.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/2/23. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_ARGSPARSER_H 6 | #define SYSYPLUS_COMPILER_ARGSPARSER_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | class ArgsParser { 17 | public: 18 | enum Options { 19 | OUTPUT_LLVMAS_FILE, 20 | OUTPUT_EXECUTABLE, 21 | OUTPUT_OBJ_FILE, 22 | PASS_TIME_ANALYSIS 23 | }; 24 | 25 | static ArgsParser* inst(int args,char** argv); 26 | 27 | const vector &getFiles() const; 28 | 29 | const set &getOpts() const; 30 | 31 | const string &getOutputPath() const; 32 | 33 | private: 34 | ArgsParser(); 35 | bool verify(int i, char **pString); 36 | std::vector files; 37 | std::set opts; 38 | std::string output_path; 39 | }; 40 | 41 | 42 | #endif //SYSYPLUS_COMPILER_ARGSPARSER_H 43 | -------------------------------------------------------------------------------- /args/context.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__CONTEXT_HPP__INCLUDED 32 | #define ARGS__CONTEXT_HPP__INCLUDED 33 | 34 | // C++ include. 35 | #include 36 | 37 | // Args include. 38 | #include "utils.hpp" 39 | #include "types.hpp" 40 | 41 | 42 | namespace Args { 43 | 44 | // 45 | // ContextInternal 46 | // 47 | 48 | //! What Context actually is. 49 | typedef StringList ContextInternal; 50 | 51 | 52 | // 53 | // Context 54 | // 55 | 56 | /*! 57 | Context is a list of words in the command line that user 58 | presented with interface for interacting with them. 59 | */ 60 | class Context final { 61 | public: 62 | Context() 63 | : m_it( m_context.begin() ) 64 | { 65 | } 66 | 67 | explicit Context( ContextInternal items ); 68 | 69 | Context & operator = ( ContextInternal && items ) 70 | { 71 | m_context = std::move( items ); 72 | 73 | m_it = m_context.begin(); 74 | 75 | return *this; 76 | } 77 | 78 | //! \return Iterator to the first item in the context. 79 | ContextInternal::iterator begin(); 80 | 81 | //! \return Iterator to the last item in the context. 82 | ContextInternal::iterator end(); 83 | 84 | //! \return Is context at end? 85 | bool atEnd(); 86 | 87 | //! \return Iterator to the next item in the context. 88 | ContextInternal::iterator next(); 89 | 90 | //! Put back last taken item. 91 | void putBack(); 92 | 93 | //! Prepend context with new item. 94 | void prepend( const String & what ); 95 | 96 | private: 97 | DISABLE_COPY( Context ) 98 | 99 | //! Internal representation of the context. 100 | ContextInternal m_context; 101 | //! Iterator to the current item in the context. 102 | ContextInternal::iterator m_it; 103 | }; // class Context 104 | 105 | 106 | // 107 | // Context 108 | // 109 | 110 | inline 111 | Context::Context( ContextInternal items ) 112 | : m_context( std::move( items ) ) 113 | , m_it( m_context.begin() ) 114 | { 115 | } 116 | 117 | inline ContextInternal::iterator 118 | Context::begin() 119 | { 120 | return m_it; 121 | } 122 | 123 | inline ContextInternal::iterator 124 | Context::end() 125 | { 126 | return m_context.end(); 127 | } 128 | 129 | inline bool 130 | Context::atEnd() 131 | { 132 | return ( begin() == end() ); 133 | } 134 | 135 | inline ContextInternal::iterator 136 | Context::next() 137 | { 138 | if( atEnd() ) 139 | return end(); 140 | else 141 | return m_it++; 142 | } 143 | 144 | inline void 145 | Context::putBack() 146 | { 147 | if( begin() == m_context.begin() ) 148 | return; 149 | else 150 | --m_it; 151 | } 152 | 153 | inline void 154 | Context::prepend( const String & what ) 155 | { 156 | m_it = m_context.insert( m_it, what ); 157 | } 158 | 159 | } /* namespace Args */ 160 | 161 | #endif // ARGS__CONTEXT_HPP__INCLUDED 162 | -------------------------------------------------------------------------------- /args/enums.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__ENUMS_HPP__INCLUDED 32 | #define ARGS__ENUMS_HPP__INCLUDED 33 | 34 | namespace Args { 35 | 36 | // 37 | // ValueOptions 38 | // 39 | 40 | //! Options for value property. 41 | enum class ValueOptions { 42 | //! No values. 43 | NoValue = 0, 44 | //! One value. 45 | OneValue = 1, 46 | //! Many values. 47 | ManyValues = 2 48 | }; // enum class ValueOptions 49 | 50 | 51 | // 52 | // ArgType 53 | // 54 | 55 | //! Type of the argument. 56 | enum class ArgType { 57 | //! Command. 58 | Command, 59 | //! Argument. 60 | Arg, 61 | //! Multi argument 62 | MultiArg, 63 | //! "Only one" group. 64 | OnlyOneGroup, 65 | //! "All of" group. 66 | AllOfGroup, 67 | //! "At least one" group. 68 | AtLeastOneGroup 69 | }; // enum class ArgType 70 | 71 | } /* namespace Args */ 72 | 73 | #endif // ARGS__ENUMS_HPP__INCLUDED 74 | -------------------------------------------------------------------------------- /args/exceptions.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__EXCEPTIONS_HPP__INCLUDED 32 | #define ARGS__EXCEPTIONS_HPP__INCLUDED 33 | 34 | // C++ include. 35 | #include 36 | 37 | // Args include. 38 | #include "types.hpp" 39 | 40 | 41 | namespace Args { 42 | 43 | // 44 | // BaseException 45 | // 46 | 47 | //! Base exception of the library. 48 | class BaseException 49 | : public std::logic_error 50 | { 51 | public: 52 | explicit BaseException( String what ) 53 | : std::logic_error( "Please use desc() method of the exception." ) 54 | , m_what( std::move( what ) ) 55 | { 56 | } 57 | 58 | virtual ~BaseException() noexcept 59 | { 60 | } 61 | 62 | //! \return What as std::wstring. 63 | const String & desc() const noexcept 64 | { 65 | return m_what; 66 | } 67 | 68 | private: 69 | //! What happened? 70 | String m_what; 71 | }; // class BaseException 72 | 73 | 74 | // 75 | // HelpHasBeenPrintedException 76 | // 77 | 78 | //! This exception notifies about that help has been printed. 79 | class HelpHasBeenPrintedException final 80 | : public BaseException 81 | { 82 | public: 83 | HelpHasBeenPrintedException() 84 | : BaseException( SL( "Help has been printed." ) ) 85 | { 86 | } 87 | }; // class HelpHasBeenPrintedException 88 | 89 | } /* namespace Args */ 90 | 91 | #endif // ARGS__EXCEPTIONS_HPP__INCLUDED 92 | -------------------------------------------------------------------------------- /args/group_iface.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__GROUP_IFACE_HPP__INCLUDED 32 | #define ARGS__GROUP_IFACE_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "arg_iface.hpp" 36 | #include "utils.hpp" 37 | #include "exceptions.hpp" 38 | #include "types.hpp" 39 | 40 | // C++ include. 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | 48 | namespace Args { 49 | 50 | class Command; 51 | 52 | 53 | // 54 | // GroupIface 55 | // 56 | 57 | //! Interface for the groups. 58 | class GroupIface 59 | : public ArgIface 60 | { 61 | public: 62 | //! Dummy empty string. 63 | static const String m_dummyEmptyString; 64 | 65 | public: 66 | //! Smart pointer to the argument. 67 | using ArgPtr = std::unique_ptr< ArgIface, details::Deleter< ArgIface > >; 68 | //! List of child arguments. 69 | using Arguments = std::vector< ArgPtr >; 70 | 71 | template< typename T > 72 | explicit GroupIface( T && name, 73 | bool required = false ) 74 | : m_name( std::forward< T > ( name ) ) 75 | , m_required( required ) 76 | { 77 | } 78 | 79 | virtual ~GroupIface() 80 | { 81 | } 82 | 83 | //! \return List of children. 84 | const Arguments & children() const 85 | { 86 | return m_children; 87 | } 88 | 89 | //! Add argument. \note Developer should handle lifetime of the argument. 90 | template< typename T > 91 | typename std::enable_if< std::is_base_of< ArgIface, T >::value && 92 | !std::is_base_of< Command, T >::value >::type 93 | addArg( T & arg ) 94 | { 95 | addArg( ArgPtr( &arg, details::Deleter< ArgIface > ( false ) ) ); 96 | } 97 | 98 | //! Add argument. \note Developer should handle lifetime of the argument. 99 | template< typename T > 100 | typename std::enable_if< std::is_base_of< ArgIface, T >::value && 101 | !std::is_base_of< Command, T >::value >::type 102 | addArg( T * arg ) 103 | { 104 | addArg( ArgPtr( arg, details::Deleter< ArgIface > ( false ) ) ); 105 | } 106 | 107 | //! Add argument. 108 | void addArg( ArgPtr arg ) 109 | { 110 | if( arg->type() == ArgType::Command ) 111 | throw BaseException( String( SL( "Commands not allowed in groups. " 112 | "You are trying to add command \"" ) ) + arg->name() + 113 | SL( "\" to group \"" ) + name() + SL( "\"." ) ); 114 | 115 | if( std::find( m_children.cbegin(), m_children.cend(), arg ) == 116 | m_children.cend() ) 117 | { 118 | if( cmdLine() ) 119 | arg->setCmdLine( cmdLine() ); 120 | 121 | m_children.push_back( std::move( arg ) ); 122 | } 123 | } 124 | 125 | /*! 126 | \return Name of the argument. 127 | 128 | If name is empty returned value should be a flag. 129 | I.e. for example "-t" or "--timeout" 130 | */ 131 | String name() const override 132 | { 133 | return m_name; 134 | } 135 | 136 | //! \return Is this argument with value? 137 | bool isWithValue() const override 138 | { 139 | return false; 140 | } 141 | 142 | //! \return Is this argument required? 143 | bool isRequired() const override 144 | { 145 | return m_required; 146 | } 147 | 148 | //! Set required flag. 149 | virtual void setRequired( bool on = true ) 150 | { 151 | m_required = on; 152 | } 153 | 154 | //! \return Flag. 155 | const String & flag() const override 156 | { 157 | return m_dummyEmptyString; 158 | } 159 | 160 | //! \return Argument name. 161 | const String & argumentName() const override 162 | { 163 | return m_dummyEmptyString; 164 | } 165 | 166 | //! \return Value specifier. 167 | const String & valueSpecifier() const override 168 | { 169 | return m_dummyEmptyString; 170 | } 171 | 172 | //! \return Description of the argument. 173 | const String & description() const override 174 | { 175 | return m_dummyEmptyString; 176 | } 177 | 178 | //! \return Long description of the argument. 179 | const String & longDescription() const override 180 | { 181 | return m_dummyEmptyString; 182 | } 183 | 184 | //! Clear state of the argument. 185 | void clear() override 186 | { 187 | std::for_each( children().begin(), children().end(), 188 | [ & ] ( const auto & ch ) { ch->clear(); } ); 189 | } 190 | 191 | protected: 192 | /*! 193 | \return Argument for the given name. 194 | 195 | \retval Pointer to the ArgIface if this argument handles 196 | argument with the given name. 197 | \retval nullptr if this argument doesn't know about 198 | argument with name. 199 | 200 | \note Looks only in children. 201 | */ 202 | ArgIface * findArgument( 203 | /*! 204 | Name of the argument. Can be for example "-t" or 205 | "--timeout". 206 | */ 207 | const String & name ) override 208 | { 209 | for( const auto & arg : details::asConst( m_children ) ) 210 | { 211 | ArgIface * tmp = arg->findArgument( name ); 212 | 213 | if( tmp != nullptr ) 214 | return tmp; 215 | } 216 | 217 | return nullptr; 218 | } 219 | 220 | /*! 221 | Process argument's staff, for example take values from 222 | context. This method invokes exactly at that moment when 223 | parser has found this argument. 224 | */ 225 | void process( 226 | //! Context of the command line. 227 | Context & ) override 228 | { 229 | } 230 | 231 | /*! 232 | Check correctness of the argument before parsing. 233 | 234 | Implementation of this method must add his flag 235 | and name to the flags and names. 236 | */ 237 | void checkCorrectnessBeforeParsing( 238 | //! All known flags. 239 | StringList & flags, 240 | //! All known names. 241 | StringList & names ) const override 242 | { 243 | for( const auto & arg : details::asConst( m_children ) ) 244 | arg->checkCorrectnessBeforeParsing( flags, names ); 245 | } 246 | 247 | //! Check correctness of the argument after parsing. 248 | void checkCorrectnessAfterParsing() const override 249 | { 250 | for( const auto & arg : details::asConst( m_children ) ) 251 | arg->checkCorrectnessAfterParsing(); 252 | 253 | if( isRequired() && !isDefined() ) 254 | throw BaseException( 255 | String( SL( "Not defined required argument \"" ) ) + 256 | name() + SL( "\"" ) ); 257 | } 258 | 259 | //! Set command line parser. 260 | void setCmdLine( CmdLine * cmdLine ) override 261 | { 262 | ArgIface::setCmdLine( cmdLine ); 263 | 264 | for( const auto & arg : details::asConst( m_children ) ) 265 | arg->setCmdLine( cmdLine ); 266 | } 267 | 268 | //! \return Is given name a misspelled name of the argument. 269 | bool isMisspelledName( 270 | //! Name to check (misspelled). 271 | const String & name, 272 | //! List of possible names for the given misspelled name. 273 | StringList & possibleNames ) const override 274 | { 275 | bool ret = false; 276 | 277 | std::for_each( children().cbegin(), children().cend(), 278 | [ & ] ( const auto & ch ) 279 | { 280 | if( ch->isMisspelledName( name, possibleNames ) ) 281 | ret = true; 282 | } ); 283 | 284 | return ret; 285 | } 286 | 287 | protected: 288 | //! List of children. 289 | Arguments m_children; 290 | 291 | private: 292 | DISABLE_COPY( GroupIface ) 293 | 294 | //! Name. 295 | String m_name; 296 | //! Is required? 297 | bool m_required; 298 | }; // class GroupIface 299 | 300 | const String GroupIface::m_dummyEmptyString; 301 | 302 | } /* namespace Args */ 303 | 304 | #endif // ARGS__GROUP_IFACE_HPP__INCLUDED 305 | -------------------------------------------------------------------------------- /args/groups.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | /*! 32 | \file 33 | 34 | \warning If you are including this file you should include command.hpp too. 35 | */ 36 | 37 | #ifndef ARGS__GROUPS_HPP__INCLUDED 38 | #define ARGS__GROUPS_HPP__INCLUDED 39 | 40 | // Args include. 41 | #include "group_iface.hpp" 42 | #include "types.hpp" 43 | 44 | // C++ include. 45 | #include 46 | 47 | 48 | namespace Args { 49 | 50 | // 51 | // OnlyOneGroup 52 | // 53 | 54 | //! Group of args where only one argument can be defined. 55 | class OnlyOneGroup final 56 | : public GroupIface 57 | { 58 | public: 59 | template< typename T > 60 | explicit OnlyOneGroup( T && name, 61 | bool required = false ) 62 | : GroupIface( std::forward< T > ( name ), required ) 63 | { 64 | } 65 | 66 | virtual ~OnlyOneGroup() 67 | { 68 | } 69 | 70 | //! \return Type of the argument. 71 | ArgType type() const override 72 | { 73 | return ArgType::OnlyOneGroup; 74 | } 75 | 76 | //! \return Is this argument defined? 77 | bool isDefined() const override 78 | { 79 | return std::any_of( children().cbegin(), children().cend(), 80 | [] ( const auto & arg ) { return arg->isDefined(); } ); 81 | } 82 | 83 | protected: 84 | /*! 85 | Check correctness of the argument before parsing. 86 | 87 | Implementation of this method must add his flag 88 | and name to the flags and names. 89 | */ 90 | void checkCorrectnessBeforeParsing( 91 | //! All known flags. 92 | StringList & flags, 93 | //! All known names. 94 | StringList & names ) const override 95 | { 96 | GroupIface::checkCorrectnessBeforeParsing( flags, names ); 97 | 98 | for( const auto & arg : details::asConst( children() ) ) 99 | { 100 | if( arg->isRequired() ) 101 | throw BaseException( String( SL( "Required argument \"" ) ) + 102 | arg->name() + 103 | SL( "\" is not allowed to be in OnlyOne group \"" ) + 104 | name() + SL( "\"." ) ); 105 | } 106 | } 107 | 108 | //! Check correctness of the argument after parsing. 109 | void checkCorrectnessAfterParsing() const override 110 | { 111 | GroupIface::checkCorrectnessAfterParsing(); 112 | 113 | ArgIface * defined = nullptr; 114 | 115 | for( const auto & arg : details::asConst( children() ) ) 116 | { 117 | if( arg->isDefined() ) 118 | { 119 | if( defined ) 120 | throw BaseException( String( SL( "Only one argument can " 121 | "be defined in OnlyOne group \"" ) ) + name() + SL( "\". " ) + 122 | SL( "Whereas defined \"" ) + defined->name() + 123 | SL( "\" and \"" ) + arg->name() + SL( "\"." ) ); 124 | else 125 | defined = arg.get(); 126 | } 127 | } 128 | } 129 | }; // class OnlyOneGroup 130 | 131 | 132 | // 133 | // AllOfGroup 134 | // 135 | 136 | //! Group of args where all arguments should be defined. 137 | class AllOfGroup final 138 | : public GroupIface 139 | { 140 | public: 141 | template< typename T > 142 | explicit AllOfGroup( T && name, 143 | bool required = false ) 144 | : GroupIface( std::forward< T > ( name ), required ) 145 | { 146 | } 147 | 148 | virtual ~AllOfGroup() 149 | { 150 | } 151 | 152 | //! \return Type of the argument. 153 | ArgType type() const override 154 | { 155 | return ArgType::AllOfGroup; 156 | } 157 | 158 | //! \return Is this argument defined? 159 | bool isDefined() const override 160 | { 161 | return !std::any_of( children().cbegin(), children().cend(), 162 | [] ( const auto & arg ) { return !arg->isDefined(); } ); 163 | } 164 | 165 | protected: 166 | /*! 167 | Check correctness of the argument before parsing. 168 | 169 | Implementation of this method must add his flag 170 | and name to the flags and names. 171 | */ 172 | void checkCorrectnessBeforeParsing( 173 | //! All known flags. 174 | StringList & flags, 175 | //! All known names. 176 | StringList & names ) const override 177 | { 178 | GroupIface::checkCorrectnessBeforeParsing( flags, names ); 179 | 180 | for( const auto & arg : details::asConst( children() ) ) 181 | { 182 | if( arg->isRequired() ) 183 | throw BaseException( String( SL( "Required argument \"" ) ) + 184 | arg->name() + 185 | SL( "\" is not allowed to " ) + 186 | SL( "be in AllOf group \"" ) + name() + SL( "\"." ) ); 187 | } 188 | } 189 | 190 | //! Check correctness of the argument after parsing. 191 | void checkCorrectnessAfterParsing() const override 192 | { 193 | GroupIface::checkCorrectnessAfterParsing(); 194 | 195 | const bool defined = std::any_of( children().cbegin(), children().cend(), 196 | [] ( const auto & arg ) { return arg->isDefined(); } ); 197 | 198 | const bool all = std::all_of( children().cbegin(), children().cend(), 199 | [] ( const auto & arg ) { return arg->isDefined(); } ); 200 | 201 | if( defined && !all ) 202 | throw BaseException( String( SL( "All arguments in " 203 | "AllOf group \"" ) ) + name() + SL( "\" should be defined." ) ); 204 | } 205 | }; // class AllOfGroup 206 | 207 | 208 | // 209 | // AtLeastOneGroup 210 | // 211 | 212 | //! Group of args where at least one argument should be defined. 213 | class AtLeastOneGroup final 214 | : public GroupIface 215 | { 216 | public: 217 | template< typename T > 218 | explicit AtLeastOneGroup( T && name, 219 | bool required = false ) 220 | : GroupIface( std::forward< T > ( name ), required ) 221 | { 222 | } 223 | 224 | virtual ~AtLeastOneGroup() 225 | { 226 | } 227 | 228 | //! \return Type of the argument. 229 | ArgType type() const override 230 | { 231 | return ArgType::AtLeastOneGroup; 232 | } 233 | 234 | //! \return Is this argument defined? 235 | bool isDefined() const override 236 | { 237 | return std::any_of( children().cbegin(), children().cend(), 238 | [] ( const auto & arg ) { return arg->isDefined(); } ); 239 | } 240 | 241 | protected: 242 | /*! 243 | Check correctness of the argument before parsing. 244 | 245 | Implementation of this method must add his flag 246 | and name to the flags and names. 247 | */ 248 | void checkCorrectnessBeforeParsing( 249 | //! All known flags. 250 | StringList & flags, 251 | //! All known names. 252 | StringList & names ) const override 253 | { 254 | GroupIface::checkCorrectnessBeforeParsing( flags, names ); 255 | 256 | for( const auto & arg : details::asConst( children() ) ) 257 | { 258 | if( arg->isRequired() ) 259 | throw BaseException( String( SL( "Required argument \"" ) ) + 260 | arg->name() + 261 | SL( "\" is not allowed to " ) + 262 | SL( "be in AtLeastOne group \"" ) + name() + SL( "\"." ) ); 263 | } 264 | } 265 | }; // class AtLeastOneGroup 266 | 267 | } /* namespace Args */ 268 | 269 | #endif // ARGS__GROUPS_HPP__INCLUDED 270 | -------------------------------------------------------------------------------- /args/help.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__HELP_HPP__INCLUDED 32 | #define ARGS__HELP_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "arg.hpp" 36 | #include "help_printer_iface.hpp" 37 | #include "context.hpp" 38 | #include "utils.hpp" 39 | #include "exceptions.hpp" 40 | #include "types.hpp" 41 | #include "command.hpp" 42 | 43 | // C++ include. 44 | #include 45 | 46 | #ifdef ARGS_TESTING 47 | #ifndef ARGS_QSTRING_BUILD 48 | // C++ include. 49 | #include 50 | #endif 51 | #endif 52 | 53 | 54 | namespace Args { 55 | 56 | #ifdef ARGS_TESTING 57 | #ifdef ARGS_WSTRING_BUILD 58 | extern std::wstringstream g_argsOutStream; 59 | #elif defined( ARGS_QSTRING_BUILD ) 60 | extern OutStreamType g_argsOutStream; 61 | #else 62 | extern std::stringstream g_argsOutStream; 63 | #endif 64 | #else 65 | OutStreamType & g_argsOutStream = outStream(); 66 | #endif // ARGS_TESTING 67 | 68 | 69 | // 70 | // Help 71 | // 72 | 73 | //! Help argument. 74 | class Help final 75 | : public Arg 76 | { 77 | public: 78 | explicit Help( bool throwExceptionOnPrint = true ); 79 | 80 | //! Set executable name. 81 | void setExecutable( const String & exe ); 82 | 83 | //! Set description for the application. 84 | void setAppDescription( const String & desc ); 85 | 86 | //! Set line length for the help. 87 | void setLineLength( String::size_type length ); 88 | 89 | protected: 90 | /*! 91 | Process argument's staff, for example take values from 92 | context. This method invokes exactly at that moment when 93 | parser has found this argument. 94 | */ 95 | void process( 96 | //! Context of the command line. 97 | Context & context ) override; 98 | 99 | //! Set command line parser. 100 | void setCmdLine( CmdLine * cmdLine ) override 101 | { 102 | Arg::setCmdLine( cmdLine ); 103 | 104 | m_printer->setCmdLine( cmdLine ); 105 | } 106 | 107 | private: 108 | //! Printer. 109 | std::unique_ptr< HelpPrinterIface > m_printer; 110 | //! Throw or not exception? 111 | bool m_throwExceptionOnPrint; 112 | }; // class Help 113 | 114 | 115 | // 116 | // Help 117 | // 118 | 119 | inline void 120 | Help::setExecutable( const String & exe ) 121 | { 122 | m_printer->setExecutable( exe ); 123 | } 124 | 125 | inline void 126 | Help::setAppDescription( const String & desc ) 127 | { 128 | m_printer->setAppDescription( desc ); 129 | } 130 | 131 | inline void 132 | Help::setLineLength( String::size_type length ) 133 | { 134 | m_printer->setLineLength( length ); 135 | } 136 | 137 | inline void 138 | Help::process( Context & context ) 139 | { 140 | if( !context.atEnd() ) 141 | { 142 | String arg = *context.next(); 143 | 144 | // Argument or flag. 145 | if( details::isArgument( arg ) || details::isFlag( arg ) ) 146 | m_printer->print( arg, g_argsOutStream ); 147 | // Command? 148 | else 149 | { 150 | auto * tmp = m_printer->findArgument( arg ); 151 | 152 | // Command. 153 | if( tmp && tmp->type() == ArgType::Command ) 154 | { 155 | bool printed = false; 156 | 157 | auto * cmd = static_cast< Command* > ( tmp ); 158 | 159 | while( !context.atEnd() ) 160 | { 161 | arg = *context.next(); 162 | 163 | if( tmp && tmp->type() == ArgType::Command ) 164 | { 165 | cmd = static_cast< Command* > ( tmp ); 166 | 167 | // Argument or flag. 168 | if( details::isArgument( arg ) || details::isFlag( arg ) ) 169 | { 170 | m_printer->print( arg, g_argsOutStream, cmd ); 171 | 172 | printed = true; 173 | 174 | break; 175 | } 176 | // Command? 177 | else 178 | tmp = cmd->findChild( arg ); 179 | } 180 | else 181 | break; 182 | } 183 | 184 | if( !printed ) 185 | { 186 | if( tmp ) 187 | m_printer->print( tmp->name(), g_argsOutStream, 188 | ( cmd != tmp ? cmd : nullptr ) ); 189 | else 190 | m_printer->print( g_argsOutStream ); 191 | } 192 | } 193 | else 194 | m_printer->print( g_argsOutStream ); 195 | } 196 | } 197 | else 198 | m_printer->print( g_argsOutStream ); 199 | 200 | setDefined( true ); 201 | 202 | if( m_throwExceptionOnPrint ) 203 | throw HelpHasBeenPrintedException(); 204 | } 205 | 206 | } /* namespace Args */ 207 | 208 | #endif // ARGS__HELP_HPP__INCLUDED 209 | -------------------------------------------------------------------------------- /args/help_printer_iface.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__HELP_PRINTER_IFACE_HPP__INCLUDED 32 | #define ARGS__HELP_PRINTER_IFACE_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "utils.hpp" 36 | 37 | 38 | namespace Args { 39 | 40 | class CmdLine; 41 | class Command; 42 | class ArgIface; 43 | 44 | 45 | // 46 | // HelpPrinterIface 47 | // 48 | 49 | /*! 50 | Interface for HelpPrinter. 51 | */ 52 | class HelpPrinterIface { 53 | public: 54 | HelpPrinterIface() 55 | { 56 | } 57 | 58 | virtual ~HelpPrinterIface() 59 | { 60 | } 61 | 62 | //! Print help for all arguments. 63 | virtual void print( 64 | //! Output stream for the printing help. 65 | OutStreamType & to ) = 0; 66 | 67 | //! Print help for the given argument. 68 | virtual void print( 69 | //! Name of the argument. I.e. "-t" or "--timeout". 70 | const String & name, 71 | //! Output stream for the printing help. 72 | OutStreamType & to, 73 | //! Parent command if present. 74 | Command * parent = nullptr ) = 0; 75 | 76 | //! Set executable name. 77 | virtual void setExecutable( const String & exe ) = 0; 78 | 79 | //! Set description for the application. 80 | virtual void setAppDescription( const String & desc ) = 0; 81 | 82 | //! Set command line. 83 | virtual void setCmdLine( CmdLine * cmd ) = 0; 84 | 85 | //! Set line length for the help. 86 | virtual void setLineLength( String::size_type length ) = 0; 87 | 88 | //! \return Argument for the given name. 89 | virtual ArgIface * findArgument( const String & name ) = 0; 90 | 91 | private: 92 | DISABLE_COPY( HelpPrinterIface ) 93 | }; // class HelpPrinterIface 94 | 95 | } /* namespace Args */ 96 | 97 | #endif // ARGS__HELP_PRINTER_IFACE_HPP__INCLUDED 98 | -------------------------------------------------------------------------------- /args/multi_arg.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__MULTI_ARG_HPP__INCLUDED 32 | #define ARGS__MULTI_ARG_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "arg.hpp" 36 | #include "context.hpp" 37 | #include "exceptions.hpp" 38 | #include "value_utils.hpp" 39 | #include "utils.hpp" 40 | #include "types.hpp" 41 | 42 | // C++ include. 43 | #include 44 | 45 | 46 | namespace Args { 47 | 48 | // 49 | // MultiArg 50 | // 51 | 52 | /*! 53 | MultiArg is a class that presents argument in the command 54 | line taht can be presented more than once or can have more 55 | than one value. 56 | */ 57 | class MultiArg 58 | : public Arg 59 | { 60 | public: 61 | //! Construct argument with flag and name. 62 | template< typename T > 63 | MultiArg( 64 | //! Flag for this argument. 65 | Char flag, 66 | //! Name for this argument. 67 | T && name, 68 | //! Is this argument with value? 69 | bool isWithValue = false, 70 | //! Is this argument required? 71 | bool isRequired = false ); 72 | 73 | //! Construct argument only with flag, without name. 74 | explicit MultiArg( 75 | //! Flag for this argument. 76 | Char flag, 77 | //! Is this argument with value? 78 | bool isWithValue = false, 79 | //! Is this argument required? 80 | bool isRequired = false ); 81 | 82 | //! Construct argument only with name, without flag. 83 | template< typename T > 84 | explicit MultiArg( 85 | //! Name for this argument. 86 | T && name, 87 | //! Is this argument with value? 88 | bool isWithValue = false, 89 | //! Is this argument required? 90 | bool isRequired = false ); 91 | 92 | virtual ~MultiArg(); 93 | 94 | //! \return Type of the argument. 95 | ArgType type() const override 96 | { 97 | return ArgType::MultiArg; 98 | } 99 | 100 | //! \return First value of this argument. 101 | const String & value() const override; 102 | //! Set value. \note Value will be pushed back to the list of values. 103 | void setValue( const String & v ) override; 104 | 105 | //! \return All values for this argument. 106 | virtual const StringList & values() const; 107 | 108 | /*! 109 | \return Count of times that this argument was presented 110 | in the command line if argument without value or count of values 111 | if argument is with values. 112 | */ 113 | size_t count() const; 114 | 115 | //! \return Default value. 116 | const String & defaultValue() const override 117 | { 118 | if( !m_defaultValues.empty() ) 119 | return m_defaultValues.front(); 120 | else 121 | return m_emptyString; 122 | } 123 | 124 | //! Set default value. \note Value will be pushed back to the list 125 | //! of default values. 126 | void setDefaultValue( const String & v ) override 127 | { 128 | m_defaultValues.push_back( v ); 129 | } 130 | 131 | //! \return Default values. 132 | const StringList & defaultValues() const 133 | { 134 | return m_defaultValues; 135 | } 136 | 137 | //! Set default values. 138 | void setDefaultValues( const StringList & v ) 139 | { 140 | m_defaultValues = v; 141 | } 142 | 143 | //! Clear state of the argument. 144 | void clear() override 145 | { 146 | setDefined( false ); 147 | 148 | m_values.clear(); 149 | } 150 | 151 | protected: 152 | /*! 153 | Process argument's staff, for example take values from 154 | context. This method invokes exactly at that moment when 155 | parser has found this argument. 156 | */ 157 | void process( 158 | //! Context of the command line. 159 | Context & context ) override; 160 | 161 | private: 162 | DISABLE_COPY( MultiArg ) 163 | 164 | //! Dummy empty string. 165 | static const String m_emptyString; 166 | 167 | //! Values of this argument. 168 | StringList m_values; 169 | //! Counter. 170 | size_t m_count; 171 | //! Default values. 172 | StringList m_defaultValues; 173 | }; // class MultiArg 174 | 175 | const String MultiArg::m_emptyString; 176 | 177 | 178 | // 179 | // MultiArg 180 | // 181 | 182 | template< typename T > 183 | MultiArg::MultiArg( Char flag, T && name, 184 | bool isWithValue, bool isRequired ) 185 | : Arg( flag, std::forward< T > ( name ), isWithValue, isRequired ) 186 | , m_count( 0 ) 187 | { 188 | } 189 | 190 | inline 191 | MultiArg::MultiArg( Char flag, 192 | bool isWithValue, bool isRequired ) 193 | : Arg( flag, isWithValue, isRequired ) 194 | , m_count( 0 ) 195 | { 196 | } 197 | 198 | template< typename T > 199 | MultiArg::MultiArg( T && name, 200 | bool isWithValue, bool isRequired ) 201 | : Arg( std::forward< T > ( name ), isWithValue, isRequired ) 202 | , m_count( 0 ) 203 | { 204 | } 205 | 206 | inline 207 | MultiArg::~MultiArg() 208 | { 209 | } 210 | 211 | inline const String & 212 | MultiArg::value() const 213 | { 214 | if( !m_values.empty() ) 215 | return m_values.front(); 216 | else if( !m_defaultValues.empty() ) 217 | return m_defaultValues.front(); 218 | else 219 | return m_emptyString; 220 | } 221 | 222 | inline void 223 | MultiArg::setValue( const String & v ) 224 | { 225 | m_values.push_back( v ); 226 | } 227 | 228 | inline const StringList & 229 | MultiArg::values() const 230 | { 231 | if( !m_values.empty() ) 232 | return m_values; 233 | else 234 | return m_defaultValues; 235 | } 236 | 237 | inline size_t 238 | MultiArg::count() const 239 | { 240 | if( !isWithValue() ) 241 | return m_count; 242 | else if( !m_values.empty() ) 243 | return m_values.size(); 244 | else 245 | return m_defaultValues.size(); 246 | } 247 | 248 | inline void 249 | MultiArg::process( Context & context ) 250 | { 251 | if( isWithValue() ) 252 | { 253 | setDefined( eatValues( context, m_values, 254 | String( SL( "Argument \"" ) ) + 255 | name() + SL( "\" requires value that wasn't presented." ), 256 | cmdLine() ) ); 257 | } 258 | else 259 | { 260 | setDefined( true ); 261 | 262 | ++m_count; 263 | } 264 | } 265 | 266 | } /* namespace Args */ 267 | 268 | #endif // ARGS__MULTI_ARG_HPP__INCLUDED 269 | 270 | -------------------------------------------------------------------------------- /args/types.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__TYPES_HPP__INCLUDED 32 | #define ARGS__TYPES_HPP__INCLUDED 33 | 34 | #ifdef ARGS_WSTRING_BUILD 35 | // C++ include. 36 | #include 37 | #include 38 | 39 | #ifdef ARGS_LIST 40 | #include 41 | #elif defined( ARGS_DEQUE ) 42 | #include 43 | #else 44 | #include 45 | #endif 46 | 47 | #elif defined( ARGS_QSTRING_BUILD ) 48 | // Qt include. 49 | #include 50 | #include 51 | 52 | #ifdef ARGS_LIST 53 | #include 54 | #elif defined( ARGS_DEQUE ) 55 | #include 56 | #else 57 | #include 58 | #endif 59 | 60 | #else 61 | // C++ include. 62 | #include 63 | #include 64 | 65 | #ifdef ARGS_LIST 66 | #include 67 | #elif defined( ARGS_DEQUE ) 68 | #include 69 | #else 70 | #include 71 | #endif 72 | 73 | #endif 74 | 75 | 76 | namespace Args { 77 | 78 | #ifdef ARGS_WSTRING_BUILD 79 | 80 | //! String type. 81 | using String = std::wstring; 82 | 83 | //! Char type. 84 | using Char = String::value_type; 85 | 86 | //! Out stream type. 87 | using OutStreamType = std::wostream; 88 | 89 | //! Output stream. 90 | static OutStreamType & outStream() 91 | { 92 | return std::wcout; 93 | } 94 | 95 | #define SL(str) L##str 96 | 97 | //! List of strings. 98 | #ifdef ARGS_LIST 99 | using StringList = std::list< String >; 100 | #elif defined( ARGS_DEQUE ) 101 | using StringList = std::deque< String >; 102 | #else 103 | using StringList = std::vector< String >; 104 | #endif 105 | 106 | #elif defined( ARGS_QSTRING_BUILD ) 107 | 108 | //! Char type. 109 | using Char = QChar; 110 | 111 | //! Out stream type. 112 | using OutStreamType = QTextStream; 113 | 114 | class String { 115 | public: 116 | using size_type = int; 117 | 118 | String() 119 | { 120 | } 121 | 122 | String( size_type size, Char ch ) 123 | : m_str( size, ch ) 124 | { 125 | } 126 | 127 | String( const char * str ) 128 | : m_str( str ) 129 | { 130 | } 131 | 132 | String( const QString & other ) 133 | : m_str( other ) 134 | { 135 | } 136 | 137 | 138 | String( const Char * unicode, size_type size = -1 ) 139 | : m_str( unicode, size ) 140 | { 141 | } 142 | 143 | String( Char ch ) 144 | : m_str( ch ) 145 | { 146 | } 147 | 148 | String( QLatin1String str ) 149 | : m_str( str ) 150 | { 151 | } 152 | 153 | String( const QByteArray & ba ) 154 | : m_str( ba ) 155 | { 156 | } 157 | 158 | operator QString () 159 | { 160 | return m_str; 161 | } 162 | 163 | operator QString () const 164 | { 165 | return m_str; 166 | } 167 | 168 | inline bool empty() const 169 | { 170 | return m_str.isEmpty(); 171 | } 172 | 173 | static const int npos = -1; 174 | 175 | inline int find( Char ch ) const 176 | { 177 | return m_str.indexOf( ch ); 178 | } 179 | 180 | inline int find( const String & str ) const 181 | { 182 | return m_str.indexOf( str.m_str ); 183 | } 184 | 185 | QString::iterator begin() 186 | { 187 | return m_str.begin(); 188 | } 189 | 190 | QString::iterator end() 191 | { 192 | return m_str.end(); 193 | } 194 | 195 | QString::const_iterator begin() const 196 | { 197 | return m_str.begin(); 198 | } 199 | 200 | QString::const_iterator end() const 201 | { 202 | return m_str.end(); 203 | } 204 | 205 | QString::const_iterator cbegin() const 206 | { 207 | return m_str.begin(); 208 | } 209 | 210 | QString::const_iterator cend() const 211 | { 212 | return m_str.end(); 213 | } 214 | 215 | size_type length() const 216 | { 217 | return m_str.length(); 218 | } 219 | 220 | String substr( size_type pos, size_type count = npos ) const 221 | { 222 | return m_str.mid( pos, count ); 223 | } 224 | 225 | friend bool operator == ( const String & s1, const String & s2 ) 226 | { 227 | return ( s1.m_str == s2.m_str ); 228 | } 229 | 230 | friend String operator + ( const String & s1, const String & s2 ) 231 | { 232 | return String( s1.m_str + s2.m_str ); 233 | } 234 | 235 | friend String operator + ( const String & s1, const char * s2 ) 236 | { 237 | return String( s1.m_str + s2 ); 238 | } 239 | 240 | friend String operator + ( const char * s1, const String & s2 ) 241 | { 242 | return String( s1 + s2.m_str ); 243 | } 244 | 245 | friend String operator + ( const String & s1, const char ch ) 246 | { 247 | return String( s1.m_str + ch ); 248 | } 249 | 250 | friend String operator + ( const char ch, const String & s2 ) 251 | { 252 | return String( ch + s2.m_str ); 253 | } 254 | 255 | friend bool operator < ( const String & s1, const String & s2 ) 256 | { 257 | return s1.m_str < s2.m_str; 258 | } 259 | 260 | friend OutStreamType & operator << ( OutStreamType & to, 261 | const String & what ) 262 | { 263 | to << what.m_str; 264 | 265 | return to; 266 | } 267 | 268 | const Char operator [] ( size_type pos ) const 269 | { 270 | return m_str[ pos ]; 271 | } 272 | 273 | String & append( const String & other ) 274 | { 275 | m_str.append( other.m_str ); 276 | 277 | return *this; 278 | } 279 | 280 | String & append( size_type count, Char ch ) 281 | { 282 | m_str.append( QString( count, ch ) ); 283 | 284 | return *this; 285 | } 286 | 287 | void clear() 288 | { 289 | m_str.clear(); 290 | } 291 | 292 | private: 293 | //! Actual string. 294 | QString m_str; 295 | }; // class String 296 | 297 | //! Output stream. 298 | static OutStreamType & outStream() 299 | { 300 | static QTextStream stream( stdout ); 301 | 302 | return stream; 303 | } 304 | 305 | #define SL(str) str 306 | 307 | //! List of strings. 308 | #ifdef ARGS_LIST 309 | using StringList = QLinkedList< String >; 310 | #elif defined( ARGS_DEQUE ) 311 | using StringList = QList< String >; 312 | #else 313 | using StringList = QVector< String >; 314 | #endif 315 | 316 | #else 317 | 318 | //! String type. 319 | using String = std::string; 320 | 321 | //! Char type. 322 | using Char = String::value_type; 323 | 324 | //! Out stream type. 325 | using OutStreamType = std::ostream; 326 | 327 | //! Output stream. 328 | static OutStreamType & outStream() 329 | { 330 | return std::cout; 331 | } 332 | 333 | #define SL(str) str 334 | 335 | //! List of strings. 336 | #ifdef ARGS_LIST 337 | using StringList = std::list< String >; 338 | #elif defined( ARGS_DEQUE ) 339 | using StringList = std::deque< String >; 340 | #else 341 | using StringList = std::vector< String >; 342 | #endif 343 | 344 | #endif 345 | 346 | 347 | namespace details { 348 | 349 | // 350 | // Deleter 351 | // 352 | 353 | //! Deleter. 354 | template< typename T > 355 | class Deleter { 356 | public: 357 | explicit Deleter( bool shouldIDelete ) 358 | : m_delete( shouldIDelete ) 359 | { 360 | } 361 | 362 | void operator () ( T * obj ) noexcept 363 | { 364 | if( m_delete ) 365 | delete obj; 366 | } 367 | 368 | private: 369 | //! Should deleter delete object? 370 | bool m_delete; 371 | }; // class Deleter 372 | 373 | } /* namespace details */ 374 | 375 | } /* namespace Args */ 376 | 377 | #endif // ARGS__TYPES_HPP__INCLUDED 378 | -------------------------------------------------------------------------------- /args/utils.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__UTILS_HPP__INCLUDED 32 | #define ARGS__UTILS_HPP__INCLUDED 33 | 34 | #ifndef ARGS_QSTRING_BUILD 35 | 36 | // C++ include. 37 | #include 38 | 39 | #else 40 | 41 | // Qt include. 42 | #include 43 | 44 | #endif 45 | 46 | // Args include. 47 | #include "types.hpp" 48 | 49 | // C++ include. 50 | #include 51 | #include 52 | 53 | 54 | namespace Args { 55 | 56 | 57 | // 58 | // DISABLE_COPY 59 | // 60 | 61 | //! Macro for disabling copy. 62 | #define DISABLE_COPY( Class ) \ 63 | Class( const Class & ) = delete; \ 64 | Class & operator= ( const Class & ) = delete; 65 | 66 | 67 | // 68 | // UNUSED 69 | // 70 | 71 | //! Macro to supress warning about unused argument. 72 | #define UNUSED( Var ) (void)Var; 73 | 74 | 75 | namespace details { 76 | 77 | // 78 | // asConst 79 | // 80 | 81 | //! Adds const to non-const objects. 82 | template< typename T > 83 | constexpr typename std::add_const< T >::type & 84 | asConst( T & t ) noexcept 85 | { 86 | return t; 87 | } 88 | 89 | template < typename T > 90 | void asConst( const T && ) = delete; 91 | 92 | 93 | // 94 | // isArgument 95 | // 96 | 97 | //! \return Is word an argument? 98 | static inline bool 99 | isArgument( const String & word ) 100 | { 101 | return ( word.find( SL( "--" ) ) == 0 ); 102 | } // isArgument 103 | 104 | 105 | // 106 | // isFlag 107 | // 108 | 109 | //! \return Is word a flag? 110 | static inline bool 111 | isFlag( const String & word ) 112 | { 113 | if( !isArgument( word ) ) 114 | { 115 | if( word.find( SL( '-' ) ) == 0 ) 116 | return true; 117 | } 118 | 119 | return false; 120 | } // isFlag 121 | 122 | 123 | // 124 | // isCorrectFlag 125 | // 126 | 127 | //! \return Is flag correct? 128 | static inline bool 129 | isCorrectFlag( const String & flag ) 130 | { 131 | if( flag.empty() || flag.length() > 1 ) 132 | return false; 133 | 134 | static const String availableSymbols( SL( "0123456789" 135 | "abcdefghijklmnopqrstuvwxyz" 136 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ) ); 137 | 138 | return ( availableSymbols.find( flag ) != String::npos ); 139 | } // isCorrectFlag 140 | 141 | 142 | // 143 | // isCorrectName 144 | // 145 | 146 | //! \return Is name correct? 147 | static inline bool 148 | isCorrectName( const String & name ) 149 | { 150 | if( name.empty() ) 151 | return false; 152 | 153 | #ifndef ARGS_QSTRING_BUILD 154 | 155 | #ifdef ARGS_WSTRING_BUILD 156 | std::wregex r( L"\\s" ); 157 | #else 158 | std::regex r( "\\s" ); 159 | #endif 160 | 161 | if( std::regex_search( name, r ) ) 162 | return false; 163 | #else 164 | QRegExp r( "\\s" ); 165 | 166 | if( r.indexIn( name ) != -1 ) 167 | return false; 168 | #endif 169 | 170 | static const String availableSymbols( SL( "0123456789" 171 | "abcdefghijklmnopqrstuvwxyz" 172 | "ABCDEFGHIJKLMNOPQRSTUVWXYZ-_" ) ); 173 | 174 | for( const Char & c : asConst( name ) ) 175 | { 176 | if( availableSymbols.find( c ) == String::npos ) 177 | return false; 178 | } 179 | 180 | return true; 181 | } // isCorrectName 182 | 183 | 184 | // 185 | // isMisspelledName 186 | // 187 | 188 | //! \return Is the given name a misspelling of correct name. 189 | bool isMisspelledName( const String & misspelled, 190 | const String & correct ) 191 | { 192 | if( !misspelled.empty() && !correct.empty() ) 193 | { 194 | String ms = misspelled; 195 | String cs = correct; 196 | 197 | std::sort( ms.begin(), ms.end() ); 198 | std::sort( cs.begin(), cs.end() ); 199 | 200 | return ( ms == cs ); 201 | } 202 | else 203 | return false; 204 | } 205 | 206 | } /* namespace details */ 207 | 208 | } /* namespace Args */ 209 | 210 | #endif // ARGS__UTILS_HPP__INCLUDED 211 | -------------------------------------------------------------------------------- /args/value_utils.hpp: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | \file 4 | 5 | \author Igor Mironchik (igor.mironchik at gmail dot com). 6 | 7 | Copyright (c) 2013-2020 Igor Mironchik 8 | 9 | Permission is hereby granted, free of charge, to any person 10 | obtaining a copy of this software and associated documentation 11 | files (the "Software"), to deal in the Software without 12 | restriction, including without limitation the rights to use, 13 | copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the 15 | Software is furnished to do so, subject to the following 16 | conditions: 17 | 18 | The above copyright notice and this permission notice shall be 19 | included in all copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 23 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 27 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 | OTHER DEALINGS IN THE SOFTWARE. 29 | */ 30 | 31 | #ifndef ARGS__VALUE_UTILS_HPP__INCLUDED 32 | #define ARGS__VALUE_UTILS_HPP__INCLUDED 33 | 34 | // Args include. 35 | #include "utils.hpp" 36 | #include "exceptions.hpp" 37 | #include "types.hpp" 38 | 39 | // C++ include. 40 | #include 41 | 42 | 43 | namespace Args { 44 | 45 | // 46 | // eatValues 47 | // 48 | 49 | //! Eat values in context. 50 | template< typename Container, typename Cmd, typename Ctx > 51 | bool eatValues( Ctx & context, Container & container, 52 | const String & errorDescription, Cmd * cmdLine ) 53 | { 54 | if( !context.atEnd() ) 55 | { 56 | auto begin = context.begin(); 57 | 58 | auto last = std::find_if( context.begin(), context.end(), 59 | [ & ] ( const String & v ) -> bool 60 | { 61 | return( cmdLine->findArgument( v ) != nullptr ); 62 | } 63 | ); 64 | 65 | if( last != begin ) 66 | { 67 | begin = context.next(); 68 | 69 | while( begin != last ) 70 | { 71 | container.push_back( *begin ); 72 | 73 | begin = context.next(); 74 | } 75 | 76 | if( last != context.end() ) 77 | context.putBack(); 78 | 79 | return true; 80 | } 81 | } 82 | 83 | throw BaseException( errorDescription ); 84 | } 85 | 86 | 87 | // 88 | // eatOneValue 89 | // 90 | 91 | //! Eat one value. 92 | template< typename Cmd, typename Ctx > 93 | String eatOneValue( Ctx & context, 94 | const String & errorDescription, Cmd * cmdLine ) 95 | { 96 | if( !context.atEnd() ) 97 | { 98 | auto val = context.next(); 99 | 100 | if( !cmdLine->findArgument( *val ) ) 101 | return *val; 102 | 103 | context.putBack(); 104 | } 105 | 106 | throw BaseException( errorDescription ); 107 | } 108 | 109 | } /* namespace Args */ 110 | 111 | #endif // ARGS__VALUE_UTILS_HPP__INCLUDED 112 | -------------------------------------------------------------------------------- /codegen/CodeGen.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/1/31. 3 | // 4 | 5 | #include "CodeGen.h" 6 | 7 | void CodeGenContext::push_block(BasicBlock *block) { 8 | auto bb = new CodeGenBlock(); 9 | bb->block = block; 10 | if (blocks == nullptr) { 11 | blocks = new std::vector(); 12 | } 13 | this->blocks->push_back(bb); 14 | 15 | } 16 | 17 | CodeGenBlock *CodeGenContext::pop_block() { 18 | CodeGenBlock *top = (*this->blocks)[this->blocks->size() - 1]; 19 | this->blocks->pop_back(); 20 | return top; 21 | } 22 | 23 | CodeGenBlock *CodeGenContext::get_current_locals() { 24 | if (blocks == nullptr || blocks->empty()) { 25 | return nullptr; 26 | } else { 27 | return (*this->blocks)[this->blocks->size() - 1]; 28 | } 29 | } 30 | 31 | void CodeGenContext::setFunction(Function *func) { 32 | function = func; 33 | } 34 | 35 | Function *CodeGenContext::getFunc() { 36 | return function; 37 | } 38 | 39 | void CodeGenContext::removeFunction() { 40 | function = nullptr; 41 | } 42 | 43 | Value *CodeGenContext::findValue(std::string &name) { 44 | if (blocks->empty()) { 45 | return nullptr; 46 | } 47 | auto it = blocks->rbegin(); 48 | for (; it != blocks->rend(); it++) { 49 | auto itt = (*it)->localVars.find(name); 50 | if (itt != (*it)->localVars.end()) { 51 | return (*itt).second; 52 | } 53 | } 54 | auto gv = TheModule->getGlobalVariable(name); 55 | return gv; 56 | } 57 | 58 | CodeGenBlock *CodeGenContext::findTopCodeGenBlockTypeBlock(CodeGenBlockContextType type) { 59 | if (blocks->empty()) { 60 | return nullptr; 61 | } 62 | for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { 63 | if ((*i)->contextType == type) { 64 | return (*i); 65 | } 66 | } 67 | return nullptr; 68 | } 69 | 70 | CodeGenBlock *CodeGenContext::findTopLoopCodeGenBlockTypeBlock() { 71 | if (blocks->empty()) { 72 | return nullptr; 73 | } 74 | for (auto i = blocks->rbegin(); i != blocks->rend(); ++i) { 75 | if (isLoopCodeGenBlockContextType((*i)->contextType)) { 76 | return (*i); 77 | } 78 | } 79 | return nullptr; 80 | } 81 | 82 | BasicBlock *CodeGenContext::getRetBb() const { 83 | return retBB; 84 | } 85 | 86 | void CodeGenContext::setRetBb(BasicBlock *retBb) { 87 | retBB = retBb; 88 | } 89 | 90 | Value *CodeGenContext::getRetV() const { 91 | return retV; 92 | } 93 | 94 | void CodeGenContext::setRetV(Value *retV) { 95 | CodeGenContext::retV = retV; 96 | } 97 | 98 | bool isLoopCodeGenBlockContextType(CodeGenBlockContextType type) { 99 | return (type == CodeGenBlockContextType::FOR) 100 | || type == CodeGenBlockContextType::WHILE; 101 | } 102 | 103 | void CodeGenBlock::setContextType(CodeGenBlockContextType contextType) { 104 | CodeGenBlock::contextType = contextType; 105 | } 106 | 107 | void CodeGenContext::reset(){ 108 | if (blocks != nullptr){ 109 | blocks->clear(); 110 | } 111 | setIsAborted(false); 112 | function = nullptr; 113 | retBB = nullptr; 114 | retV = nullptr; 115 | } 116 | 117 | bool CodeGenContext::isAborted() const { 118 | return is_aborted; 119 | } 120 | 121 | void CodeGenContext::setIsAborted(bool isAborted) { 122 | is_aborted = isAborted; 123 | } 124 | 125 | ForCodeGenBlockContext::ForCodeGenBlockContext(BasicBlock *bbStart, BasicBlock *bbCond, BasicBlock *bbStep, 126 | BasicBlock *bbBody, BasicBlock *bbEndFor) : bbStart(bbStart), 127 | bbCond(bbCond), 128 | bbStep(bbStep), 129 | bbBody(bbBody), 130 | bbEndFor(bbEndFor) {} 131 | 132 | WhileCodeGenBlockContext::WhileCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbBody, BasicBlock *bbEndWhile) 133 | : bbCond(bbCond), bbBody(bbBody), bbEndWhile(bbEndWhile) {} 134 | 135 | IfCodeGenBlockContext::IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEndIf, BasicBlock *bbTrue, 136 | BasicBlock *bbElse) : bbCond(bbCond), bbEndIf(bbEndIf), bbTrue(bbTrue), 137 | bbElse(bbElse) {} 138 | -------------------------------------------------------------------------------- /codegen/CodeGen.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/1/31. 3 | // 4 | 5 | #ifndef LLVM_KALEIDOSCOPE_CODEGEN_H 6 | #define LLVM_KALEIDOSCOPE_CODEGEN_H 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | using namespace llvm; 14 | 15 | extern std::unique_ptr TheModule; 16 | 17 | enum CodeGenBlockContextType { 18 | NONE, //无 19 | FOR, //for环境 20 | IF, // if环境 21 | WHILE 22 | }; 23 | 24 | bool isLoopCodeGenBlockContextType(CodeGenBlockContextType type); 25 | 26 | typedef struct ForCodeGenBlockContext { 27 | BasicBlock *bbStart; 28 | BasicBlock *bbCond; 29 | BasicBlock *bbStep; 30 | BasicBlock *bbBody; 31 | BasicBlock *bbEndFor; 32 | 33 | ForCodeGenBlockContext(BasicBlock *bbStart, BasicBlock *bbCond, BasicBlock *bbStep, BasicBlock *bbBody, 34 | BasicBlock *bbEndFor); 35 | 36 | } ForCodeGenBlockContext; 37 | 38 | typedef struct IfCodeGenBlockContext { 39 | BasicBlock *bbCond; 40 | BasicBlock *bbEndIf; 41 | BasicBlock *bbTrue; 42 | BasicBlock *bbElse; 43 | 44 | IfCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbEndIf, BasicBlock *bbTrue, BasicBlock *bbElse); 45 | } IfCodeGenBlockContext; 46 | 47 | typedef struct WhileCodeGenBlockContext { 48 | BasicBlock *bbCond; 49 | BasicBlock *bbBody; 50 | BasicBlock *bbEndWhile; 51 | 52 | WhileCodeGenBlockContext(BasicBlock *bbCond, BasicBlock *bbBody, BasicBlock *bbEndWhile); 53 | 54 | } WhileCodeGenBlockContext; 55 | 56 | union CodeGenBlockContext { 57 | ForCodeGenBlockContext *forCodeGenBlockContext; 58 | IfCodeGenBlockContext *ifCodeGenBlockContext; 59 | WhileCodeGenBlockContext *whileCodeGenBlockContext; 60 | }; 61 | typedef union CodeGenBlockContext CodeGenBlockContext; 62 | 63 | class CodeGenBlock { 64 | public: 65 | BasicBlock *block; // BasicBlock 66 | std::map localVars; //本地变量 67 | CodeGenBlockContext context; 68 | enum CodeGenBlockContextType contextType = CodeGenBlockContextType::NONE; //默认为NONE 69 | 70 | void setContextType(CodeGenBlockContextType contextType); 71 | }; 72 | 73 | class CodeGenContext { 74 | public: 75 | std::vector *blocks; 76 | // 目前设计为单例模式 77 | Function *function; 78 | BasicBlock *retBB; 79 | Value *retV; 80 | bool is_aborted = false; 81 | 82 | [[nodiscard]] bool isAborted() const; 83 | 84 | void setIsAborted(bool isAborted); 85 | 86 | void push_block(BasicBlock *block); 87 | 88 | CodeGenBlock *pop_block(); 89 | 90 | CodeGenBlock *get_current_locals(); 91 | 92 | void setFunction(Function *func); 93 | 94 | Function *getFunc(); 95 | 96 | void removeFunction(); 97 | 98 | Value *findValue(std::string &name); 99 | 100 | BasicBlock *getRetBb() const; 101 | 102 | Value *getRetV() const; 103 | 104 | void setRetV(Value *retV); 105 | 106 | void setRetBb(BasicBlock *retBb); 107 | 108 | void reset(); 109 | 110 | /** 111 | * 获取顶部符合type的block 112 | * @param type 113 | * @return CodeGenBlock* 114 | */ 115 | CodeGenBlock *findTopCodeGenBlockTypeBlock(CodeGenBlockContextType type); 116 | 117 | CodeGenBlock *findTopLoopCodeGenBlockTypeBlock(); 118 | }; 119 | 120 | #endif //LLVM_KALEIDOSCOPE_CODEGEN_H 121 | -------------------------------------------------------------------------------- /compiler/Compiler.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/3/12. 3 | // 4 | 5 | #include "Compiler.h" 6 | 7 | #include "codegen/CodeGen.h" 8 | #include "stat.h" 9 | #include "module/time/src/time.c" 10 | #include "parser/NetworkReader.h" 11 | 12 | #ifdef CLANG_SUPPORT 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | using namespace clang; 22 | #endif 23 | 24 | Lexer *m_lexer; 25 | 26 | const vector *getOpenSSLLibDir(); 27 | 28 | void initExternFunc() { 29 | // 初始化外层函数 30 | ExternFunctionLinker::registerHandler(new EchoFunctionHandler()); 31 | ExternFunctionLinker::registerHandler(new SleepFunctionHandler()); 32 | ExternFunctionLinker::registerHandler(new TimeFunctionHandler()); 33 | ExternFunctionLinker::registerHandler(new WebFunctionHandler()); 34 | ExternFunctionLinker::registerHandler(new KStringFunctionHandler()); 35 | ExternFunctionLinker::registerHandler(new KsqlFunctionHandler()); 36 | } 37 | 38 | int startAnalyze(ArgsParser *parser) { 39 | // 初始化外层函数 40 | initExternFunc(); 41 | for (const auto &uri : parser->getFiles()) { 42 | outs() << "正在分析 " << uri << "...\n"; 43 | boost::cmatch url_parsed; 44 | IFileReader *file_reader; 45 | if (boost::regex_match(uri.c_str(), url_parsed, network::url_regex)) { 46 | file_reader = new NetworkReader(uri); 47 | } else { 48 | file_reader = new FileReader(uri); 49 | } 50 | m_lexer = new Lexer(file_reader); 51 | TheLexer = m_lexer; 52 | long t1 = __getms(); 53 | int result = yyparse(); 54 | if (!result) { 55 | auto ast = program; 56 | auto val = ast->codegen(); 57 | #ifdef DEBUG_FLAG 58 | ast->initChildrenLayers(); 59 | std::cout << ast->toString(); 60 | webc::outputStats(); 61 | #endif 62 | if (val == nullptr) { 63 | return RERR; 64 | } else { 65 | long t2 = __getms(); 66 | printf("\n语法分析耗时:%ld", t2 - t1); 67 | return ROK; 68 | } 69 | } else { 70 | return RERR; 71 | } 72 | } 73 | return RERR; 74 | } 75 | 76 | int genCode(const set &opts, const char *outputPath) { 77 | #ifdef SYSY_ARM 78 | LLVMInitializeARMTargetInfo(); 79 | LLVMInitializeARMTarget(); 80 | LLVMInitializeARMTargetMC(); 81 | LLVMInitializeARMAsmParser(); 82 | LLVMInitializeARMAsmPrinter(); 83 | #endif 84 | #ifdef SYSY_AARCH64 85 | LLVMInitializeAArch64TargetInfo(); 86 | LLVMInitializeAArch64Target(); 87 | LLVMInitializeAArch64TargetMC(); 88 | LLVMInitializeAArch64AsmParser(); 89 | LLVMInitializeAArch64AsmPrinter(); 90 | #else 91 | LLVMInitializeX86TargetInfo(); 92 | LLVMInitializeX86Target(); 93 | LLVMInitializeX86TargetMC(); 94 | LLVMInitializeX86AsmParser(); 95 | LLVMInitializeX86AsmPrinter(); 96 | #endif 97 | long t1 = __getms(); 98 | auto TargetTriple = sys::getDefaultTargetTriple(); 99 | TheModule->setTargetTriple(TargetTriple); 100 | 101 | outs() << "正在生成目标代码(" << TargetTriple << ")...\n"; 102 | std::string err; 103 | auto Target = TargetRegistry::lookupTarget(TargetTriple, err); 104 | 105 | // Print an error and exit if we couldn't find the requested target. 106 | // This generally occurs if we've forgotten to initialise the 107 | // TargetRegistry or we have a bogus target triple. 108 | if (!Target) { 109 | LogError(err.c_str()); 110 | auto it = TargetRegistry::targets(); 111 | errs() << "支持的targets:\n"; 112 | auto i = it.begin(); 113 | while (i != it.end()) { 114 | errs() << (*i).getName() << "\n"; 115 | i++; 116 | } 117 | return 1; 118 | } 119 | 120 | auto CPU = "generic"; 121 | auto Features = ""; 122 | 123 | TargetOptions opt; 124 | auto RM = Optional(); 125 | auto TheTargetMachine = 126 | Target->createTargetMachine(TargetTriple, CPU, Features, opt, RM); 127 | 128 | TheModule->setDataLayout(TheTargetMachine->createDataLayout()); 129 | 130 | auto omit_file_name = (string(outputPath) + OBJ_SUFFIX); 131 | std::error_code EC; 132 | 133 | if (EC) { 134 | LogError(EC.message().c_str()); 135 | return 1; 136 | } 137 | auto file_type = CodeGenFileType::CGFT_ObjectFile; 138 | if (opts.find(ArgsParser::Options::OUTPUT_LLVMAS_FILE) != opts.end()) { 139 | file_type = CodeGenFileType::CGFT_AssemblyFile; 140 | omit_file_name = string(outputPath) + ASM_SUFFIX; 141 | } 142 | raw_fd_ostream dest(omit_file_name, EC, sys::fs::F_None); 143 | legacy::PassManager pass; 144 | // 临时关闭这些优化器 145 | #ifdef DEBUG_FLAG 146 | 147 | #else 148 | pass.add(createTailCallEliminationPass()); 149 | pass.add(createReassociatePass()); 150 | pass.add(createGVNPass()); 151 | pass.add(createCFGSimplificationPass()); 152 | #endif 153 | if (opts.find(ArgsParser::Options::PASS_TIME_ANALYSIS) != opts.end()) { 154 | pass.add(new TimeAnalysisPass()); 155 | } 156 | pass.add(new RecursiveToLoopPass()); 157 | if (TheTargetMachine->addPassesToEmitFile(pass, dest, nullptr, file_type)) { 158 | LogError("TheTargetMachine can't emit a file of this type"); 159 | return 1; 160 | } 161 | pass.run(*TheModule); 162 | #ifdef DEBUG_FLAG 163 | #ifdef CGUI 164 | std::string ir_buf; 165 | raw_string_ostream rfostream(ir_buf); 166 | TheModule->print(rfostream, NIL); 167 | rfostream.flush(); 168 | LogInfo(ir_buf.c_str()); 169 | #else 170 | TheModule->print(outs(), NIL); 171 | #endif 172 | #endif 173 | dest.flush(); 174 | if (dest.has_error()) { 175 | LogError(dest.error().message().c_str()); 176 | } 177 | 178 | LogInfo("已生成目标文件"); 179 | LogInfo(omit_file_name.c_str()); 180 | #ifdef CLANG_SUPPORT 181 | // 不需要生成可执行文件 182 | if (opts.find(ArgsParser::Options::OUTPUT_EXECUTABLE) == opts.end()) { 183 | return ROK; 184 | } 185 | LogInfo("开始生成可执行文件"); 186 | auto clang = llvm::sys::findProgramByName("clang++"); 187 | if (auto ec = clang.getError()) { 188 | LogInfo("clang++未找到"); 189 | LogInfo(ec.message().c_str()); 190 | return RERR; 191 | } 192 | LogInfo(clang->c_str()); 193 | vector args; 194 | // TODO 支持多文件 195 | args.push_back(clang->c_str()); 196 | args.push_back(omit_file_name.c_str()); 197 | #if WIN32 198 | #else 199 | args.push_back("-L/usr/local/lib"); 200 | #endif 201 | args.push_back("-lksql"); 202 | args.push_back("-lmysqlcppconn"); 203 | args.push_back("-lkweb"); 204 | args.push_back("-lktime"); 205 | args.push_back("-lkjson"); 206 | args.push_back("-lkstring"); 207 | // 系统库 208 | args.push_back("-lpthread"); 209 | // 链接openssl 210 | auto openssl_libs = getOpenSSLLibDir(); 211 | if (openssl_libs == nullptr) { 212 | LogError("openssl库没找到,无法编译"); 213 | return RERR; 214 | } 215 | for (const auto &item : *openssl_libs) { 216 | args.push_back(item.c_str()); 217 | } 218 | #ifdef WIN32 219 | args.push_back("-lwsock32"); 220 | args.push_back("-lws2_32"); 221 | #endif 222 | // 输出文件 223 | args.push_back("-o"); 224 | args.push_back(outputPath); 225 | IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); 226 | DiagnosticsEngine diag_engine(DiagID, new DiagnosticOptions()); 227 | driver::Driver driver(args[0], sys::getDefaultTargetTriple(), diag_engine); 228 | auto webc_compilation = driver.BuildCompilation(args); 229 | // fallback 230 | SmallVector, 4> failingCommands; 231 | const clang::driver::Command *failingCommand = nullptr; 232 | #ifdef DEBUG_FLAG 233 | driver.PrintActions(*webc_compilation); 234 | #endif 235 | int compile_res = driver.ExecuteCompilation(*webc_compilation, failingCommands); 236 | if (compile_res < 0) { 237 | driver.generateCompilationDiagnostics(*webc_compilation, *failingCommand); 238 | return RERR; 239 | } 240 | long t2 = __getms(); 241 | LogInfo("编译完成"); 242 | LogInfo(to_string(t2 - t1).c_str()); 243 | LogInfo(outputPath); 244 | #endif 245 | return ROK; 246 | } 247 | 248 | int analysis(std::string *buf) { 249 | reset(); 250 | auto reader = new StringReader(buf); 251 | m_lexer = new Lexer(reader); 252 | // 放至全局变量 253 | TheLexer = m_lexer; 254 | int res = yyparse(); 255 | if (!res) { 256 | initExternFunc(); 257 | auto v = program->codegen(); 258 | if (v == nullptr) { 259 | res = 1; //正数失败 260 | } 261 | } 262 | delete reader; 263 | delete m_lexer; 264 | m_lexer = NIL; 265 | TheLexer = NIL; 266 | return !res ? ROK : RERR; 267 | } 268 | 269 | void reset() { 270 | Builder.reset(); 271 | TheModule.reset(); 272 | TheContext = std::make_unique(); 273 | Builder = std::make_unique>(*TheContext); 274 | TheModule = std::make_unique(APPNAME, *TheContext); 275 | TheCodeGenContext->reset(); 276 | } 277 | 278 | int build(std::string *buf, const char *outputPath, const std::set &opts) { 279 | if (analysis(buf) == ROK) { 280 | if (genCode(opts, outputPath) == ROK) { 281 | return ROK; 282 | } else { 283 | return RERR; 284 | } 285 | } 286 | return RERR; 287 | } 288 | 289 | #ifdef CLANG_SUPPORT 290 | const vector *getOpenSSLLibDir() { 291 | vector argv; 292 | auto pkgconfig = sys::findProgramByName("pkg-config"); 293 | if (auto ec = pkgconfig.getError()) { 294 | LogError(ec.message().c_str()); 295 | return nullptr; 296 | } 297 | argv.push_back(pkgconfig->c_str()); 298 | argv.push_back("openssl"); 299 | argv.push_back("--libs"); 300 | auto stdoutput = new string(); 301 | auto stderroutput = new string(); 302 | try { 303 | Glib::spawn_sync("", argv, Glib::SPAWN_DEFAULT, Glib::SlotSpawnChildSetup(), stdoutput, stderroutput); 304 | if (stderroutput->empty()) { 305 | boost::trim_right(*stdoutput); 306 | auto v = new vector(); 307 | boost::split(*v, *stdoutput, boost::is_any_of(" "), boost::token_compress_on); 308 | return v; 309 | } else { 310 | LogError("查找openssl库失败,请确保openssl库已加入系统环境变量"); 311 | LogError(stderroutput->c_str()); 312 | return nullptr; 313 | } 314 | } catch (Glib::SpawnError &err) { 315 | LogError(err.what().c_str()); 316 | return nullptr; 317 | } 318 | } 319 | 320 | #endif -------------------------------------------------------------------------------- /compiler/Compiler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/3/12. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_COMPILER_H 6 | #define SYSYPLUS_COMPILER_COMPILER_H 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include "args_parser.h" 13 | #include "Global.h" 14 | #include "ErrHelper.h" 15 | #include "pass/TimeAnalysisPass.h" 16 | #include "pass/RecursiveToLoopPass.h" 17 | #include "parser/FileReader.h" 18 | #include "parser/StringReader.h" 19 | #include "Global.h" 20 | #include "parser/Parser.hpp" 21 | 22 | extern Lexer *m_lexer; 23 | 24 | /// 终端输入 25 | 26 | int genCode(const set& opts, const char *outputPath); 27 | 28 | int startAnalyze(ArgsParser* parser); 29 | 30 | /// 可视化调用 31 | 32 | int analysis(std::string* buf); 33 | 34 | int build(std::string *buf, const char* outputPath,const std::set& opts); 35 | 36 | /** 37 | * 重置编译器 38 | */ 39 | void reset(); 40 | 41 | #endif //SYSYPLUS_COMPILER_COMPILER_H 42 | -------------------------------------------------------------------------------- /extern/ExternFunctionHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/4. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_EXTERNFUNCTIONHANDLER_H 6 | #define SYSYPLUS_COMPILER_EXTERNFUNCTIONHANDLER_H 7 | 8 | #include 9 | 10 | #include "Global.h" 11 | 12 | #define INTERNAL_IMPL 10 13 | #define USER_IMPL 100 14 | 15 | #define MIN_IMPL 0 16 | #define MAX_PRI 100 17 | 18 | using namespace llvm; 19 | 20 | class ExternFunctionHandler { 21 | private: 22 | public: 23 | ExternFunctionHandler(); 24 | 25 | virtual Value *tryhandle(LLVMContext &context, 26 | Module &module, std::string callName, std::vector *argV) = 0; 27 | 28 | static bool externFunctionHandlerCompRule(ExternFunctionHandler *handler1, ExternFunctionHandler *handler2); 29 | 30 | virtual int getPriority(); 31 | 32 | /** 33 | * 获取func 34 | * @param context 35 | * @param module 36 | * @param func_name 37 | * @param vector 38 | * @return 39 | */ 40 | static Function *getExternFunc(LLVMContext &context, Module &module, const std::string &func_name, 41 | std::vector *vector); 42 | 43 | static Function *getOrAddPrintfFunc(LLVMContext &context, Module &module); 44 | 45 | static Function *getOrAddTimeFunc(LLVMContext &context, Module &module); 46 | 47 | static Function *getOrAddSleepFunc(LLVMContext &context, Module &module); 48 | 49 | static Function *getOrAddGetSocketFunc(LLVMContext &context, Module &module); 50 | 51 | static Function *getOrAddConnectSocketFunc(LLVMContext &context, Module &module); 52 | 53 | static Function *getOrAddCloseSocketFunc(LLVMContext &context, Module &module); 54 | 55 | static Function *getOrAddIsSocketConnectedFunc(LLVMContext &context, Module &module); 56 | 57 | static Function *getOrAddGetRequestFunc(LLVMContext &context, Module &module); 58 | 59 | static Function *getOrAddPostRequestFunc(LLVMContext &context, Module &module); 60 | 61 | static Function *getOrAddGetServerFunc(LLVMContext &context, Module &module); 62 | 63 | static Function *getOrAddUrlHandler(LLVMContext &context, Module &module); 64 | 65 | static Function *getOrAddStartServer(LLVMContext &context, Module &module); 66 | 67 | static Function *getOrAddtoString(LLVMContext &context, Module &module); 68 | 69 | static Function *getOrAddConnectDB(LLVMContext &context, Module &module); 70 | 71 | static Function *getOrAddFreeMemory(LLVMContext &context, Module &module); 72 | 73 | static Function *getOrAddQueryDB(LLVMContext &context, Module &module); 74 | 75 | static Function *getOrAddIsMysqlConnected(LLVMContext &context, Module &module); 76 | }; 77 | 78 | 79 | class EchoFunctionHandler : public ExternFunctionHandler { 80 | 81 | public: 82 | EchoFunctionHandler(); 83 | 84 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 85 | 86 | int getPriority() override; 87 | }; 88 | 89 | class TimeFunctionHandler : public ExternFunctionHandler { 90 | public: 91 | int getPriority() override; 92 | 93 | TimeFunctionHandler(); 94 | 95 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 96 | }; 97 | 98 | class SleepFunctionHandler : public ExternFunctionHandler { 99 | public: 100 | int getPriority() override; 101 | 102 | SleepFunctionHandler(); 103 | 104 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 105 | }; 106 | 107 | class WebFunctionHandler : public ExternFunctionHandler { 108 | public: 109 | 110 | WebFunctionHandler(); 111 | 112 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 113 | 114 | int getPriority() override; 115 | }; 116 | 117 | class KStringFunctionHandler : public ExternFunctionHandler { 118 | public: 119 | 120 | KStringFunctionHandler(); 121 | 122 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 123 | 124 | int getPriority() override; 125 | }; 126 | 127 | class KsqlFunctionHandler : public ExternFunctionHandler { 128 | public: 129 | KsqlFunctionHandler(); 130 | 131 | Value *tryhandle(LLVMContext &context, Module &module, std::string callName, std::vector *argV) override; 132 | 133 | int getPriority() override; 134 | }; 135 | 136 | #endif //SYSYPLUS_COMPILER_EXTERNFUNCTIONHANDLER_H 137 | -------------------------------------------------------------------------------- /extern/ExternFunctionLinker.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/2/25. 3 | // 4 | 5 | #include "ExternFunctionLinker.h" 6 | 7 | std::vector ExternFunctionLinker::handlers; 8 | 9 | Value* ExternFunctionLinker::tryHandleFuncCall(LLVMContext &context, Module &module, const string &func_name, 10 | std::vector *vector) { 11 | for (ExternFunctionHandler* handler : handlers) { 12 | auto v = handler->tryhandle(context,module,func_name,vector); 13 | if (v != NIL){ 14 | return v; 15 | } 16 | } 17 | return NIL; 18 | } 19 | 20 | void ExternFunctionLinker::registerHandler(ExternFunctionHandler *handler) { 21 | if (handler != NIL && std::find(handlers.begin(),handlers.end(),handler) == handlers.end()) { 22 | handlers.push_back(handler); 23 | std::sort(handlers.begin(), handlers.end(), ExternFunctionHandler::externFunctionHandlerCompRule); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /extern/ExternFunctionLinker.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/2/25. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_EXTERNFUNCTIONLINKER_H 6 | #define SYSYPLUS_COMPILER_EXTERNFUNCTIONLINKER_H 7 | 8 | #include 9 | 10 | #include "Global.h" 11 | #include "ast/NodeAST.hpp" 12 | #include "ExternFunctionHandler.h" 13 | 14 | class ExternFunctionLinker { 15 | static std::vector handlers; 16 | public: 17 | 18 | /** 19 | * 注册外部函数Handler 20 | * @param handler 21 | */ 22 | static void registerHandler(ExternFunctionHandler* handler); 23 | 24 | /** 25 | * 尝试处理外部函数调用 26 | * @param context 27 | * @param module 28 | * @param func_name 29 | * @param vector 30 | * @return 成功返回non-nullptr 31 | */ 32 | static Value* tryHandleFuncCall(LLVMContext &context, Module &module, const std::string &func_name, 33 | std::vector* vector); 34 | }; 35 | 36 | #endif //SYSYPLUS_COMPILER_EXTERNFUNCTIONLINKER_H 37 | -------------------------------------------------------------------------------- /imgs/ide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kingtous/WebC-llvm-compiler/df85b1f8b6c6430b347d0f38daaa9f3f4dcad86f/imgs/ide.png -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "args_parser.h" 3 | #include "parser/Parser.hpp" 4 | #include "Global.h" 5 | #include "ui/widgets.h" 6 | #include "compiler/Compiler.h" 7 | 8 | using namespace llvm; 9 | 10 | #ifdef CGUI 11 | 12 | #include "ui/widgets.h" 13 | 14 | static void activate(GtkApplication *app, gpointer data); 15 | 16 | #endif 17 | 18 | int main(int argc, char **argv) { 19 | #ifdef CGUI 20 | return initWindow(argc, argv, "../ui/ui/main.glade", APPNAME); 21 | #else 22 | // Open a new module. 23 | auto args = ArgsParser::inst(argc, argv); 24 | if (args == NIL) { 25 | return RINVALID; 26 | } 27 | if (startAnalyze(args) == ROK) { 28 | if (genCode(args->getOpts(), args->getOutputPath().c_str()) == ROK) { 29 | return ROK; 30 | } else { 31 | errs() << "生成代码失败"; 32 | } 33 | } else { 34 | errs() << "分析失败"; 35 | } 36 | #endif 37 | return ROK; 38 | } -------------------------------------------------------------------------------- /module/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(KingtousCompilerModule) 3 | 4 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}) 5 | 6 | add_subdirectory(time) 7 | add_subdirectory(web) 8 | add_subdirectory(string) 9 | add_subdirectory(sql) 10 | add_subdirectory(json) -------------------------------------------------------------------------------- /module/README.md: -------------------------------------------------------------------------------- 1 | ### Modules For SysyPlus Compiler 2 | 3 | 编译方法: 4 | ```shell 5 | mkdir build && cd build 6 | cmake .. 7 | make 8 | make install 9 | ``` 10 | 11 | 编译完成后,库存放在module/lib内,为当前编译架构的目标文件 12 | 13 | 使用方法: 14 | 15 | ```shell 16 | g++ sysyplus源文件 xxx.module -o 可执行文件路径 17 | ``` -------------------------------------------------------------------------------- /module/json/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(KingtousProject) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | message(STATUS ${CMAKE_SOURCE_DIR}) 6 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/unknown) 7 | set(LOCATION "lib") 8 | 9 | #find_package(PkgConfig REQUIRED) 10 | #pkg_check_modules(JSONLib jsoncpp) 11 | #message(STATUS "json decl:${JSONLib_INCLUDE_DIRS}") 12 | #message(STATUS "json lib:${JSONLib_LIBRARY_DIRS}") 13 | #include_directories(${JSONLib_INCLUDE_DIRS}) 14 | #link_directories(${JSONLib_LIBRARY_DIRS}) 15 | 16 | message(STATUS "查找Boost框架 For PropertyTree") 17 | find_package(Boost REQUIRED) 18 | include_directories(${Boost_INCLUDE_DIR}) 19 | link_directories(${Boost_LIBRARY_DIR}) 20 | 21 | 22 | if (APPLE) 23 | message(STATUS "macOS detected") 24 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/mac) 25 | # set(CMAKE_C_FLAGS "-fPIC") 26 | # set(CMAKE_SHARED_LINKER_FLAGS "-fPIC") 27 | endif () 28 | 29 | if (UNIX) 30 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/linux) 31 | message(STATUS "unix detected") 32 | endif () 33 | 34 | aux_source_directory(src SRC) 35 | 36 | add_library(kjson STATIC ${SRC}) 37 | 38 | add_executable(kjsondemo ${SRC}) 39 | 40 | install(TARGETS kjson 41 | ARCHIVE DESTINATION ${LOCATION} 42 | LIBRARY DESTINATION ${LOCATION} 43 | ) -------------------------------------------------------------------------------- /module/json/src/kjson.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/23. 3 | // 4 | 5 | #include "kjson.h" 6 | 7 | namespace pt = 8 | boost::property_tree; 9 | 10 | SYSY_JSON_DATA strToJson(SYSY_STR str) { 11 | auto jd = new JsonData(); 12 | std::stringstream is; 13 | is << str; 14 | auto ptree = std::make_shared(); 15 | pt::read_json(is, *ptree); 16 | jd->pt = ptree; 17 | return jd; 18 | } 19 | 20 | SYSY_STR jsonToStr(SYSY_JSON_DATA json) { 21 | std::stringstream ss; 22 | pt::write_json(ss, *(json->pt), false); // 不要美化 23 | auto string = std::make_shared(ss.str()); 24 | return string->c_str(); 25 | } -------------------------------------------------------------------------------- /module/json/src/kjson.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/23. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_KJSON_H 6 | #define SYSYPLUS_COMPILER_KJSON_H 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | // TODO 之后改为const char* 13 | struct JsonData { 14 | std::shared_ptr pt; 15 | }; 16 | typedef JsonData *SYSY_JSON_DATA; 17 | typedef const char * SYSY_STR; 18 | 19 | extern "C" { 20 | 21 | /** 22 | * @brief string转json类 23 | * @param str string数据 24 | * @return json data 25 | */ 26 | SYSY_JSON_DATA strToJson(SYSY_STR str); 27 | 28 | 29 | /** 30 | * @brief json转string 31 | * @param json json数据 32 | * @return string 33 | */ 34 | SYSY_STR jsonToStr(SYSY_JSON_DATA json); 35 | 36 | 37 | 38 | } 39 | #endif //SYSYPLUS_COMPILER_KJSON_H 40 | -------------------------------------------------------------------------------- /module/json/src/kjsondemo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/23. 3 | // 4 | #include 5 | 6 | #include "kjson.h" 7 | using namespace std; 8 | int main() { 9 | // auto sz = sizeof(JsonData); 10 | SYSY_JSON_DATA data = strToJson("{\"hello\":123}"); 11 | // sz = sizeof(*data); 12 | // try { 13 | // auto tree = data->pt->get_child("hello2"); 14 | // } catch (boost::property_tree::ptree_bad_path &e) { 15 | // std::cout << e.what(); 16 | // } 17 | string mystring = jsonToStr(data); 18 | std::cout << "toString result :" << mystring; 19 | return 0; 20 | } -------------------------------------------------------------------------------- /module/sql/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(KingtousProject) 3 | set(CMAKE_CXX_STANDARD 14) 4 | 5 | message(STATUS ${CMAKE_SOURCE_DIR}) 6 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/unknown) 7 | set(LOCATION "lib") 8 | include_directories() 9 | link_directories() 10 | 11 | if (APPLE) 12 | message(STATUS "macOS detected") 13 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/mac) 14 | include_directories("/usr/local/Cellar/mysql-connector-c++/include") 15 | link_directories(/usr/local/Cellar/mysql-connector-c++/lib) 16 | # set(CMAKE_C_FLAGS "-fPIC") 17 | # set(CMAKE_SHARED_LINKER_FLAGS "-fPIC") 18 | endif () 19 | 20 | if (UNIX) 21 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/linux) 22 | message(STATUS "unix detected") 23 | endif () 24 | 25 | aux_source_directory(src SRC) 26 | 27 | message(STATUS "ksql files: ${SRC}") 28 | 29 | add_library(ksql STATIC src/ksql.cpp) 30 | 31 | add_executable(ksqldemo src/ksqldemo.cpp) 32 | 33 | target_link_libraries(ksqldemo kjson ksql mysqlcppconn) 34 | 35 | if (WIN32) 36 | target_link_libraries(ksqldemo ws2_32 secur32 mysqlclient) 37 | endif () 38 | 39 | install(TARGETS ksql 40 | ARCHIVE DESTINATION ${LOCATION} 41 | LIBRARY DESTINATION ${LOCATION} 42 | ) -------------------------------------------------------------------------------- /module/sql/src/ksql.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/20. 3 | // 4 | 5 | #include "ksql.h" 6 | 7 | #include 8 | 9 | #include "mysql_driver.h" 10 | #include "mysql_connection.h" 11 | #include "cppconn/statement.h" 12 | #include "cppconn/prepared_statement.h" 13 | #include "iostream" 14 | #include "module/json/src/kjson.h" 15 | #include "vector" 16 | 17 | //mysql连接状态码 18 | #define NOT_CONNECT -2 19 | #define FAILED -1 20 | //操作成功状态码 21 | #define SUCCESS 0 22 | 23 | //extern sql::mysql::MySQL_Driver * get_mysql_driver_instance(); 24 | 25 | using namespace std; 26 | 27 | struct SQLData { 28 | sql::Statement *statement; 29 | sql::ResultSet *resultSet; 30 | }; 31 | 32 | typedef SQLData WEBC_SQL_DATA; 33 | 34 | sql::mysql::MySQL_Driver *driver; 35 | sql::Connection *conn; 36 | WEBC_SQL_DATA webcSqlData; 37 | 38 | std::mutex mysql_mutex; 39 | 40 | string _ksql_resToJson(WEBC_SQL_DATA &sqlData); 41 | 42 | int _ksql_connect_db(const char *hostname, const char *username, const char *password, const char *schema, int port, 43 | const char *charset) { 44 | try { 45 | driver = sql::mysql::get_mysql_driver_instance(); 46 | //连接到Mysql 47 | sql::ConnectOptionsMap connection_properties; 48 | connection_properties["hostName"] = hostname; 49 | connection_properties["userName"] = username; 50 | connection_properties["password"] = password; 51 | connection_properties["schema"] = schema; 52 | connection_properties["port"] = port; 53 | connection_properties["OPT_RECONNECT"] = true; 54 | connection_properties["OPT_CHARSET_NAME"] = charset; 55 | conn = driver->connect(connection_properties); 56 | if (!conn) { 57 | cout << "连接Mysql失败" << endl; 58 | return FAILED; 59 | } 60 | return SUCCESS; 61 | } catch (sql::SQLException &e) { 62 | cout << "The error code is : " << e.getErrorCode() << endl; 63 | cout << e.what() << endl; 64 | } 65 | return FAILED; 66 | } 67 | 68 | const char *_ksql_query_db(const char *sqlSentence) { 69 | mysql_mutex.lock(); 70 | try { 71 | if (_ksql_isMysqlConnected() != 0) { 72 | return "mysql未能成功连接"; 73 | } 74 | _ksql_free_memory(); 75 | string temp = sqlSentence; 76 | replace(temp.begin(), temp.end(), '\"', '\''); 77 | webcSqlData.statement = conn->createStatement(); 78 | sqlSentence = temp.c_str(); 79 | webcSqlData.resultSet = webcSqlData.statement->executeQuery(sqlSentence); 80 | if (!webcSqlData.resultSet->next()) { 81 | return "您所查询的表为空\n"; 82 | } 83 | // FIXME: 会有内存泄露 84 | auto jsondata = _ksql_resToJson(webcSqlData); 85 | auto cstrdata = new string(jsondata); 86 | mysql_mutex.unlock(); 87 | return cstrdata->c_str(); 88 | } catch (sql::SQLException &e) { 89 | cout << "The error code is : " << e.getErrorCode() << endl; 90 | cout << e.what() << endl; 91 | mysql_mutex.unlock(); 92 | } 93 | return ""; 94 | } 95 | 96 | string _ksql_resToJson(WEBC_SQL_DATA &sqlData) { 97 | vector ans; 98 | try { 99 | string s; 100 | s += "{"; 101 | s += "\"result\":"; 102 | s += "["; 103 | //列数 104 | unsigned int count = sqlData.resultSet->getMetaData()->getColumnCount(); 105 | if (ans.empty()) { 106 | sqlData.resultSet->beforeFirst(); 107 | while (sqlData.resultSet->next()) { 108 | auto metadata = sqlData.resultSet->getMetaData(); 109 | string temp; 110 | for (int i = 1; i <= count; ++i) { 111 | if (i == 1) { 112 | temp += "{"; 113 | } 114 | temp += "\""; 115 | temp += metadata->getColumnLabel(i); 116 | temp += "\":"; 117 | auto type = metadata->getColumnTypeName(i); 118 | if (type == "VARCHAR") { 119 | temp += "\""; 120 | temp += sqlData.resultSet->getString(i); 121 | temp += "\""; 122 | } else { 123 | temp += sqlData.resultSet->getString(i); 124 | } 125 | if (i == count) temp += "}"; 126 | temp += ","; 127 | } 128 | ans.push_back(temp); 129 | } 130 | ans[ans.size() - 1].pop_back(); 131 | } 132 | for (const auto &str:ans) { 133 | s += str; 134 | } 135 | s += "]}"; 136 | return s; 137 | } catch (sql::SQLException &e) { 138 | cout << "The error code is : " << e.getErrorCode() << endl; 139 | cout << e.what() << endl; 140 | } 141 | return ""; 142 | } 143 | 144 | int _ksql_free_memory() { 145 | delete webcSqlData.resultSet; 146 | delete webcSqlData.statement; 147 | webcSqlData.resultSet = nullptr; 148 | webcSqlData.statement = nullptr; 149 | return SUCCESS; 150 | } 151 | 152 | int _ksql_isMysqlConnected() { 153 | return conn->isClosed() ? NOT_CONNECT : SUCCESS; 154 | } 155 | 156 | 157 | -------------------------------------------------------------------------------- /module/sql/src/ksql.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/20. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_KSQL_H 6 | #define SYSYPLUS_COMPILER_KSQL_H 7 | 8 | extern "C" { 9 | /** 10 | * 连接到MySQL 11 | * @param hostname 12 | * @param username 13 | * @param password 14 | * @param schema 15 | * @param port 端口 16 | * @param charset 字符集 17 | * @return 18 | */ 19 | int _ksql_connect_db(const char *hostname, const char *username, const char *password, const char *schema, int port,const char *charset); 20 | /** 21 | * 释放内存 22 | * @return 23 | */ 24 | int _ksql_free_memory(); 25 | /** 26 | * 查询数据 27 | * @param sqlSentence select语句 28 | * @return 29 | */ 30 | const char *_ksql_query_db(const char *sqlSentence); 31 | /** 32 | * 判断mysql是否连接 33 | * @return 34 | */ 35 | int _ksql_isMysqlConnected(); 36 | } 37 | 38 | #endif //SYSYPLUS_COMPILER_KSQL_H 39 | -------------------------------------------------------------------------------- /module/sql/src/ksqldemo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/20. 3 | // 4 | #include 5 | 6 | #include "ksql.h" 7 | 8 | int main() { 9 | _ksql_connect_db("39.107.226.2", "weather", "jintao123", "weather", 3306, "utf8"); 10 | // auto a = strToJson(_ksql_query_db("select * from subject")); 11 | // cout<(a); 11 | int tmp_num = *tmp; 12 | auto str = std::to_string(tmp_num); 13 | char *str_mem = new char[str.size() + 1]; 14 | memcpy(str_mem, str.c_str(), str.size() + 1); 15 | return str_mem; 16 | } 17 | case SYSYTYPE_DOUBLE: { 18 | auto *tmp = static_cast(a); 19 | auto tmp_num = *tmp; 20 | auto str = std::to_string(tmp_num); 21 | char *str_mem = new char[str.size() + 1]; 22 | memcpy(str_mem, str.c_str(), str.size() + 1); 23 | return str_mem; 24 | } 25 | case SYSYTYPE_LONG: { 26 | auto *tmp = static_cast(a); 27 | auto tmp_num = *tmp; 28 | auto str = std::to_string(tmp_num); 29 | char *str_mem = new char[str.size() + 1]; 30 | memcpy(str_mem, str.c_str(), str.size() + 1); 31 | return str_mem; 32 | } 33 | default: 34 | return "unknown type"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /module/string/src/kstring.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/18. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_KSTRING_H 6 | #define SYSYPLUS_COMPILER_KSTRING_H 7 | 8 | #include 9 | #include 10 | 11 | typedef int sysytype_t; 12 | 13 | #define SYSYTYPE_INT 0 14 | #define SYSYTYPE_LONG 1 15 | #define SYSYTYPE_DOUBLE 2 16 | 17 | extern "C" { 18 | /** 19 | * 转string 20 | * @param 变量地址 21 | * @param type 如上 22 | * @return 23 | */ 24 | const char *toString(void *a, sysytype_t type); 25 | }; 26 | 27 | #endif //SYSYPLUS_COMPILER_KSTRING_H 28 | -------------------------------------------------------------------------------- /module/time/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(KingtousProject) 3 | set(CMAKE_CXX_STANDARD 17) 4 | 5 | message(STATUS ${CMAKE_SOURCE_DIR}) 6 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/unknown) 7 | set(LOCATION "lib") 8 | 9 | if (APPLE) 10 | message(STATUS "macOS detected") 11 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/mac) 12 | # set(CMAKE_C_FLAGS "-fPIC") 13 | # set(CMAKE_SHARED_LINKER_FLAGS "-fPIC") 14 | endif () 15 | 16 | if (UNIX) 17 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/linux) 18 | message(STATUS "unix detected") 19 | endif () 20 | 21 | aux_source_directory(src SRC) 22 | 23 | add_library(ktime STATIC ${SRC}) 24 | 25 | 26 | install(TARGETS ktime 27 | ARCHIVE DESTINATION ${LOCATION} 28 | LIBRARY DESTINATION ${LOCATION} 29 | ) -------------------------------------------------------------------------------- /module/time/src/time.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/2/26. 3 | // 4 | 5 | #ifdef WIN32 6 | #include 7 | #include 8 | #else 9 | 10 | #include 11 | 12 | #endif 13 | 14 | #ifdef WIN32 15 | int gettimeofday(struct timeval* tp, void* tzp) 16 | { 17 | time_t clock; 18 | struct tm tm; 19 | SYSTEMTIME wtm; 20 | GetLocalTime(&wtm); 21 | tm.tm_year = wtm.wYear - 1900; 22 | tm.tm_mon = wtm.wMonth - 1; 23 | tm.tm_mday = wtm.wDay; 24 | tm.tm_hour = wtm.wHour; 25 | tm.tm_min = wtm.wMinute; 26 | tm.tm_sec = wtm.wSecond; 27 | tm.tm_isdst = -1; 28 | clock = mktime(&tm); 29 | tp->tv_sec = clock; 30 | tp->tv_usec = wtm.wMilliseconds * 1000; 31 | return (0); 32 | } 33 | #endif 34 | 35 | /** 36 | * 获取ms数 37 | * @return ms 38 | */ 39 | long __getms() { 40 | struct timeval tp; 41 | gettimeofday(&tp, 0); 42 | long ms = tp.tv_sec * 1000 + tp.tv_usec / 1000; 43 | return ms; 44 | } 45 | -------------------------------------------------------------------------------- /module/web/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | project(KingtousProject) 3 | message(STATUS "configuring KingtousProject-Web模块") 4 | set(CMAKE_BUILD_TYPE Release) 5 | 6 | set(CMAKE_CXX_STANDARD 14) 7 | 8 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/unknown) 9 | set(LOCATION "lib") 10 | 11 | find_package(PkgConfig REQUIRED) 12 | pkg_check_modules(SSLLib openssl) 13 | message(STATUS "found ssl lib in ${SSLLib_INCLUDE_DIRS}") 14 | message(STATUS "found ssl lib in ${SSLLib_LIBRARY_DIRS}") 15 | include_directories(${SSLLib_INCLUDE_DIRS}) 16 | link_directories(${SSLLib_LIBRARY_DIRS}) 17 | 18 | # Boost 19 | message(STATUS "查找Boost框架") 20 | find_package(Boost COMPONENTS system filesystem REQUIRED) 21 | include_directories(${Boost_INCLUDE_DIR}) 22 | link_directories(${Boost_LIBRARY_DIR}) 23 | 24 | if (APPLE) 25 | message(STATUS "macOS detected") 26 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/mac) 27 | # set(CMAKE_C_FLAGS "-fPIC") 28 | # set(CMAKE_SHARED_LINKER_FLAGS "-fPIC") 29 | endif () 30 | 31 | if (UNIX) 32 | set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/obj/x86_64/linux) 33 | message(STATUS "unix detected") 34 | endif () 35 | 36 | #aux_source_directory(src SRC) 37 | 38 | add_library(kweb STATIC src/web.hpp src/web.cpp) 39 | 40 | add_executable(webdemo src/webdemo.cpp src/web.hpp src/web.cpp) 41 | 42 | add_executable(serverdemo src/serverdemo.cpp src/web.hpp src/web.cpp) 43 | 44 | target_link_libraries(webdemo Boost::filesystem Boost::system pthread ${SSLLib_LIBRARIES} ksql kjson mysqlcppconn ) 45 | 46 | target_link_libraries(serverdemo Boost::filesystem Boost::system pthread ${SSLLib_LIBRARIES} ksql kjson mysqlcppconn ) 47 | 48 | if(WIN32) 49 | target_link_libraries(webdemo wsock32 ws2_32) 50 | 51 | target_link_libraries(serverdemo wsock32 ws2_32) 52 | 53 | endif() 54 | 55 | install(TARGETS kweb 56 | ARCHIVE DESTINATION ${LOCATION} 57 | LIBRARY DESTINATION ${LOCATION} 58 | ) -------------------------------------------------------------------------------- /module/web/cert/ca.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDmTCCAoECFDW66CGdWzzHmQ3a2kyYh4+/aaabMA0GCSqGSIb3DQEBCwUAMIGI 3 | MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdYaTEPMA0GA1UEBwwGWWlDaHVu 4 | MREwDwYDVQQKDAhLaW5ndG91czERMA8GA1UECwwIS2luZ3RvdXMxETAPBgNVBAMM 5 | CEtpbmd0b3VzMR0wGwYJKoZIhvcNAQkBFg5tZUBraW5ndG91cy5jbjAeFw0yMTAz 6 | MjAxMzAzNThaFw0zMTAzMTgxMzAzNThaMIGIMQswCQYDVQQGEwJDTjEQMA4GA1UE 7 | CAwHSmlhbmdYaTEPMA0GA1UEBwwGWWlDaHVuMREwDwYDVQQKDAhLaW5ndG91czER 8 | MA8GA1UECwwIS2luZ3RvdXMxETAPBgNVBAMMCEtpbmd0b3VzMR0wGwYJKoZIhvcN 9 | AQkBFg5tZUBraW5ndG91cy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 10 | ggEBAL5+tF42E/cvtz/qRb1/n8DZZFDIGWDDc7LufVXPtrKj9YJC4MCMGkWHxeyE 11 | 0GGlO0UnrIYmBqvPB9MEfnvi59j/l5aWzIy1FLqe9pHfG0OUeTBOLR4ZIp3hB41K 12 | NspQ9+LGJH2GVvGsW5+5Xz72xBxzCdn/MlRF3qJUd9kbK6HsqppMbC8ohCuJ84ac 13 | O3Fv3Hk2+e++eJof0mQL2Nq6dX1yByxli6NL8c6bSOWVuoTcSLAx/yjNvt9b14gq 14 | Sj3Ngvufm6WfMb/bLJ5WS9QxmiomecqLJU6Q2hncGxISsp/zgr9prvOJixpErtS1 15 | SC3XZoAXk5VHZLj1n6Xg3E5cUcECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEALw/Q 16 | hzK+LfnoYUtFrgfEc6LXRlIdKVsc2yYGcsaHrUctkH+7A2U+TmokIFR23wETbgd7 17 | SXwWi6lBMa+mKi4uAFTpI0Y/TteTRCy9d0Al1t8/FJ962N/4EWpDgh+mNYAiQI4i 18 | hyuuNnuZz038m2nyHmQj19d5mb5YSFfZooo3LYzlndUzYLLhjU6lwcqOsA1Sqz0/ 19 | CvIGiLuj6FpHxP5caUcDT4hHZ9aJHOkYubqwXRqgnkPLKBs0vNc6yQKaqrS9w5JJ 20 | yfNWzLIt25F+NS1l+enfOVnt6nvfBkE6up4+64THbK/Pfnc+6cKrpaGpybT+BD7J 21 | 0K9q3puHodE2tiRDJA== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /module/web/cert/ca.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC/TCCAeUCAQAwgYgxCzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdKaWFuZ1hpMQ8w 3 | DQYDVQQHDAZZaUNodW4xETAPBgNVBAoMCEtpbmd0b3VzMREwDwYDVQQLDAhLaW5n 4 | dG91czERMA8GA1UEAwwIS2luZ3RvdXMxHTAbBgkqhkiG9w0BCQEWDm1lQGtpbmd0 5 | b3VzLmNuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvn60XjYT9y+3 6 | P+pFvX+fwNlkUMgZYMNzsu59Vc+2sqP1gkLgwIwaRYfF7ITQYaU7RSeshiYGq88H 7 | 0wR+e+Ln2P+XlpbMjLUUup72kd8bQ5R5ME4tHhkineEHjUo2ylD34sYkfYZW8axb 8 | n7lfPvbEHHMJ2f8yVEXeolR32RsroeyqmkxsLyiEK4nzhpw7cW/ceTb57754mh/S 9 | ZAvY2rp1fXIHLGWLo0vxzptI5ZW6hNxIsDH/KM2+31vXiCpKPc2C+5+bpZ8xv9ss 10 | nlZL1DGaKiZ5yoslTpDaGdwbEhKyn/OCv2mu84mLGkSu1LVILddmgBeTlUdkuPWf 11 | peDcTlxRwQIDAQABoC8wFAYJKoZIhvcNAQkHMQcMBWp0MTIzMBcGCSqGSIb3DQEJ 12 | AjEKDAhLaW5ndG91czANBgkqhkiG9w0BAQsFAAOCAQEACK8hJWt3pDh/jSUjRsxy 13 | /e3wMNoFz9S800p8A2qFjdzS6c9C1q4oveolOm7gqzpxhZzmm+RATC93Re4chKbY 14 | 2pV6loignr6PTAUTBZtZxVCZU3BC5rhZRzZnhxMys7kK2s0HoMGzCvw1mCQqW2ol 15 | 6auJJNS0TpMwOqn6yyZUYh51HHU2aohABfwLt+CqJvO6HD7by7IiN8qKogGCsdZG 16 | tJZEVd8hCM5j7UQLdhdJmMMIY/0X+w9Hu4rcma4l6bQANEPQMahmwEelp39F7JtV 17 | lMq5sygR1eyi6NVzwBH6xgbmzQtf9NMyfYiznOlUwGBVDt5s5I5lBKTO4grUGnua 18 | mw== 19 | -----END CERTIFICATE REQUEST----- 20 | -------------------------------------------------------------------------------- /module/web/cert/ca.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEpAIBAAKCAQEAvn60XjYT9y+3P+pFvX+fwNlkUMgZYMNzsu59Vc+2sqP1gkLg 3 | wIwaRYfF7ITQYaU7RSeshiYGq88H0wR+e+Ln2P+XlpbMjLUUup72kd8bQ5R5ME4t 4 | HhkineEHjUo2ylD34sYkfYZW8axbn7lfPvbEHHMJ2f8yVEXeolR32Rsroeyqmkxs 5 | LyiEK4nzhpw7cW/ceTb57754mh/SZAvY2rp1fXIHLGWLo0vxzptI5ZW6hNxIsDH/ 6 | KM2+31vXiCpKPc2C+5+bpZ8xv9ssnlZL1DGaKiZ5yoslTpDaGdwbEhKyn/OCv2mu 7 | 84mLGkSu1LVILddmgBeTlUdkuPWfpeDcTlxRwQIDAQABAoIBAQCTvBwR/IqbZ4wM 8 | q5mOj03L+EzOQYE9BBfUqxTU2hRskq+yaD951K4DQnsDJTWepNBEn7IzD4aY9CSz 9 | SIb3eVApgH+FsEnOzhjXarT7CDZSwPEDv31KHGA2ZPDAaM/5M7YrT1O5bdg78VnV 10 | k6QEZshM8AKx6DKWHOG+rxeLboD2QAcqnf4pWv8dGxSwkFFK4//rDflm6FXmduol 11 | +P0S9D2fVv0k89O7/MBc4MOlnKLfPG3IVBXS/fc9zq41tW1oqDnq0fZXozwthshO 12 | GThOSpIcFSR9u5j0Mq91DFtGBUWLvgkH7mmkkrzLkCzCOAbwsKobzCrZ+dR6oZnl 13 | RYJPmHpJAoGBAPMa/jAIgV3bxu2PzNAqQ99SzTq3SmTSiPtBWY/wcnNfBNKAWyVe 14 | YEaoOBIQSiU5R9fqsaQKylcu49Z3akKzog10kZ7HWkwQP7y2AVWEmmXIc8ASLJBf 15 | jdufz9ZLl6NB8fStqKnnNR60qu/eduqFXC1oKbaOR+6v/s4DxhRIC64LAoGBAMiZ 16 | VwkNDNR+T5S/tnUajzrQso54Uj8AWYoeVsLTcqrAtX3JUdPrzqURP1wSxd0uVGXJ 17 | l4jTY6WaTBVPtjt39/hZEb/axAGyX2EYTf/QEJGzNRCPZlXAzlTCIqux+mwrh4ow 18 | 8dF8kVdxOw15Mj3SbgM1IY7I+0ISuZvvxmMPx7rjAoGAUB7CTVRQRn2rVxoAd06m 19 | pdBlQQetZgMZEC2eddjZ73oOXc3dvDgZZNAGArYJqbDyI4/+0cCYpRkYD9O1WpxX 20 | OTYE1B6BfPYR+4DEecnFFOx2cYPL2h0T5KEL32V0aWLPekNNhglkMWV7vKhF6s7e 21 | 7TwaG0dTH7AzOvR1cLO53bcCgYEAmg/SnXvtV6GuwwI+Qk/kovo3uF3GZOaC3iYQ 22 | 4k59KZEZkoK0mrrnGTVW4QL1/bogTZB3FjmrtTr8pf1zatbnlk/p5txAX0E8KZj+ 23 | BrMolo34+j/4C3IpxUTYVd86AiuoTETs48P06CBphx6GrJ5ZqZL7s+q9tfAlpxKO 24 | 3fP3pJsCgYB0tPVCMj0QBRFVwMPDyoxi3y5x9TdOI/oU/pYI/8RdH2IWAm1XX1Cl 25 | 8I2aq3JlEmiaG02FsD3PDX0ZOCAb3WAyIQL+L7IY3TtkpB0eHaAglp1YyfDJA+sE 26 | EgGFdAP06mSRUK2htokQdRoSzkSitpUE4t+Vb5i5lTBNAAuWXS5GPg== 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /module/web/cert/ca.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDmTCCAoECFDW66CGdWzzHmQ3a2kyYh4+/aaabMA0GCSqGSIb3DQEBCwUAMIGI 3 | MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdYaTEPMA0GA1UEBwwGWWlDaHVu 4 | MREwDwYDVQQKDAhLaW5ndG91czERMA8GA1UECwwIS2luZ3RvdXMxETAPBgNVBAMM 5 | CEtpbmd0b3VzMR0wGwYJKoZIhvcNAQkBFg5tZUBraW5ndG91cy5jbjAeFw0yMTAz 6 | MjAxMzAzNThaFw0zMTAzMTgxMzAzNThaMIGIMQswCQYDVQQGEwJDTjEQMA4GA1UE 7 | CAwHSmlhbmdYaTEPMA0GA1UEBwwGWWlDaHVuMREwDwYDVQQKDAhLaW5ndG91czER 8 | MA8GA1UECwwIS2luZ3RvdXMxETAPBgNVBAMMCEtpbmd0b3VzMR0wGwYJKoZIhvcN 9 | AQkBFg5tZUBraW5ndG91cy5jbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 10 | ggEBAL5+tF42E/cvtz/qRb1/n8DZZFDIGWDDc7LufVXPtrKj9YJC4MCMGkWHxeyE 11 | 0GGlO0UnrIYmBqvPB9MEfnvi59j/l5aWzIy1FLqe9pHfG0OUeTBOLR4ZIp3hB41K 12 | NspQ9+LGJH2GVvGsW5+5Xz72xBxzCdn/MlRF3qJUd9kbK6HsqppMbC8ohCuJ84ac 13 | O3Fv3Hk2+e++eJof0mQL2Nq6dX1yByxli6NL8c6bSOWVuoTcSLAx/yjNvt9b14gq 14 | Sj3Ngvufm6WfMb/bLJ5WS9QxmiomecqLJU6Q2hncGxISsp/zgr9prvOJixpErtS1 15 | SC3XZoAXk5VHZLj1n6Xg3E5cUcECAwEAATANBgkqhkiG9w0BAQsFAAOCAQEALw/Q 16 | hzK+LfnoYUtFrgfEc6LXRlIdKVsc2yYGcsaHrUctkH+7A2U+TmokIFR23wETbgd7 17 | SXwWi6lBMa+mKi4uAFTpI0Y/TteTRCy9d0Al1t8/FJ962N/4EWpDgh+mNYAiQI4i 18 | hyuuNnuZz038m2nyHmQj19d5mb5YSFfZooo3LYzlndUzYLLhjU6lwcqOsA1Sqz0/ 19 | CvIGiLuj6FpHxP5caUcDT4hHZ9aJHOkYubqwXRqgnkPLKBs0vNc6yQKaqrS9w5JJ 20 | yfNWzLIt25F+NS1l+enfOVnt6nvfBkE6up4+64THbK/Pfnc+6cKrpaGpybT+BD7J 21 | 0K9q3puHodE2tiRDJA== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /module/web/cert/demoCA/index.txt: -------------------------------------------------------------------------------- 1 | V 220320130728Z 01 unknown /C=CN/ST=JiangXi/O=Kingtous/OU=Kingtous/CN=Kingtous/emailAddress=me@kingtous.cn 2 | -------------------------------------------------------------------------------- /module/web/cert/demoCA/index.txt.attr: -------------------------------------------------------------------------------- 1 | unique_subject = yes 2 | -------------------------------------------------------------------------------- /module/web/cert/demoCA/index.txt.old: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kingtous/WebC-llvm-compiler/df85b1f8b6c6430b347d0f38daaa9f3f4dcad86f/module/web/cert/demoCA/index.txt.old -------------------------------------------------------------------------------- /module/web/cert/demoCA/newcerts/01.pem: -------------------------------------------------------------------------------- 1 | Certificate: 2 | Data: 3 | Version: 3 (0x2) 4 | Serial Number: 1 (0x1) 5 | Signature Algorithm: sha256WithRSAEncryption 6 | Issuer: C=CN, ST=JiangXi, L=YiChun, O=Kingtous, OU=Kingtous, CN=Kingtous/emailAddress=me@kingtous.cn 7 | Validity 8 | Not Before: Mar 20 13:07:28 2021 GMT 9 | Not After : Mar 20 13:07:28 2022 GMT 10 | Subject: C=CN, ST=JiangXi, O=Kingtous, OU=Kingtous, CN=Kingtous/emailAddress=me@kingtous.cn 11 | Subject Public Key Info: 12 | Public Key Algorithm: rsaEncryption 13 | RSA Public-Key: (1024 bit) 14 | Modulus: 15 | 00:b7:e6:48:96:3d:87:37:2e:ce:47:fa:c5:fc:21: 16 | 2d:8c:1a:64:c0:7a:55:10:c5:70:af:99:97:bb:6c: 17 | 3a:b1:b3:ff:c7:68:7e:04:70:a1:a1:5c:77:61:75: 18 | 85:07:f5:de:5b:b0:ea:dd:b7:1a:b7:65:bc:1b:75: 19 | 5b:d1:70:97:fc:c7:ae:8e:98:56:d6:c6:c2:0b:9e: 20 | a4:f1:56:ee:c2:82:e7:aa:05:4d:5a:f0:36:9d:8c: 21 | ea:47:3f:7d:5f:33:73:f1:a1:38:13:c8:f7:c5:9e: 22 | f9:8e:3e:f5:4c:b8:2a:9c:58:b4:9c:1b:b5:86:b6: 23 | fc:fb:78:7d:6e:46:d4:83:4b 24 | Exponent: 65537 (0x10001) 25 | X509v3 extensions: 26 | X509v3 Basic Constraints: 27 | CA:FALSE 28 | Netscape Comment: 29 | OpenSSL Generated Certificate 30 | X509v3 Subject Key Identifier: 31 | E0:62:CE:20:7D:32:89:C7:43:5E:85:97:78:7D:5D:33:AE:F2:DE:12 32 | X509v3 Authority Key Identifier: 33 | DirName:/C=CN/ST=JiangXi/L=YiChun/O=Kingtous/OU=Kingtous/CN=Kingtous/emailAddress=me@kingtous.cn 34 | serial:35:BA:E8:21:9D:5B:3C:C7:99:0D:DA:DA:4C:98:87:8F:BF:69:A6:9B 35 | 36 | Signature Algorithm: sha256WithRSAEncryption 37 | 15:7c:54:d6:e5:71:e1:55:ef:40:1b:fd:d9:29:cf:e0:73:3f: 38 | f1:39:6d:16:56:de:d6:b4:5e:30:ca:80:2c:bf:05:96:8c:9a: 39 | 01:e2:bc:09:19:1c:93:b2:a8:41:3e:00:f4:d9:db:ca:7c:ed: 40 | cd:9a:8b:64:67:48:e1:7f:27:db:49:e9:37:69:b7:ed:e6:e5: 41 | 09:6e:70:87:52:62:6f:08:90:bf:db:95:bc:29:26:1c:fd:22: 42 | 31:a4:29:52:ad:2e:4c:5d:3f:92:11:55:04:d7:89:6f:1c:21: 43 | 1b:53:9a:c8:e2:ed:21:62:23:89:61:25:c5:94:ab:7c:01:04: 44 | f0:e0:12:34:e1:cf:b1:c9:e7:f8:6d:f4:cc:14:86:5f:12:1f: 45 | 7f:d9:63:5b:2f:9f:4b:04:e1:24:73:3f:ef:e7:79:6b:86:48: 46 | 5c:f5:9e:c1:5c:d6:f6:f0:ff:36:7a:41:56:02:dc:1e:5b:7f: 47 | 84:e2:3f:4d:d7:73:37:5f:28:34:f0:93:f4:28:dd:92:99:fa: 48 | 06:52:e7:99:89:05:78:25:f7:6d:fe:af:11:ff:d8:49:10:a2: 49 | f4:27:82:d5:ad:a8:af:67:e9:ef:84:00:2b:cf:cd:79:bd:61: 50 | 8d:bb:ce:b1:02:f4:2d:f2:b5:c8:ed:e6:d9:5b:b6:c7:d2:cf: 51 | 95:7c:85:85 52 | -----BEGIN CERTIFICATE----- 53 | MIIECjCCAvKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCQ04x 54 | EDAOBgNVBAgMB0ppYW5nWGkxDzANBgNVBAcMBllpQ2h1bjERMA8GA1UECgwIS2lu 55 | Z3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5ndG91czEdMBsG 56 | CSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24wHhcNMjEwMzIwMTMwNzI4WhcNMjIw 57 | MzIwMTMwNzI4WjB3MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdYaTERMA8G 58 | A1UECgwIS2luZ3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5n 59 | dG91czEdMBsGCSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24wgZ8wDQYJKoZIhvcN 60 | AQEBBQADgY0AMIGJAoGBALfmSJY9hzcuzkf6xfwhLYwaZMB6VRDFcK+Zl7tsOrGz 61 | /8dofgRwoaFcd2F1hQf13luw6t23GrdlvBt1W9Fwl/zHro6YVtbGwguepPFW7sKC 62 | 56oFTVrwNp2M6kc/fV8zc/GhOBPI98We+Y4+9Uy4KpxYtJwbtYa2/Pt4fW5G1INL 63 | AgMBAAGjggERMIIBDTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM 64 | IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU4GLOIH0yicdDXoWXeH1d 65 | M67y3hIwgbIGA1UdIwSBqjCBp6GBjqSBizCBiDELMAkGA1UEBhMCQ04xEDAOBgNV 66 | BAgMB0ppYW5nWGkxDzANBgNVBAcMBllpQ2h1bjERMA8GA1UECgwIS2luZ3RvdXMx 67 | ETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5ndG91czEdMBsGCSqGSIb3 68 | DQEJARYObWVAa2luZ3RvdXMuY26CFDW66CGdWzzHmQ3a2kyYh4+/aaabMA0GCSqG 69 | SIb3DQEBCwUAA4IBAQAVfFTW5XHhVe9AG/3ZKc/gcz/xOW0WVt7WtF4wyoAsvwWW 70 | jJoB4rwJGRyTsqhBPgD02dvKfO3NmotkZ0jhfyfbSek3abft5uUJbnCHUmJvCJC/ 71 | 25W8KSYc/SIxpClSrS5MXT+SEVUE14lvHCEbU5rI4u0hYiOJYSXFlKt8AQTw4BI0 72 | 4c+xyef4bfTMFIZfEh9/2WNbL59LBOEkcz/v53lrhkhc9Z7BXNb28P82ekFWAtwe 73 | W3+E4j9N13M3Xyg08JP0KN2SmfoGUueZiQV4Jfdt/q8R/9hJEKL0J4LVraivZ+nv 74 | hAArz815vWGNu86xAvQt8rXI7ebZW7bH0s+VfIWF 75 | -----END CERTIFICATE----- 76 | -------------------------------------------------------------------------------- /module/web/cert/demoCA/serial: -------------------------------------------------------------------------------- 1 | 02 2 | -------------------------------------------------------------------------------- /module/web/cert/demoCA/serial.old: -------------------------------------------------------------------------------- 1 | 01 2 | 3 | -------------------------------------------------------------------------------- /module/web/cert/server.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDhTCCAm0CFB6C9HfrypjV3phwViMQr9kX8tm+MA0GCSqGSIb3DQEBCwUAMH8x 3 | CzAJBgNVBAYTAkNOMQswCQYDVQQIDAJDTjELMAkGA1UEBwwCQ04xETAPBgNVBAoM 4 | CEtpbmd0b3VzMREwDwYDVQQLDAhLaW5ndG91czERMA8GA1UEAwwIS2luZ3RvdXMx 5 | HTAbBgkqhkiG9w0BCQEWDm1lQGtpbmd0b3VzLmNuMB4XDTIxMDMyODE1MjM0NVoX 6 | DTIyMDMyODE1MjM0NVowfzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkNOMQswCQYD 7 | VQQHDAJDTjERMA8GA1UECgwIS2luZ3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREw 8 | DwYDVQQDDAhLaW5ndG91czEdMBsGCSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24w 9 | ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFWLlHETMNWfEisX5+5pRF 10 | tCNzi5wetRzuhnR7lR+uN98FgDtFE5oWQzJ6ocLJ7HJbS5/hpLDMMcC67fvbT/9Q 11 | 2T5GrGa/4C+ewa/rzYf3K0Q1y3ioY8NPD03IXHqzgjqqp+IetnjWK9XQMhSTPkVg 12 | d3BOMkFduQGHvfKyGGGXc+uL7mMEBPgKAC6PYFgmGTkZ9ZLbScHZvxvH5R/feOJ2 13 | Y1pXb2Stfrxhiuy9n8m+6gzA9FIM6eQIooOJdF9IqYNbfGZ8Obto47KI3KI6PpfV 14 | z9x4mk7DSveVrDnkunnOWkpIQUtlxT7y6oWUjFqwyTbCATCtpPyF8iY4kwj+jOjP 15 | AgMBAAEwDQYJKoZIhvcNAQELBQADggEBAFgcoMlXsJqaoH9lAy+5vozKuXESU309 16 | CoUTf/shp4SdOrfTMS6R7zmy7E06uHURNUiOHgpMScgojQmGUkBH2myDUK4fzALP 17 | Bxuq6P/ntqj/4G/oGQ45cILzyK48rtzZNXiQxRcjwwOOYilriepVVpSVqwyIBAbA 18 | vzSi1M22u7sxKf5e/33mkAD8kyAiPBfNQqN3LVNbS5Yz18ZhYc8d4Y+xHIvQJCkI 19 | qbcd2NyX3sv9OCkTpjmqBvdfzkH+a/Qnb+evemwNBPYcYJkn0CkWXyETPg9KgRfb 20 | noJsD01zYWXTP60gu8IGgeoCix4sYjdPjBInylLBAyKQEBzBxyE0LG0= 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /module/web/cert/server.csr: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE REQUEST----- 2 | MIIC8DCCAdgCAQAwfzELMAkGA1UEBhMCQ04xCzAJBgNVBAgMAkNOMQswCQYDVQQH 3 | DAJDTjERMA8GA1UECgwIS2luZ3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREwDwYD 4 | VQQDDAhLaW5ndG91czEdMBsGCSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24wggEi 5 | MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFWLlHETMNWfEisX5+5pRFtCNz 6 | i5wetRzuhnR7lR+uN98FgDtFE5oWQzJ6ocLJ7HJbS5/hpLDMMcC67fvbT/9Q2T5G 7 | rGa/4C+ewa/rzYf3K0Q1y3ioY8NPD03IXHqzgjqqp+IetnjWK9XQMhSTPkVgd3BO 8 | MkFduQGHvfKyGGGXc+uL7mMEBPgKAC6PYFgmGTkZ9ZLbScHZvxvH5R/feOJ2Y1pX 9 | b2Stfrxhiuy9n8m+6gzA9FIM6eQIooOJdF9IqYNbfGZ8Obto47KI3KI6PpfVz9x4 10 | mk7DSveVrDnkunnOWkpIQUtlxT7y6oWUjFqwyTbCATCtpPyF8iY4kwj+jOjPAgMB 11 | AAGgLDAUBgkqhkiG9w0BCQIxBwwFanQxMjMwFAYJKoZIhvcNAQkHMQcMBWp0MTIz 12 | MA0GCSqGSIb3DQEBCwUAA4IBAQBpvbuXu3+MsJ3AK7hkJMJgIouGsHMXmfnqhdFN 13 | HJNoB9rg8I836x4n6NdarXjNfp9jr7nKb69oOGp+w45GTyJxGysx9Prn7c6UPbDO 14 | 8JJIxYdeEe3BUq8sI9lfHWmz6ktejtWuCEgzWVmmiGPDbtxocTwZdH0+nfUcI6u5 15 | hLidiA/p4VBkmm4Ivm7UY5LZuFcdoRwUuA0QlnFDrk2i2p1x+zsn1QDnrMSQoEos 16 | uWgaK3ikXJAzX+jZjz+vQWzI9ETtSKXEzcm2z0Bq0NkGP+alnn2g1VSjXjx0aBpx 17 | SQeOiWLyynr6PILt8+6h+xNk74HUUUmCrwvHBbtngoOzicxB 18 | -----END CERTIFICATE REQUEST----- 19 | -------------------------------------------------------------------------------- /module/web/cert/server.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEowIBAAKCAQEAxVi5RxEzDVnxIrF+fuaURbQjc4ucHrUc7oZ0e5UfrjffBYA7 3 | RROaFkMyeqHCyexyW0uf4aSwzDHAuu3720//UNk+Rqxmv+AvnsGv682H9ytENct4 4 | qGPDTw9NyFx6s4I6qqfiHrZ41ivV0DIUkz5FYHdwTjJBXbkBh73yshhhl3Pri+5j 5 | BAT4CgAuj2BYJhk5GfWS20nB2b8bx+Uf33jidmNaV29krX68YYrsvZ/JvuoMwPRS 6 | DOnkCKKDiXRfSKmDW3xmfDm7aOOyiNyiOj6X1c/ceJpOw0r3law55Lp5zlpKSEFL 7 | ZcU+8uqFlIxasMk2wgEwraT8hfImOJMI/ozozwIDAQABAoIBAQCq1GnWHgpeZVw6 8 | lwEUIs95Iz2I+PJVFpyL0fIlRGpfKlgxb9ZermA1I0ggJcTzfG1loCovbpvotqzK 9 | Y9Yf+7jcqKGjFfv/3rX6LFn3ujwXdumd05uH0Iwx9OJ1LbC9kV7teVRhF720T8/P 10 | YHq1FzOBFQMvfYtd8RdlBMWA62AXdCgubezHd7xcoVagZkosEZe+bTTVS9IOwu04 11 | tSxDKhLL2mOwxZJl31zvKDSX1ifdec2YEIPLKA3wEbUkWpXbgiHd2cTAPELrYWqV 12 | t0ZABHdhUdvTA4FjCux+P+TZeT1KeGBrsjCOxgdNkPGq2KSKql4vwagvhtBlSlww 13 | ZTp763IhAoGBAO802GvWi4C98lJRB5dvnKpNn+GSl7Mv273moBegoSQQOA9MIdvx 14 | 5Vbo20CH+WrzLBivrgjpyniOzsgSx+jNz0ZpwkrnMgKsd/OEtfRJPTdzINUuL3ws 15 | D5RHL56H2VMae5FMUEGloGjOAHPYUZ0L5egohy02uTYY0xcTvZpiCTTRAoGBANMz 16 | jJgmsJilwoy2JBtq3wo70kXqS4tv0jEvYAowWNVtRV+B+f9cTN+1dvuksfks7Nsz 17 | Fh6hdebkkosckZ8R0tOpoczyZzumhSSOcnHkVwpcFK+bwQhXahqJbp4b+bfqvUIZ 18 | 85vsx3Vf/JZudrcKdxoVCzRKChhYnO3pBdj1FiufAoGASWDkovAFi1C5bRb+RS4v 19 | 2O5HBWN6tbUQq4h7w8O6qt1u1QJ9wILL34U+/OS5Vl2SQWBi+sj9G05zkFxyhq/b 20 | zbXTrDaP2NIfWcx0JKPy63edssegOW8quEm+CduShzOwhDnsxLaSJpRK/z50isCD 21 | nlwQW4ZV+opS9tlPaHR6boECgYBzwBbX9KxonMBJejHDzQi8hRizNLt+iiR6zGoo 22 | a2LkZeTVeVjYeW+wU7YIKLVZySNu50rCMt95UeB22Yt90LjpRFjnCBtH9/WUmXVj 23 | si96AAleTVC4D6CZNqUnhlGQWNis96gp1tViIN9AWv45R0ULSGlBmSp7OWWYhlOs 24 | GnayJQKBgEiedhmcGk8dfVy2In+dMT8nQ4sA3R5/XaDC2HWQgqiFXIFenWLsL3Ka 25 | GQp5CsSr/rVPNRofd/ms316rk0mrBAowoTC9SCc8SdMcufwuhh4jZEol1uXquPLY 26 | C9++b8Bfnms5ygOnEamt2tVp1iyCT80t+Lv+PgypSY4CXDR1e33U 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /module/web/cert/server.pem: -------------------------------------------------------------------------------- 1 | Certificate: 2 | Data: 3 | Version: 3 (0x2) 4 | Serial Number: 1 (0x1) 5 | Signature Algorithm: sha256WithRSAEncryption 6 | Issuer: C=CN, ST=JiangXi, L=YiChun, O=Kingtous, OU=Kingtous, CN=Kingtous/emailAddress=me@kingtous.cn 7 | Validity 8 | Not Before: Mar 20 13:07:28 2021 GMT 9 | Not After : Mar 20 13:07:28 2022 GMT 10 | Subject: C=CN, ST=JiangXi, O=Kingtous, OU=Kingtous, CN=Kingtous/emailAddress=me@kingtous.cn 11 | Subject Public Key Info: 12 | Public Key Algorithm: rsaEncryption 13 | RSA Public-Key: (1024 bit) 14 | Modulus: 15 | 00:b7:e6:48:96:3d:87:37:2e:ce:47:fa:c5:fc:21: 16 | 2d:8c:1a:64:c0:7a:55:10:c5:70:af:99:97:bb:6c: 17 | 3a:b1:b3:ff:c7:68:7e:04:70:a1:a1:5c:77:61:75: 18 | 85:07:f5:de:5b:b0:ea:dd:b7:1a:b7:65:bc:1b:75: 19 | 5b:d1:70:97:fc:c7:ae:8e:98:56:d6:c6:c2:0b:9e: 20 | a4:f1:56:ee:c2:82:e7:aa:05:4d:5a:f0:36:9d:8c: 21 | ea:47:3f:7d:5f:33:73:f1:a1:38:13:c8:f7:c5:9e: 22 | f9:8e:3e:f5:4c:b8:2a:9c:58:b4:9c:1b:b5:86:b6: 23 | fc:fb:78:7d:6e:46:d4:83:4b 24 | Exponent: 65537 (0x10001) 25 | X509v3 extensions: 26 | X509v3 Basic Constraints: 27 | CA:FALSE 28 | Netscape Comment: 29 | OpenSSL Generated Certificate 30 | X509v3 Subject Key Identifier: 31 | E0:62:CE:20:7D:32:89:C7:43:5E:85:97:78:7D:5D:33:AE:F2:DE:12 32 | X509v3 Authority Key Identifier: 33 | DirName:/C=CN/ST=JiangXi/L=YiChun/O=Kingtous/OU=Kingtous/CN=Kingtous/emailAddress=me@kingtous.cn 34 | serial:35:BA:E8:21:9D:5B:3C:C7:99:0D:DA:DA:4C:98:87:8F:BF:69:A6:9B 35 | 36 | Signature Algorithm: sha256WithRSAEncryption 37 | 15:7c:54:d6:e5:71:e1:55:ef:40:1b:fd:d9:29:cf:e0:73:3f: 38 | f1:39:6d:16:56:de:d6:b4:5e:30:ca:80:2c:bf:05:96:8c:9a: 39 | 01:e2:bc:09:19:1c:93:b2:a8:41:3e:00:f4:d9:db:ca:7c:ed: 40 | cd:9a:8b:64:67:48:e1:7f:27:db:49:e9:37:69:b7:ed:e6:e5: 41 | 09:6e:70:87:52:62:6f:08:90:bf:db:95:bc:29:26:1c:fd:22: 42 | 31:a4:29:52:ad:2e:4c:5d:3f:92:11:55:04:d7:89:6f:1c:21: 43 | 1b:53:9a:c8:e2:ed:21:62:23:89:61:25:c5:94:ab:7c:01:04: 44 | f0:e0:12:34:e1:cf:b1:c9:e7:f8:6d:f4:cc:14:86:5f:12:1f: 45 | 7f:d9:63:5b:2f:9f:4b:04:e1:24:73:3f:ef:e7:79:6b:86:48: 46 | 5c:f5:9e:c1:5c:d6:f6:f0:ff:36:7a:41:56:02:dc:1e:5b:7f: 47 | 84:e2:3f:4d:d7:73:37:5f:28:34:f0:93:f4:28:dd:92:99:fa: 48 | 06:52:e7:99:89:05:78:25:f7:6d:fe:af:11:ff:d8:49:10:a2: 49 | f4:27:82:d5:ad:a8:af:67:e9:ef:84:00:2b:cf:cd:79:bd:61: 50 | 8d:bb:ce:b1:02:f4:2d:f2:b5:c8:ed:e6:d9:5b:b6:c7:d2:cf: 51 | 95:7c:85:85 52 | -----BEGIN CERTIFICATE----- 53 | MIIECjCCAvKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCQ04x 54 | EDAOBgNVBAgMB0ppYW5nWGkxDzANBgNVBAcMBllpQ2h1bjERMA8GA1UECgwIS2lu 55 | Z3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5ndG91czEdMBsG 56 | CSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24wHhcNMjEwMzIwMTMwNzI4WhcNMjIw 57 | MzIwMTMwNzI4WjB3MQswCQYDVQQGEwJDTjEQMA4GA1UECAwHSmlhbmdYaTERMA8G 58 | A1UECgwIS2luZ3RvdXMxETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5n 59 | dG91czEdMBsGCSqGSIb3DQEJARYObWVAa2luZ3RvdXMuY24wgZ8wDQYJKoZIhvcN 60 | AQEBBQADgY0AMIGJAoGBALfmSJY9hzcuzkf6xfwhLYwaZMB6VRDFcK+Zl7tsOrGz 61 | /8dofgRwoaFcd2F1hQf13luw6t23GrdlvBt1W9Fwl/zHro6YVtbGwguepPFW7sKC 62 | 56oFTVrwNp2M6kc/fV8zc/GhOBPI98We+Y4+9Uy4KpxYtJwbtYa2/Pt4fW5G1INL 63 | AgMBAAGjggERMIIBDTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM 64 | IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU4GLOIH0yicdDXoWXeH1d 65 | M67y3hIwgbIGA1UdIwSBqjCBp6GBjqSBizCBiDELMAkGA1UEBhMCQ04xEDAOBgNV 66 | BAgMB0ppYW5nWGkxDzANBgNVBAcMBllpQ2h1bjERMA8GA1UECgwIS2luZ3RvdXMx 67 | ETAPBgNVBAsMCEtpbmd0b3VzMREwDwYDVQQDDAhLaW5ndG91czEdMBsGCSqGSIb3 68 | DQEJARYObWVAa2luZ3RvdXMuY26CFDW66CGdWzzHmQ3a2kyYh4+/aaabMA0GCSqG 69 | SIb3DQEBCwUAA4IBAQAVfFTW5XHhVe9AG/3ZKc/gcz/xOW0WVt7WtF4wyoAsvwWW 70 | jJoB4rwJGRyTsqhBPgD02dvKfO3NmotkZ0jhfyfbSek3abft5uUJbnCHUmJvCJC/ 71 | 25W8KSYc/SIxpClSrS5MXT+SEVUE14lvHCEbU5rI4u0hYiOJYSXFlKt8AQTw4BI0 72 | 4c+xyef4bfTMFIZfEh9/2WNbL59LBOEkcz/v53lrhkhc9Z7BXNb28P82ekFWAtwe 73 | W3+E4j9N13M3Xyg08JP0KN2SmfoGUueZiQV4Jfdt/q8R/9hJEKL0J4LVraivZ+nv 74 | hAArz815vWGNu86xAvQt8rXI7ebZW7bH0s+VfIWF 75 | -----END CERTIFICATE----- 76 | -----BEGIN RSA PRIVATE KEY----- 77 | MIICXQIBAAKBgQC35kiWPYc3Ls5H+sX8IS2MGmTAelUQxXCvmZe7bDqxs//HaH4E 78 | cKGhXHdhdYUH9d5bsOrdtxq3ZbwbdVvRcJf8x66OmFbWxsILnqTxVu7CgueqBU1a 79 | 8DadjOpHP31fM3PxoTgTyPfFnvmOPvVMuCqcWLScG7WGtvz7eH1uRtSDSwIDAQAB 80 | AoGBAJ9D6x1i0BX0jWY9QvYm7cFmolcoGz/ZHsyVopkJFJQOJbjXQDwsJ28OG73l 81 | /35za03RnLbD+3lVvGGzc/+hGZ60mmtleACtXtqF5xKwjJBRO/RzvadrCudmWFlk 82 | IqBtHfqb3N8EjtKZBeKboYBF606C++De3DWf/m5pky9HWNnBAkEA3EVQFFessIot 83 | CekS+28Mi+vuYqozme6Pnx6z6GGncuk2cGpcweNF62WK1vjFuV3vc8X4OePCNZyS 84 | D/w19U6DGwJBANW6qmCVfp+EKJDZBV+3BaxO7HvrdXQhMzS+nSlkGQh4uh4tlWRP 85 | b2tyL+hjKnjX2/H5dOquk1B08O+elCW305ECQQDQWyAsneJT++Auh7HU9G5BzKJp 86 | 4eV9rhNcyIYVQopKQB+mpnWnUXxJ9nsmbZtahGiEcrciyzZh0AC57jB8IhARAkAs 87 | ujK7oa1tDog6v9/7Bt8+Dwo4aK8czXHc4OMc7WC7wCAa/qkb4+/KSYwzEsWpomrZ 88 | +b14+23C0aY2TzZrqkuxAkBl0QZp+1AbgXFleq7WhzHhe1Tl5v+YXTJJMa7o301o 89 | rF+dQabkzpaJaKOVCpIpN37jIjjls4rg9zuA+zeCoY8h 90 | -----END RSA PRIVATE KEY----- 91 | -------------------------------------------------------------------------------- /module/web/src/serverdemo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/17. 3 | // 4 | 5 | #include "web.hpp" 6 | 7 | const char *say_hello() { 8 | // const char *ans = _ksql_query_db("select * from students"); 9 | return "select * from weather"; 10 | } 11 | 12 | void startServer() { 13 | int id = _web_getServerId("127.0.0.1", 9000, 4); 14 | _web_addUrlHandler(id, "GET", "/hello", "text/html", say_hello); 15 | _web_startServe(id); 16 | } 17 | 18 | 19 | int main() { 20 | _ksql_connect_db("39.107.226.2", "weather", "jintao123", "weather",3306,"utf8"); 21 | // _ksql_connect_db(HOST, USER, PASSWD, DATABASE); 22 | startServer(); 23 | // for test interface 24 | // int serverId = _web_getServerId("127.0.0.1", 9000); 25 | // int res = _web_addUrlHandler(serverId, "POST", "/hello", say_hello); 26 | // if (res != ROK) { 27 | // return res; 28 | // } 29 | // return _web_startServe(serverId); 30 | return 0; 31 | } -------------------------------------------------------------------------------- /module/web/src/web.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/8. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_WEB_HPP 6 | #define SYSYPLUS_COMPILER_WEB_HPP 7 | 8 | #include 9 | #include 10 | #include "./module/sql/src/ksql.h" 11 | #include 12 | #include 13 | #include 14 | #include 15 | #ifdef _WIN32 16 | #include 17 | #define getcwd _getcwd // stupid MSFT "deprecation" warning 18 | #else 19 | #include 20 | #endif 21 | //#include <> 22 | 23 | /// 客户端状态码 24 | #define NOT_INITIALIZED -1 25 | #define RESOLVE_FAILED -2 26 | #define CONNECT_FAILED -3 27 | #define SOCKET_NOT_EXISTS -3 28 | #define NOT_CONNECTED -4 29 | /// 服务器状态码 30 | #define PORT_IS_IN_USE -5 31 | #define SERVER_NOT_EXISTS -6 32 | /// 通用状态码 33 | #define ROK 0 34 | 35 | #define SERVER_NAME "Kingtous WebServer" 36 | 37 | using namespace std; 38 | using tcp = boost::asio::ip::tcp; 39 | namespace http = boost::beast::http; 40 | namespace ssl = boost::asio::ssl; 41 | namespace beast = boost::beast; 42 | 43 | using request_body_t = http::string_body; 44 | 45 | extern boost::asio::io_context *_web_io_context; 46 | extern tcp::resolver *_web_resolver; 47 | extern map _web_tcp_socket_map; 48 | extern boost::asio::io_context *_server_context; 49 | 50 | // Keep 函数名,方便Linking 51 | extern "C" { 52 | 53 | /** 54 | * 初始化网络功能 55 | * @return 如上的返回值 56 | */ 57 | int _web_init(); 58 | 59 | /** 60 | * 获取一个Socket 61 | * @return 62 | */ 63 | int _web_getSocket(); 64 | 65 | /** 66 | * 连接Web 67 | * @param socketId socketId 68 | * @param baseUrl eg: kingtous.cn 69 | * @param port 端口号 70 | * @return 连接状态 71 | */ 72 | int _web_connectSocket(int socketId, const char *baseUrlOrIp, const char *port); 73 | 74 | /** 75 | * 关闭socket 76 | * @param socketId 77 | * @return 78 | */ 79 | int _web_closeSocket(int socketId); 80 | 81 | /** 82 | * socket是否连接 83 | * @param socketId 84 | * @return 85 | */ 86 | int _web_isSocketConnected(int socketId); 87 | 88 | /** 89 | * 通过GET请求发送HTTP数据 90 | * @param hosts 91 | * @param socketId 92 | * @param path eg: /index 93 | * @return 94 | */ 95 | const char *_web_callGetRequest(int socketId, char *host, char *path); 96 | 97 | /** 98 | * 通过POST请求发送HTTP数据 99 | * @param socketId 100 | * @param host 101 | * @param path 102 | * @param body 103 | * @return 104 | */ 105 | const char *_web_callPostRequest(int socketId, char *host, char *path, char *body); 106 | 107 | /** 108 | * 获取一个本地HTTP服务器的ID 109 | * @param addr 地址 110 | * @param port 端口号 111 | * @param core 线程数 112 | * @return server id 113 | */ 114 | int _web_getServerId(const char *addr, int port, int core); 115 | 116 | /** 117 | * @param sId server id 118 | * @param path URL path,如:/index 119 | * @param content_type content_type 120 | * @param method 方法 121 | * @param handler 函数指针,用于返回一个const char*内容 122 | * @return 状态 123 | */ 124 | int _web_addUrlHandler(int sId, const char *method, 125 | const char *path, 126 | const char *content_type, 127 | const char *handler()); 128 | 129 | /** 130 | * 开启服务器,程序进入阻塞状态 131 | * @param sId server id 132 | * @return 状态 133 | */ 134 | int _web_startServe(int sId); 135 | } 136 | 137 | typedef const char *HandlerFunction(); 138 | 139 | typedef boost::asio::ssl::stream ssl_stream; 140 | 141 | /** 142 | * handler结构 143 | */ 144 | typedef struct WebHttpHandler { 145 | std::string *method; 146 | std::string *path; 147 | std::string *content_type; 148 | HandlerFunction *function; 149 | } WebHttpHandler; 150 | 151 | class _web_HttpWorker { 152 | public: 153 | _web_HttpWorker(_web_HttpWorker const &) = delete; 154 | 155 | _web_HttpWorker &operator=(_web_HttpWorker const &) = delete; 156 | 157 | _web_HttpWorker(boost::asio::io_context *ioc, tcp::acceptor &acceptor, const string &basePath); 158 | 159 | std::unique_ptr> str_serializer; 160 | 161 | std::unique_ptr> str_resp; 162 | 163 | boost::asio::io_context *io_context; 164 | 165 | std::shared_ptr> handlers; 166 | 167 | /** 168 | * 接收下一个客户 169 | */ 170 | void accept(); 171 | 172 | /** 173 | * 开启服务器 174 | */ 175 | void start(); 176 | 177 | /** 178 | * 读取一个request 179 | */ 180 | void readRequest(); 181 | 182 | /** 183 | * 检查死连接 184 | */ 185 | void checkDeadline(); 186 | 187 | /** 188 | * 添加Handler 189 | */ 190 | void addHandler(WebHttpHandler &handler); 191 | 192 | /** 193 | * @brief 关闭连接 194 | */ 195 | void doClose(); 196 | 197 | private: 198 | 199 | /** 200 | * 发送url未map的信息 201 | */ 202 | void sendNotExistResponse(); 203 | 204 | tcp::acceptor &acceptor; 205 | // using request_body_t = http::basic_dynamic_body>; 206 | std::string base_path; 207 | 208 | boost::asio::ssl::context ssl_context{boost::asio::ssl::context::tlsv12}; 209 | std::shared_ptr ssl_stream_; 210 | boost::optional> parser; 211 | beast::flat_static_buffer<8192> buffer; 212 | boost::asio::basic_waitable_timer request_deadline{ 213 | acceptor.get_executor(), (std::chrono::steady_clock::time_point::max) ()}; 214 | 215 | void process_request(http::request const &request); 216 | }; 217 | 218 | 219 | boost::beast::string_view mime_type(boost::beast::string_view path); 220 | 221 | #endif //SYSYPLUS_COMPILER_WEB_HPP 222 | -------------------------------------------------------------------------------- /module/web/src/webdemo.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/3/8. 3 | // 4 | #include 5 | 6 | #include "web.hpp" 7 | 8 | int main() { 9 | auto ip = "39.107.226.2"; 10 | auto port = "80"; 11 | int socketId = _web_getSocket(); 12 | int code = _web_connectSocket(socketId, ip, port); 13 | // auto resp = _web_callGetRequest(socketId,"file.kingtous.cn","/"); 14 | auto resp = _web_callPostRequest(socketId, "file.kingtous.cn", "/", "name=root"); 15 | std::cout << resp; 16 | _web_closeSocket(socketId); 17 | return code; 18 | } -------------------------------------------------------------------------------- /parser/FileReader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/23. 3 | // 4 | #include "../ErrHelper.h" 5 | #include "FileReader.h" 6 | #include 7 | #include 8 | 9 | #include "stat.h" 10 | 11 | FileReader::FileReader(const std::string &path) { 12 | std::ifstream ifs(path); 13 | if (ifs.is_open()) { 14 | std::stringstream buffer; 15 | buffer << ifs.rdbuf(); 16 | ifs.close(); 17 | content = std::string(buffer.str()); 18 | content_length = content.size(); 19 | } else { 20 | fprintf(stderr, "err open files"); 21 | exit(-1); 22 | } 23 | } 24 | 25 | int FileReader::getchar() { 26 | if (index < content_length) { 27 | char ch = content[index++]; 28 | if (ch == '\n') { 29 | lineno++; 30 | colno = 0; 31 | colno++; 32 | webc::lex::line_num++; 33 | } 34 | return ch; 35 | } else { 36 | return END_OF_FILE; 37 | } 38 | } 39 | 40 | int FileReader::seek() { 41 | if (index < content_length) { 42 | return content[index]; 43 | } else { 44 | return EOF; 45 | } 46 | } 47 | 48 | 49 | unsigned int FileReader::getLineNo() { 50 | return lineno; 51 | } 52 | 53 | unsigned int FileReader::getCCol() { 54 | return colno; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /parser/FileReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/23. 3 | // 4 | 5 | #ifndef LLVM_KALEIDOSCOPE_FILEREADER_H 6 | #define LLVM_KALEIDOSCOPE_FILEREADER_H 7 | 8 | #include 9 | 10 | #include "IFileReader.h" 11 | 12 | class FileReader : public IFileReader { 13 | 14 | std::string content; 15 | unsigned int index = 0; 16 | unsigned int lineno = 0; 17 | unsigned int colno = 0; 18 | 19 | public: 20 | explicit FileReader(const std::string &path); 21 | 22 | int getchar() override; 23 | 24 | int seek() override; 25 | 26 | unsigned long content_length; 27 | 28 | unsigned int getLineNo() override; 29 | 30 | unsigned int getCCol() override; 31 | }; 32 | 33 | 34 | #endif //LLVM_KALEIDOSCOPE_FILEREADER_H 35 | -------------------------------------------------------------------------------- /parser/IFileReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/21. 3 | // 4 | 5 | #ifndef LLVM_KALEIDOSCOPE_FILE_READER_WRAPPER_H 6 | #define LLVM_KALEIDOSCOPE_FILE_READER_WRAPPER_H 7 | 8 | class IFileReader { 9 | public: 10 | virtual int getchar() = 0; 11 | 12 | virtual int seek() = 0; 13 | 14 | virtual unsigned int getLineNo() = 0; 15 | 16 | virtual unsigned int getCCol() = 0; 17 | 18 | }; 19 | 20 | 21 | #endif //LLVM_KALEIDOSCOPE_FILE_READER_WRAPPER_H 22 | -------------------------------------------------------------------------------- /parser/Lexer.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/21. 3 | // 4 | 5 | #include "Lexer.h" 6 | 7 | #include "stat.h" 8 | 9 | int Lexer::_getNextToken() { 10 | while (isspace(last_char)) { 11 | NEXTCHAR; 12 | } 13 | if (last_char == ',') { 14 | NEXTCHAR; 15 | return T_COMMA; 16 | } 17 | if (last_char == ';') { 18 | // 分号直接return 19 | NEXTCHAR; 20 | return ';'; 21 | } 22 | if (last_char == '\''){ 23 | string str = ""; 24 | while ((last_char = getchar()) != '\''){ 25 | str.insert(str.end(),last_char); 26 | } 27 | // 吃掉' 28 | NEXTCHAR; 29 | yylval.string = new string(str); 30 | return T_STR; 31 | } 32 | // 判断是否是标识符 33 | if (isalpha(last_char)) { // identifier: [a-zA-Z][a-zA-Z0-9]* 34 | identifierStr = char(last_char); 35 | while (isalnum((last_char = getchar())) || last_char == '_') 36 | identifierStr += last_char; 37 | 38 | if (identifierStr == "if") { 39 | return T_IF; 40 | } else if (identifierStr == "el") { 41 | return T_ELSE; 42 | } else if (identifierStr == "wh") { 43 | return T_WHILE; 44 | } else if (identifierStr == "cont") { 45 | return T_CONTINUE; 46 | } else if (identifierStr == "ret") { 47 | return T_RETURN; 48 | } else if (identifierStr == "lp") { 49 | return T_FOR; 50 | } else if (identifierStr == "out") { 51 | return T_OUT; 52 | } else if (identifierStr == "const"){ 53 | return T_CONST; 54 | } else if (identifierStr == "nil"){ 55 | return T_NULL; 56 | } else if(identifierStr == "func_ptr"){ 57 | return T_FUNC_SIGN; 58 | } else if(identifierStr == "true"){ 59 | return T_TRUE; 60 | } else if(identifierStr == "false"){ 61 | return T_FALSE; 62 | } 63 | // else if (identifierStr == "module"){ 64 | // return T_MODULE; 65 | // } 66 | yylval.string = new std::string(identifierStr); 67 | return T_IDENTIFIER; 68 | } 69 | 70 | // 是符号 71 | if (ispunct(last_char)) { 72 | // 特判 73 | if (last_char == '(') { 74 | NEXTCHAR; 75 | return T_L_SPAR; 76 | } else if (last_char == ')') { 77 | NEXTCHAR; 78 | return T_R_SPAR; 79 | } else if (last_char == '[') { 80 | NEXTCHAR; 81 | return T_L_MPAR; 82 | } else if (last_char == ']') { 83 | NEXTCHAR; 84 | return T_R_MPAR; 85 | } else if (last_char == '{') { 86 | NEXTCHAR; 87 | return T_L_LPAR; 88 | } else if (last_char == '}') { 89 | NEXTCHAR; 90 | return T_R_LPAR; 91 | } else if (last_char == '+') { 92 | NEXTCHAR; 93 | return T_ADD; 94 | } else if (last_char == '-' && isspace(seek())) { 95 | NEXTCHAR; 96 | return T_SUB; 97 | } else if (last_char == '*') { 98 | NEXTCHAR; 99 | return T_MUL; 100 | } else if (last_char == '/' && seek() != '/') { 101 | NEXTCHAR; 102 | return T_DIV; 103 | } else if (last_char == '%') { 104 | NEXTCHAR; 105 | return T_MOD; 106 | } else if (last_char == '=') { 107 | if (seek() == '=') { 108 | getchar(); 109 | NEXTCHAR; 110 | return T_EQU; 111 | } else { 112 | NEXTCHAR; 113 | return T_ASSIGN; 114 | } 115 | } else if (last_char == '<') { 116 | if (seek() == '=') { 117 | getchar(); 118 | NEXTCHAR; 119 | return T_LESS_EQU; 120 | } else { 121 | NEXTCHAR; 122 | return T_LESS; 123 | } 124 | } else if (last_char == '>') { 125 | if (seek() == '=') { 126 | getchar(); 127 | NEXTCHAR; 128 | return T_GREATER_EQU; 129 | } else { 130 | NEXTCHAR; 131 | return T_GREATER; 132 | } 133 | } else if (last_char == '!') { 134 | if (seek() == '=') { 135 | getchar(); 136 | NEXTCHAR; 137 | return T_N_EQU; 138 | } 139 | NEXTCHAR; 140 | return T_REVERSE; 141 | } 142 | 143 | identifierStr = char(last_char); 144 | 145 | 146 | while (ispunct((seek()))) { 147 | NEXTCHAR; 148 | identifierStr += last_char; 149 | // 注释 150 | if (identifierStr == "//") { 151 | while (last_char != '\n' && last_char != END_OF_FILE) { 152 | last_char = getchar(); 153 | } 154 | NEXTCHAR; 155 | return _getNextToken(); 156 | } 157 | else if (identifierStr == "&&") { 158 | NEXTCHAR; 159 | return T_AND; 160 | } 161 | else if (identifierStr == "||") { 162 | NEXTCHAR; 163 | return T_OR; 164 | } 165 | } 166 | 167 | if (identifierStr == "-") { 168 | // 负数 169 | if (isdigit(seek())) { 170 | NEXTCHAR; 171 | int token = _getNextToken(); 172 | if (token == T_INTEGER) { 173 | yylval.int_value = -yylval.int_value; 174 | } else if (token == T_DOUBLE) { 175 | yylval.double_value = -yylval.double_value; 176 | } 177 | return token; 178 | } else { 179 | return T_SUB; 180 | } 181 | } 182 | yylval.string = new std::string(identifierStr); 183 | return T_IDENTIFIER; 184 | } 185 | 186 | if (isdigit(last_char) || last_char == '.') { // Number: [0-9.]+ 187 | std::string NumStr; 188 | do { 189 | NumStr += last_char; 190 | NEXTCHAR; 191 | } while (isdigit(last_char) || last_char == '.'); 192 | if (NumStr.find('.') == string::npos) { 193 | yylval.int_value = stoi(NumStr); 194 | #ifdef DEBUG_FLAG 195 | std::fprintf(stderr, "KEX: read int: %d\n", yylval.int_value); 196 | #endif 197 | return T_INTEGER; 198 | } else { 199 | yylval.double_value = stod(NumStr); 200 | #ifdef DEBUG_FLAG 201 | std::fprintf(stderr, "KEX: read double: %f\n", yylval.double_value); 202 | #endif 203 | return T_DOUBLE; 204 | } 205 | } 206 | if (last_char == '#') { 207 | // Comment until end of line. 208 | do 209 | NEXTCHAR; 210 | while (last_char != END_OF_FILE && last_char != '\n' && last_char != '\r'); 211 | 212 | if (last_char != END_OF_FILE) 213 | return getNextToken(); 214 | } 215 | // Check for end of file. Don't eat the END_OF_FILE. 216 | if (last_char == END_OF_FILE) 217 | return 0; 218 | // Otherwise, just return the character as its ascii value. 219 | int ThisChar = last_char; 220 | NEXTCHAR; 221 | return ThisChar; 222 | } 223 | 224 | int Lexer::getNextToken() { 225 | currToken = _getNextToken(); 226 | #ifdef DEBUG_FLAG //如果处于DEBUG模式的话,就打印这些字符 227 | if (currToken == T_IDENTIFIER) { 228 | std::fprintf(stderr, "KEX: read identifier: %s\n", (*yylval.string).c_str()); 229 | } else if (currToken < 258) { 230 | std::fprintf(stderr, "KEX: read character: %c\n", currToken); 231 | } else { 232 | std::fprintf(stderr, "KEX: read token type: %d\n", currToken); 233 | } 234 | #endif //如果不是debug模式的话,就不打印这些字符,直接返回 235 | webc::lex::token_num++; 236 | return currToken; 237 | } 238 | 239 | int Lexer::getchar() { 240 | return reader->getchar(); 241 | } 242 | 243 | int Lexer::seek() { 244 | return reader->seek(); 245 | } 246 | 247 | unsigned int Lexer::getCLineNumber() { 248 | return reader->getLineNo() + 1; 249 | } 250 | 251 | unsigned int Lexer::getCCol() { 252 | return reader->getCCol(); 253 | } 254 | 255 | Lexer *TheLexer = nullptr; 256 | 257 | int yylex() { 258 | return TheLexer->getNextToken(); 259 | } 260 | -------------------------------------------------------------------------------- /parser/Lexer.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2020/9/21. 3 | // Description: from word to lex 4 | // 5 | 6 | #ifndef LLVM_KALEIDOSCOPE_LEXER_H 7 | #define LLVM_KALEIDOSCOPE_LEXER_H 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../Global.h" 14 | #include "IFileReader.h" 15 | #include "FileReader.h" 16 | #include "Parser.hpp" 17 | #include "StringReader.h" 18 | 19 | #define NEXTCHAR (last_char=getchar()) 20 | 21 | class Lexer { 22 | public: 23 | std::string identifierStr = ""; //如果是tok_identifier就传入 24 | double NumVal = INIT_NUM; //如果是tok_number则表示数字 25 | int currToken; //当前的token 26 | 27 | 28 | /// lexer构造函数:传入代码 29 | /// params: rawStr 代码全文 30 | // explicit代表这个构造函数不能进行隐式的类型转换 31 | explicit Lexer(IFileReader *fileReader) : reader(fileReader) {} 32 | 33 | /// 获取下一个token 34 | int getNextToken(); 35 | 36 | unsigned int getCLineNumber(); 37 | 38 | unsigned int getCCol(); 39 | 40 | private: 41 | /// 当前的Token 42 | IFileReader* reader; 43 | 44 | int last_char = ' '; 45 | 46 | int _getNextToken(); 47 | 48 | int getchar(); 49 | 50 | int seek(); 51 | }; 52 | 53 | extern Lexer *TheLexer; 54 | 55 | int yylex(); 56 | 57 | #endif //LLVM_KALEIDOSCOPE_LEXER_H 58 | -------------------------------------------------------------------------------- /parser/NetworkReader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/5/17. 3 | // 4 | 5 | #include "NetworkReader.h" 6 | #include "Global.h" 7 | #include "ErrHelper.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | namespace http = boost::beast::http; 23 | 24 | #define NETWORKREADER_RETRY_TIMES 3 25 | 26 | namespace network { 27 | enum download_status { 28 | INIT = 0, 29 | IN_DOWNLOAD = 1, 30 | DOWNLOADED = 2, 31 | FAILED = 3 32 | }; 33 | boost::regex url_regex("(http|https)://([^/ :]+):?([^/ ]*)(/?[^ #?]*)\\x3f?([^ #]*)#?([^ ]*)"); 34 | } 35 | 36 | int NetworkReader::retry_times = NETWORKREADER_RETRY_TIMES; 37 | 38 | int NetworkReader::getchar() { 39 | if (isContentReady() && string_reader_ptr != nullptr) { 40 | return string_reader_ptr->getchar(); 41 | } 42 | return END_OF_FILE; 43 | } 44 | 45 | int NetworkReader::seek() { 46 | if (isContentReady() && string_reader_ptr != nullptr) { 47 | return string_reader_ptr->seek(); 48 | } 49 | return END_OF_FILE; 50 | } 51 | 52 | unsigned int NetworkReader::getLineNo() { 53 | if (isContentReady() && string_reader_ptr != nullptr) { 54 | return string_reader_ptr->getLineNo(); 55 | } 56 | return END_OF_FILE; 57 | } 58 | 59 | unsigned int NetworkReader::getCCol() { 60 | if (isContentReady() && string_reader_ptr != nullptr) { 61 | return string_reader_ptr->getCCol(); 62 | } 63 | return END_OF_FILE; 64 | } 65 | 66 | NetworkReader::NetworkReader(std::string url) : url(std::move(url)) { 67 | // init 68 | download_status = network::download_status::INIT; 69 | download(); 70 | } 71 | 72 | int NetworkReader::download() { 73 | boost::asio::post(thread_pool, [this]() { 74 | download_status = network::download_status::IN_DOWNLOAD; 75 | LogInfo("正在下载代码数据\n"); 76 | try { 77 | boost::cmatch url_parsed; 78 | if (boost::regex_match(url.c_str(), url_parsed, network::url_regex)) { 79 | boost::asio::io_context ioc; 80 | boost::asio::ip::tcp::resolver tcp_resolver(ioc); 81 | auto protocol = string(url_parsed[1].first, url_parsed[1].second); 82 | auto base_url = string(url_parsed[2].first, url_parsed[2].second); 83 | auto port = string(url_parsed[3].first, url_parsed[3].second); 84 | auto path = string(url_parsed[4].first, url_parsed[4].second); 85 | auto query = string(url_parsed[5].first, url_parsed[5].second); 86 | // preprocess 87 | bool isSSL = protocol == "https"; 88 | if (port.empty()) { 89 | port = isSSL ? "443" : "80"; 90 | } 91 | // connect 92 | auto result = tcp_resolver.resolve(base_url, port); 93 | if (result.empty()) { 94 | LogError("无法解析指定地址"); 95 | download_status = network::download_status::FAILED; 96 | return; 97 | } 98 | 99 | if (!isSSL) { 100 | auto tcp_socket = boost::asio::ip::tcp::socket(ioc); 101 | boost::asio::connect(tcp_socket, result.begin(), result.end()); 102 | if (!tcp_socket.is_open()) { 103 | LogError("无法连接指定地址"); 104 | download_status = network::download_status::FAILED; 105 | return; 106 | } 107 | // start download 108 | http::request request{http::verb::get, path + "?" + query, 11}; 109 | request.set(http::field::host, base_url); 110 | request.set(http::field::user_agent, APPNAME); 111 | http::write(tcp_socket, request); 112 | // 开启一个buffer 113 | boost::beast::flat_buffer buffer; 114 | // 开启一个response body 115 | http::response res; 116 | // Receive the HTTP response 117 | http::read(tcp_socket, buffer, res); 118 | string_reader_ptr = 119 | std::make_unique(new string(res.body())); 120 | download_status = network::download_status::DOWNLOADED; 121 | tcp_socket.close(); 122 | } else { 123 | // ssl support 124 | boost::asio::ssl::context ssl_ctx(boost::asio::ssl::context::method::sslv23_client); 125 | boost::asio::ssl::stream ssl_socket(ioc, ssl_ctx); 126 | boost::asio::connect(ssl_socket.lowest_layer(), result.begin(), result.end()); 127 | if (!ssl_socket.lowest_layer().is_open()) { 128 | LogError("无法连接指定地址(SSL)"); 129 | download_status = network::download_status::FAILED; 130 | return; 131 | } 132 | // handshake 133 | ssl_socket.handshake(boost::asio::ssl::stream_base::client); 134 | // start download 135 | http::request request{http::verb::get, path + "?" + query, 11}; 136 | request.set(http::field::host, base_url); 137 | request.set(http::field::user_agent, APPNAME); 138 | http::write(ssl_socket, request); 139 | // 开启一个buffer 140 | boost::beast::flat_buffer buffer; 141 | // 开启一个response body 142 | http::response res; 143 | // Receive the HTTP response 144 | http::read(ssl_socket, buffer, res); 145 | string_reader_ptr = 146 | std::make_unique(new string(res.body())); 147 | download_status = network::download_status::DOWNLOADED; 148 | ssl_socket.lowest_layer().close(); 149 | } 150 | 151 | } else { 152 | LogError("不是个有效的URL地址"); 153 | download_status = network::download_status::FAILED; 154 | } 155 | } catch (boost::system::system_error &e) { 156 | LogError(e.what()); 157 | download_status = network::download_status::FAILED; 158 | } 159 | }); 160 | return ROK; 161 | } 162 | 163 | bool NetworkReader::isContentReady() { 164 | // download in progress, block 165 | while (download_status == network::download_status::IN_DOWNLOAD); 166 | return download_status == network::download_status::DOWNLOADED 167 | && string_reader_ptr != nullptr; 168 | } 169 | -------------------------------------------------------------------------------- /parser/NetworkReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/5/17. 3 | // 4 | 5 | #ifndef WEBC_COMPILER_NETWORKREADER_H 6 | #define WEBC_COMPILER_NETWORKREADER_H 7 | 8 | #include "IFileReader.h" 9 | #include "StringReader.h" 10 | 11 | #include 12 | #include 13 | 14 | class NetworkReader : public IFileReader { 15 | public: 16 | explicit NetworkReader(std::string url); 17 | 18 | int getchar() override; 19 | 20 | int seek() override; 21 | 22 | unsigned int getLineNo() override; 23 | 24 | unsigned int getCCol() override; 25 | 26 | private: 27 | int download(); 28 | 29 | bool isContentReady(); 30 | 31 | private: 32 | std::string url; 33 | std::unique_ptr string_reader_ptr; 34 | static int retry_times; 35 | volatile int download_status; 36 | boost::asio::thread_pool thread_pool{}; 37 | }; 38 | 39 | 40 | #endif //WEBC_COMPILER_NETWORKREADER_H 41 | -------------------------------------------------------------------------------- /parser/Parser.hpp: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.7. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2020 Free Software Foundation, 6 | Inc. 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . */ 20 | 21 | /* As a special exception, you may create a larger work that contains 22 | part or all of the Bison parser skeleton and distribute that work 23 | under terms of your choice, so long as that work isn't itself a 24 | parser generator using the skeleton or a modified version thereof 25 | as a parser skeleton. Alternatively, if you modify or redistribute 26 | the parser skeleton itself, you may (at your option) remove this 27 | special exception, which will cause the skeleton and the resulting 28 | Bison output files to be licensed under the GNU General Public 29 | License without this special exception. 30 | 31 | This special exception was added by the Free Software Foundation in 32 | version 2.2 of Bison. */ 33 | 34 | /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, 35 | especially those whose name start with YY_ or yy_. They are 36 | private implementation details that can be changed or removed. */ 37 | 38 | #ifndef YY_YY_PARSER_HPP_INCLUDED 39 | # define YY_YY_PARSER_HPP_INCLUDED 40 | /* Debug traces. */ 41 | #ifndef YYDEBUG 42 | # define YYDEBUG 0 43 | #endif 44 | #if YYDEBUG 45 | extern int yydebug; 46 | #endif 47 | /* "%code requires" blocks. */ 48 | #line 5 "Parser.y" 49 | 50 | #include "Lexer.h" 51 | #include "ast/NodeAST.hpp" 52 | // 程序分析入口点 53 | extern BlockAST* program; 54 | using std::vector; 55 | 56 | #line 57 "Parser.hpp" 57 | 58 | /* Token kinds. */ 59 | #ifndef YYTOKENTYPE 60 | # define YYTOKENTYPE 61 | enum yytokentype 62 | { 63 | YYEMPTY = -2, 64 | END = 0, /* "END OF FILE BY SYSYPLUS COMPILER BY KINGTOUS" */ 65 | YYerror = 256, /* error */ 66 | YYUNDEF = 257, /* "invalid token" */ 67 | T_IDENTIFIER = 258, /* T_IDENTIFIER */ 68 | T_INTEGER = 259, /* T_INTEGER */ 69 | T_DOUBLE = 260, /* T_DOUBLE */ 70 | T_ADD = 261, /* T_ADD */ 71 | T_SUB = 262, /* T_SUB */ 72 | T_MUL = 263, /* T_MUL */ 73 | T_DIV = 264, /* T_DIV */ 74 | T_MOD = 265, /* T_MOD */ 75 | T_ASSIGN = 266, /* T_ASSIGN */ 76 | T_EQU = 267, /* T_EQU */ 77 | T_N_EQU = 268, /* T_N_EQU */ 78 | T_LESS = 269, /* T_LESS */ 79 | T_GREATER = 270, /* T_GREATER */ 80 | T_REVERSE = 271, /* T_REVERSE */ 81 | T_LESS_EQU = 272, /* T_LESS_EQU */ 82 | T_GREATER_EQU = 273, /* T_GREATER_EQU */ 83 | T_COMMA = 274, /* T_COMMA */ 84 | T_SEMICOLON = 275, /* T_SEMICOLON */ 85 | T_L_SPAR = 276, /* T_L_SPAR */ 86 | T_R_SPAR = 277, /* T_R_SPAR */ 87 | T_L_MPAR = 278, /* T_L_MPAR */ 88 | T_R_MPAR = 279, /* T_R_MPAR */ 89 | T_L_LPAR = 280, /* T_L_LPAR */ 90 | T_R_LPAR = 281, /* T_R_LPAR */ 91 | T_CONST = 282, /* T_CONST */ 92 | T_STR = 283, /* T_STR */ 93 | T_NULL = 284, /* T_NULL */ 94 | T_TRUE = 285, /* T_TRUE */ 95 | T_FALSE = 286, /* T_FALSE */ 96 | T_FOR = 287, /* T_FOR */ 97 | T_WHILE = 288, /* T_WHILE */ 98 | T_OUT = 289, /* T_OUT */ 99 | T_CONTINUE = 290, /* T_CONTINUE */ 100 | T_IF = 291, /* T_IF */ 101 | T_ELSE = 292, /* T_ELSE */ 102 | T_RETURN = 293, /* T_RETURN */ 103 | T_VOID = 294, /* T_VOID */ 104 | T_INT = 295, /* T_INT */ 105 | T_FUNC_SIGN = 296, /* T_FUNC_SIGN */ 106 | T_OR = 298, /* T_OR */ 107 | T_AND = 299, /* T_AND */ 108 | T_MINUS = 300, /* T_MINUS */ 109 | T_POS = 301 /* T_POS */ 110 | }; 111 | typedef enum yytokentype yytoken_kind_t; 112 | #endif 113 | 114 | /* Value type. */ 115 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 116 | union YYSTYPE 117 | { 118 | #line 28 "Parser.y" 119 | 120 | NodeAST* node; 121 | ExpressionAST* expr; 122 | StatementAST* stmt; 123 | BlockAST* block; 124 | IdentifierExprAST* ident; 125 | IdentifierArrExprAST* identarr; 126 | VariableDeclarationAST* vdeclar; 127 | ConditionAST* cond; 128 | ForExprAST* forexpr; 129 | WhileStmtAST* whilestmt; 130 | FuncPtrAST* funcptr; 131 | std::vector *varvec; 132 | std::vector *identvec; 133 | std::vector *exprvec; 134 | std::vector *aivec; // array index vector 135 | vector* arrayvalvec; 136 | std::string *string; 137 | double double_value; 138 | int int_value; 139 | int token; 140 | 141 | #line 142 "Parser.hpp" 142 | 143 | }; 144 | typedef union YYSTYPE YYSTYPE; 145 | # define YYSTYPE_IS_TRIVIAL 1 146 | # define YYSTYPE_IS_DECLARED 1 147 | #endif 148 | 149 | 150 | extern YYSTYPE yylval; 151 | 152 | int yyparse (void); 153 | 154 | #endif /* !YY_YY_PARSER_HPP_INCLUDED */ 155 | -------------------------------------------------------------------------------- /parser/Parser.y: -------------------------------------------------------------------------------- 1 | %code top { 2 | #include 3 | } 4 | 5 | %code requires { 6 | #include "Lexer.h" 7 | #include "ast/NodeAST.hpp" 8 | // 程序分析入口点 9 | extern BlockAST* program; 10 | using std::vector; 11 | } 12 | 13 | %{ 14 | #include "Lexer.h" 15 | extern char *yytext; 16 | #ifdef CGUI 17 | extern void logOnUi(const char* s); 18 | #endif 19 | void yyerror(const char *s) 20 | { fprintf(stderr,"%s on line %d, Col %d\n",s,TheLexer->getCLineNumber(),TheLexer->getCCol()); 21 | #ifdef CGUI 22 | logOnUi((string(s)+" 在 " + to_string(TheLexer->getCLineNumber())+" 行 "+to_string(TheLexer->getCCol())+" 列").c_str()); 23 | #endif 24 | } 25 | %} 26 | 27 | // 声明变量可能有的类型 28 | %union{ 29 | NodeAST* node; 30 | ExpressionAST* expr; 31 | StatementAST* stmt; 32 | BlockAST* block; 33 | IdentifierExprAST* ident; 34 | IdentifierArrExprAST* identarr; 35 | VariableDeclarationAST* vdeclar; 36 | ConditionAST* cond; 37 | ForExprAST* forexpr; 38 | WhileStmtAST* whilestmt; 39 | FuncPtrAST* funcptr; 40 | std::vector *varvec; 41 | std::vector *identvec; 42 | std::vector *exprvec; 43 | std::vector *aivec; // array index vector 44 | vector* arrayvalvec; 45 | std::string *string; 46 | double double_value; 47 | int int_value; 48 | int token; 49 | } 50 | /// 终结符 51 | // 设置结点对应的类型 52 | %token T_IDENTIFIER 53 | %token T_INTEGER 54 | %token T_DOUBLE 55 | // 计算符号 56 | %token T_ADD T_SUB T_MUL T_DIV T_MOD T_ASSIGN 57 | // 比较符 58 | %token T_EQU T_N_EQU T_LESS T_GREATER T_REVERSE T_LESS_EQU T_GREATER_EQU 59 | // , ; () [] {} <> 60 | %token T_COMMA T_SEMICOLON T_L_SPAR T_R_SPAR T_L_MPAR T_R_MPAR T_L_LPAR T_R_LPAR T_CONST 61 | // ' " 62 | %token T_STR T_NULL 63 | %token T_TRUE T_FALSE 64 | // 循环 65 | %token T_FOR T_WHILE T_OUT T_CONTINUE 66 | %token T_IF T_ELSE 67 | %token T_RETURN 68 | %token T_VOID T_INT 69 | %token T_FUNC_SIGN 70 | %token END 0 "END OF FILE BY SYSYPLUS COMPILER BY KINGTOUS" 71 | /// 非终结符 72 | // type 类型 为此类型的名称 73 | %type program block stmts 74 | %type ident 75 | %type ident_arr 76 | %type number expr str 77 | %type if_condition 78 | %type for_stmt 79 | %type while_stmt 80 | %type for_args 81 | %type stmt func_decl 82 | %type var_decl 83 | %type func_args 84 | %type func_ptr_args 85 | %type call_args 86 | %type array_init_val array_init_list 87 | %type array_index "array index vector" 88 | // 标识 or 优先级 > and 89 | %left T_OR 90 | %left T_AND 91 | %left T_ASSIGN T_EQU T_N_EQU T_LESS T_GREATER T_LESS_EQU T_GREATER_EQU 92 | %left T_ADD T_SUB 93 | %left T_MUL T_DIV T_MOD 94 | 95 | // 标识无关token,在处理优先级时忽略 96 | %nonassoc T_L_MPAR 97 | %nonassoc T_R_SPAR 98 | %nonassoc T_MINUS T_POS T_REVERSE 99 | %nonassoc T_ELSE 100 | %nonassoc T_VOID T_INT 101 | // 开始为program 102 | %start program 103 | %% 104 | 105 | program : stmts{ 106 | program = $1; 107 | #ifdef DEBUG_FLAG 108 | fprintf(stdout,"parse success\n"); 109 | #endif 110 | } 111 | ; 112 | 113 | stmts : stmt {$$ = new BlockAST(); $$->addStatement($1);} 114 | | stmts stmt {$1->addStatement($2);} 115 | ; 116 | 117 | stmt : var_decl ';' { 118 | #ifdef DEBUG_FLAG 119 | fprintf(stderr,"build var decl stmt\n"); 120 | #endif 121 | } 122 | | T_CONST var_decl ';' {$2->setIsConst(true);$$=$2;} 123 | | func_decl {$$ = $1;} 124 | | if_condition {$$ = $1;} 125 | | while_stmt {$$ = $1;} 126 | | ident T_ASSIGN expr ';' {$$ = new VariableAssignmentAST($1->identifier,$3);} 127 | | ident_arr T_ASSIGN expr ';' {$$ = new VariableArrAssignmentAST($1,$3);} 128 | | T_RETURN ';'{$$ = new ReturnStmtAST();} 129 | | T_RETURN expr ';'{$$ = new ReturnStmtAST($2);} 130 | | for_stmt {$$ = $1;} 131 | | T_OUT ';' {$$ = new OutStmtAST();} 132 | | T_CONTINUE ';' {$$ = new ContinueStmtAST();} 133 | | block {$$ = $1;} 134 | | ';' {} 135 | | expr ';' {$$ = new ExpressionStatementAST($1);} 136 | ; 137 | 138 | ident : T_IDENTIFIER { 139 | $$ = new IdentifierExprAST(*$1);} 140 | ; 141 | // a[xx][xx]... 142 | ident_arr : ident array_index { $$ = new IdentifierArrExprAST($1->identifier,$2);} 143 | 144 | // int a 145 | // int a = 123 146 | var_decl : ident ident { 147 | $$ = new VariableDeclarationAST( 148 | $1->identifier, 149 | $2 150 | ); 151 | } 152 | | ident ident T_ASSIGN expr {$$ = new VariableDeclarationAST($1->identifier,$2,$4);} 153 | | ident ident_arr { 154 | $$ = new VariableArrDeclarationAST( 155 | $1->identifier, 156 | $2 157 | ); 158 | } 159 | | ident ident_arr T_ASSIGN array_init_val {$$ = new VariableArrDeclarationAST($1->identifier,$2,$4);} 160 | | T_FUNC_SIGN T_LESS func_ptr_args T_GREATER ident{$$ = new FuncPtrAST(*$3,$5);} 161 | ; 162 | 163 | func_ptr_args: ident{$$ = new std::vector(); 164 | $$->push_back($1); } 165 | |func_ptr_args T_COMMA ident{$1->push_back($3);} 166 | ; 167 | // func() func(a,b) func(a) 168 | // a; 169 | // aidentifier,*$3); } 171 | | ident {$$ = $1;} 172 | | ident_arr {$$ = $1;} 173 | | T_SUB ident {$$ = new BinaryExprAST(BinaryType::sub,new IntegerExprAST(0),$2);} 174 | | number 175 | | T_L_SPAR expr T_R_SPAR {$$ = $2;} 176 | | expr T_ADD expr {$$ = new BinaryExprAST(BinaryType::add,$1,$3);} 177 | | expr T_SUB expr {$$ = new BinaryExprAST(BinaryType::sub,$1,$3);} 178 | | expr T_MUL expr {$$ = new BinaryExprAST(BinaryType::mul,$1,$3);} 179 | | expr T_DIV expr {$$ = new BinaryExprAST(BinaryType::divi,$1,$3);} 180 | | expr T_MOD expr {$$ = new BinaryExprAST(BinaryType::mod,$1,$3);} 181 | | expr T_LESS expr {$$ = new BinaryExprAST(BinaryType::less,$1,$3);} 182 | | expr T_GREATER expr {$$ = new BinaryExprAST(BinaryType::greater,$1,$3);} 183 | | expr T_LESS_EQU expr {$$ = new BinaryExprAST(BinaryType::less_equ,$1,$3);} 184 | | expr T_GREATER_EQU expr {$$ = new BinaryExprAST(BinaryType::greater_equ,$1,$3);} 185 | | expr T_EQU expr {$$ = new BinaryExprAST(BinaryType::equ,$1,$3);} 186 | | expr T_N_EQU expr {$$ = new BinaryExprAST(BinaryType::n_equ,$1,$3);} 187 | | expr T_AND expr {$$ = new BinaryExprAST(BinaryType::AND,$1,$3);} 188 | | expr T_OR expr {$$ = new BinaryExprAST(BinaryType::OR,$1,$3);} 189 | | str {$$ = $1;} 190 | | T_NULL {$$ = new NullExprAST();} 191 | | T_TRUE {$$ = new BoolExprAST(true);} 192 | | T_FALSE {$$ = new BoolExprAST(false);} 193 | ; 194 | //aivec 195 | array_index : T_L_MPAR T_R_MPAR {$$ = new vector(); $$->push_back(NIL);} 196 | | T_L_MPAR expr T_R_MPAR {$$ = new vector(); $$->push_back($2);} 197 | | T_L_MPAR T_R_MPAR array_index{$3->insert($3->begin(),NIL); $$ = $3;} 198 | | T_L_MPAR expr T_R_MPAR array_index {$4->insert($4->begin(),$2); $$ = $4;} 199 | 200 | call_args : %empty {$$ = new std::vector();} 201 | | expr {$$ = new std::vector();$$->push_back($1);} 202 | | call_args T_COMMA expr {$1->push_back($3);} 203 | ; 204 | 205 | number : T_DOUBLE 206 | { 207 | $$ = new DoubleExprAST($1); 208 | } 209 | | T_INTEGER { 210 | $$ = new IntegerExprAST($1); 211 | } 212 | ; 213 | 214 | block : T_L_LPAR stmts T_R_LPAR {$$ = $2;} 215 | | T_L_LPAR T_R_LPAR {$$ = new BlockAST();} 216 | 217 | // int func_name(expr1,...){block} 218 | func_decl : ident ident T_L_SPAR func_args T_R_SPAR block 219 | { 220 | PrototypeAST* proto = new PrototypeAST($1->identifier,$2->identifier,*$4); 221 | BlockAST* body = $6; 222 | $$ = new FunctionAST(proto,body); 223 | //printf("build function %s \n",$2->identifier.c_str()); 224 | } 225 | 226 | func_args : %empty { $$ = new std::vector(); } 227 | | var_decl { $$ = new std::vector(); 228 | $$->push_back($1); } //$1为stmt类型,但是我们要取子类vdeclar类型 229 | | func_args T_COMMA var_decl { $1->push_back($3); } 230 | ; 231 | 232 | if_condition : T_IF T_L_SPAR expr T_R_SPAR block {$$ = new ConditionAST($3,$5,nullptr);} 233 | | T_IF T_L_SPAR expr T_R_SPAR block T_ELSE block {$$ = new ConditionAST($3,$5,$7);} 234 | ; 235 | 236 | for_stmt : T_FOR T_L_SPAR for_args ';' for_args ';' for_args T_R_SPAR block 237 | { 238 | $$ = new ForExprAST($3,$5,$7,$9); 239 | } 240 | 241 | for_args : var_decl {$$ = $1;} 242 | | ident T_ASSIGN expr {$$ = new VariableAssignmentAST($1->identifier,$3);} 243 | | expr {$$ = $1;} 244 | ; 245 | 246 | while_stmt : T_WHILE T_L_SPAR expr T_R_SPAR block {$$ = new WhileStmtAST($3,$5);} 247 | 248 | // {{1,2,3,4},{1,123,23,3}}; 249 | array_init_val : expr {$$ = new vector(); $$->push_back($1);} 250 | | T_L_LPAR array_init_list T_R_LPAR {$$ = $2;} 251 | | T_L_LPAR T_R_LPAR {$$ = new vector();} 252 | ; 253 | 254 | array_init_list : array_init_list T_COMMA array_init_val {$$ = $1; $1->insert($1->end(),$3->begin(),$3->end());} 255 | | array_init_val {$$ = $1;} 256 | 257 | str : T_STR {$$ = new StringExprAST($$);} 258 | 259 | //module_stmt : T_MODULE 260 | %% 261 | 262 | BlockAST* program = nullptr; 263 | 264 | BlockAST* run_parser(std::string path) { 265 | FILE* yyin = fopen(path.c_str(), "r+"); 266 | program = nullptr; 267 | int ret = yyparse(); 268 | if (ret != 0) 269 | program = nullptr; 270 | fclose(yyin); 271 | return program; 272 | } 273 | 274 | -------------------------------------------------------------------------------- /parser/StringReader.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/3/15. 3 | // 4 | 5 | #include "StringReader.h" 6 | 7 | int StringReader::getchar() { 8 | if (cindex >= str->length()) { 9 | return END_OF_FILE; 10 | } 11 | char ch = str->at(cindex++); 12 | if (ch == '\n') { 13 | lineno++; 14 | colno = 0; 15 | } else { 16 | colno++; 17 | } 18 | return ch; 19 | } 20 | 21 | int StringReader::seek() { 22 | if (cindex >= str->length()) { 23 | return END_OF_FILE; 24 | } 25 | return str->at(cindex); 26 | } 27 | 28 | unsigned int StringReader::getLineNo() { 29 | return lineno; 30 | } 31 | 32 | unsigned int StringReader::getCCol() { 33 | return colno; 34 | } 35 | 36 | StringReader::StringReader(std::string *str) : str(str) {} 37 | -------------------------------------------------------------------------------- /parser/StringReader.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/3/15. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_STRINGREADER_H 6 | #define SYSYPLUS_COMPILER_STRINGREADER_H 7 | 8 | #include "Global.h" 9 | #include "IFileReader.h" 10 | 11 | /** 12 | * 使用字符串传入分析 13 | */ 14 | class StringReader : public IFileReader { 15 | 16 | std::string* str; 17 | 18 | unsigned int lineno = 0; 19 | unsigned int colno = 0; 20 | unsigned int cindex = 0; 21 | 22 | public: 23 | explicit StringReader(std::string *str); 24 | 25 | int getchar() override; 26 | 27 | int seek() override; 28 | 29 | unsigned int getLineNo() override; 30 | 31 | unsigned int getCCol() override; 32 | }; 33 | 34 | 35 | #endif //SYSYPLUS_COMPILER_STRINGREADER_H 36 | -------------------------------------------------------------------------------- /pass/RecursiveToLoopPass.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/2/26. 3 | // 4 | 5 | #include "RecursiveToLoopPass.h" 6 | 7 | char RecursiveToLoopPass::ID = 0; 8 | 9 | // example: 10 | //int loop_echo(int a,int b,int times){ 11 | // if (times <= 0){ 12 | // ret b; 13 | // } 14 | // ret loop_echo(b,a+b,times-1); 15 | //} 16 | 17 | /// 满足条件:最后一条是递归、标记为了tail 18 | bool RecursiveToLoopPass::runOnFunction(Function &F) { 19 | auto rit = F.getBasicBlockList().rbegin(); 20 | rit++; 21 | if (rit->empty()) { 22 | return false; 23 | } 24 | return false; 25 | } 26 | 27 | RecursiveToLoopPass::RecursiveToLoopPass() : FunctionPass(ID) { 28 | } 29 | -------------------------------------------------------------------------------- /pass/RecursiveToLoopPass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/2/26. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_RECURSIVETOLOOPPASS_H 6 | #define SYSYPLUS_COMPILER_RECURSIVETOLOOPPASS_H 7 | 8 | #include "Global.h" 9 | 10 | using namespace llvm; 11 | 12 | class RecursiveToLoopPass : public FunctionPass { 13 | static char ID; 14 | public: 15 | RecursiveToLoopPass(); 16 | 17 | bool runOnFunction(Function &F) override; 18 | }; 19 | 20 | 21 | #endif //SYSYPLUS_COMPILER_RECURSIVETOLOOPPASS_H 22 | -------------------------------------------------------------------------------- /pass/TimeAnalysisPass.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/2/24. 3 | // 4 | 5 | #include "TimeAnalysisPass.h" 6 | 7 | #include "ErrHelper.h" 8 | 9 | char TimeAnalysisPass::ID = 0; 10 | 11 | bool TimeAnalysisPass::runOnFunction(Function &func) { 12 | // 确保可以使用printf 13 | auto printfFunc = ExternFunctionHandler::getOrAddPrintfFunc(*TheContext, *TheModule); 14 | if (printfFunc == NIL) { 15 | LogError("函数printf未找到,设置的时间分析插值失效"); 16 | return false; 17 | } 18 | auto bb_it = func.getBasicBlockList().begin(); 19 | Builder->SetInsertPoint(&bb_it->front()); 20 | 21 | // auto st_mem = Builder->CreateAlloca(getTypeFromStr("long"),NIL,LabelPrefix+string("st")); 22 | auto call_v = Builder->CreateCall(ExternFunctionHandler::getOrAddTimeFunc(*TheContext, *TheModule), 23 | ConstantExpr::getNullValue(getTypeFromStr("long")->getPointerTo())); 24 | auto call_v_mem = Builder->CreateAlloca(getTypeFromStr("long")); 25 | Builder->CreateStore(call_v, call_v_mem); 26 | 27 | auto bb_it_end = func.getBasicBlockList().rbegin(); 28 | Builder->SetInsertPoint(&(*bb_it_end->rbegin())); 29 | auto call_v_2 = Builder->CreateCall(ExternFunctionHandler::getOrAddTimeFunc(*TheContext, *TheModule), 30 | ConstantExpr::getNullValue(getTypeFromStr("long")->getPointerTo())); 31 | auto call_v_2_mem = Builder->CreateAlloca(getTypeFromStr("long")); 32 | Builder->CreateStore(call_v_2, call_v_2_mem); 33 | 34 | auto time_v = Builder->CreateSub(Builder->CreateLoad(call_v_2_mem), Builder->CreateLoad(call_v_mem)); 35 | auto time_mem = Builder->CreateAlloca(getTypeFromStr("long")); 36 | Builder->CreateStore(time_v, time_mem); 37 | 38 | auto stmt = TheModule->getGlobalVariable(LabelPrefix + string(func.getName()) + string("time_cost")); 39 | if (stmt == NIL) { 40 | stmt = Builder->CreateGlobalString(string("function<"+func.getName().str())+string(">: %ld(ms)\n"), LabelPrefix + string("time_cost")); 41 | } 42 | std::vector args_vec; 43 | args_vec.push_back(ConstantInt::get(getTypeFromStr("int"), 0)); 44 | args_vec.push_back(ConstantInt::get(getTypeFromStr("int"), 0)); 45 | auto stmt_ptr = Builder->CreateInBoundsGEP(stmt,{ConstantInt::get(getTypeFromStr("int"),0),ConstantInt::get(getTypeFromStr("int"),0)}); 46 | Builder->CreateCall(printfFunc, 47 | {stmt_ptr, Builder->CreateLoad(time_mem)}); 48 | return false; 49 | } 50 | 51 | TimeAnalysisPass::TimeAnalysisPass() : FunctionPass(ID) { 52 | } 53 | -------------------------------------------------------------------------------- /pass/TimeAnalysisPass.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by bytedance on 2021/2/24. 3 | // 4 | 5 | #ifndef SYSYPLUS_COMPILER_TIMEANALYSISPASS_H 6 | #define SYSYPLUS_COMPILER_TIMEANALYSISPASS_H 7 | 8 | #include "Global.h" 9 | 10 | #include "extern/ExternFunctionHandler.h" 11 | 12 | struct TimeAnalysisPass : public FunctionPass{ 13 | static char ID; 14 | 15 | public: 16 | TimeAnalysisPass(); 17 | 18 | bool runOnFunction(Function &func) override; 19 | }; 20 | 21 | #endif //SYSYPLUS_COMPILER_TIMEANALYSISPASS_H 22 | -------------------------------------------------------------------------------- /stat.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/5/3. 3 | // 4 | 5 | #include "stat.h" 6 | 7 | #include 8 | 9 | namespace webc { 10 | namespace lex { 11 | int token_num = 0; 12 | int line_num = 0; 13 | } 14 | namespace parser { 15 | int condition_num = 0; 16 | int loop_num = 0; 17 | int func_num = 0; 18 | int func_params_num = 0; 19 | int func_pointers_num = 0; 20 | } 21 | namespace ast { 22 | int layers = 0; 23 | int nodes_num = 0; 24 | } 25 | 26 | void outputStats() { 27 | printf("WebC Code Stats:\nlexer:tokennum:%d,linenum:%d\n" 28 | "parser:condition:%d,loop:%d,funcs:%d,fparam:%d,fpoint:%d\n" 29 | "ast:layers:%d,node_num:%d\n", lex::token_num, lex::line_num, parser::condition_num, parser::loop_num, 30 | parser::func_num, parser::func_params_num, parser::func_pointers_num, ast::layers, ast::nodes_num); 31 | } 32 | } -------------------------------------------------------------------------------- /stat.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/5/3. 3 | // 4 | 5 | #ifndef WEBC_COMPILER_STAT_H 6 | #define WEBC_COMPILER_STAT_H 7 | 8 | #define UPDATE_MAX_LAYERS(x) webc::ast::layers = max(x,webc::ast::layers) 9 | 10 | namespace webc { 11 | namespace lex { 12 | extern int token_num; 13 | extern int line_num; 14 | } 15 | namespace parser { 16 | extern int condition_num; 17 | extern int loop_num; 18 | extern int func_num; 19 | extern int func_params_num; 20 | extern int func_pointers_num; 21 | } 22 | namespace ast { 23 | extern int layers; 24 | extern int nodes_num; 25 | } 26 | 27 | /** 28 | * 输出统计结果 29 | */ 30 | void outputStats(); 31 | } 32 | 33 | #endif //WEBC_COMPILER_STAT_H 34 | -------------------------------------------------------------------------------- /test.kl: -------------------------------------------------------------------------------- 1 | def average(x y) (x+y)/2; 2 | 3 | 4 | def main() average(3,4); -------------------------------------------------------------------------------- /test/case/webc_test/gcd.webc: -------------------------------------------------------------------------------- 1 | // 保证 x > y 2 | int gcd(int x, int y){ 3 | if (x < y){ 4 | int tmp = x; 5 | x = y; 6 | y = tmp; 7 | } 8 | if (y){ 9 | ret gcd(y, x%y); 10 | } el { 11 | ret x; 12 | } 13 | ret 0; 14 | } 15 | 16 | int main(){ 17 | echo('4与10的最大公约数是',gcd(4,10)); 18 | } -------------------------------------------------------------------------------- /test/case/webc_test/helloserver.webc: -------------------------------------------------------------------------------- 1 | str hello() { 2 | ret 'hello from compiler'; 3 | } 4 | 5 | int main() { 6 | echo('init...'); 7 | str host = '0.0.0.0'; 8 | int port = 9000; 9 | int core = 2; 10 | echo('get server...'); 11 | int server_id = getServer(host, port, core); 12 | echo('server id is', server_id); 13 | addUrlHandler(server_id, 'GET', '/hello', 'text/html', hello); 14 | echo('start server in host', host, ',port is', port); 15 | startServer(server_id); 16 | ret 0; 17 | } -------------------------------------------------------------------------------- /test/case/webc_test/qsort.webc: -------------------------------------------------------------------------------- 1 | int qsort(int a[],int left,int right){ 2 | if (right <= left){ 3 | ret -1; 4 | } 5 | int base = a[left]; 6 | int j = left; 7 | int k = right; 8 | echo('begin wh'); 9 | wh(j=base && j
 
 
地区 天气
石家庄 24°C
承德 21°C
秦皇岛 20°C
'; 4 | } 5 | 6 | str getWeatherJsonData() { 7 | str ans = query_db('select * from weather'); 8 | echo('database is ', ans); 9 | ret ans; 10 | } 11 | 12 | 13 | int main() { 14 | echo('init...'); 15 | connect_db('39.107.226.2', 'weather', 'jintao123', 'weather', 3306, 'utf8'); 16 | str host = '0.0.0.0'; 17 | int port = 9000; 18 | int core = 4; 19 | echo('get server...'); 20 | int server_id = getServer(host, port, core); 21 | echo('server id is', server_id); 22 | addUrlHandler(server_id, 'GET', '/api/getWeather', 'text/plain', getWeatherJsonData); 23 | addUrlHandler(server_id, 'GET', '/', 'text/html', getWeatherHtml); 24 | echo('start server in host', host, ',port is', port); 25 | startServer(server_id); 26 | ret 27 | 0; 28 | } 29 | -------------------------------------------------------------------------------- /test/test1.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Created by 金韬 on 2021/2/1. 3 | // 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | extern "C" { 10 | void myfunc(int (*my)()) { 11 | my(); 12 | } 13 | 14 | int ok() { 15 | return 0; 16 | } 17 | } 18 | 19 | 20 | int main() { 21 | myfunc(ok); 22 | } 23 | //class A { 24 | // public: 25 | // int a; 26 | // int b; 27 | // int print() { 28 | // return a; 29 | // } 30 | // static int print2(){ 31 | // return 5; 32 | // } 33 | //}; 34 | // 35 | // 36 | //int af(int a){ 37 | // return af(a-3) + af(a-2); 38 | //} 39 | // 40 | //int get(int maxv) { 41 | // if (maxv > 0) { 42 | // return get(maxv - 1); 43 | // } 44 | // return maxv; 45 | //} 46 | // 47 | //int main() { 48 | // int a; 49 | // printf("%d",a); 50 | // A::print2(); 51 | //} -------------------------------------------------------------------------------- /ui/css/main.css: -------------------------------------------------------------------------------- 1 | /*#code {*/ 2 | /* font: 15px "Monospace";*/ 3 | /*}*/ 4 | 5 | * { 6 | font-size: 1.25em; 7 | } -------------------------------------------------------------------------------- /ui/widgets.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by kingtous on 2021/2/12. 3 | // 用于创建各种窗口、ui 4 | // mail: kingtous@qq.com 5 | // 6 | 7 | #ifndef SYSYPLUS_COMPILER_WIDGETS_H 8 | #define SYSYPLUS_COMPILER_WIDGETS_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "compiler/Compiler.h" 23 | 24 | #define WINDOW_NAME "SySyCompiler By Kingtous" 25 | #define BUILD_PAGE_ID 0 26 | #define RUNTIME_PAGE_ID 1 27 | #define STATIC_ANALYSIS_PAGE_ID 2 28 | 29 | using namespace Gtk; 30 | using namespace Glib; 31 | using namespace Gio; 32 | namespace pt = boost::posix_time; 33 | 34 | extern Glib::RefPtr m_app; 35 | 36 | /** 37 | * 向UI打印日志 38 | * @param Str 39 | */ 40 | void logOnUi(const char *Str); 41 | 42 | /** 43 | * 初始化窗口 44 | */ 45 | int initWindow(int argc, 46 | char **argv, 47 | const char *glade_path, 48 | const char *window_name); 49 | 50 | /** 51 | * 写入文件 52 | * @param file_ptr 53 | * @param content 54 | * @return 55 | */ 56 | long writeFile(RefPtr file_ptr, const std::string &content); 57 | 58 | /** 59 | * 60 | * @param file_ptr 61 | * @param buffer 62 | * @param sz 63 | * @return 64 | */ 65 | long writeFile(RefPtr file_ptr, const void *buffer, long sz); 66 | 67 | class CompilerWindow : public Gtk::ApplicationWindow { 68 | public: 69 | enum M_STATUS { 70 | IN_NONE, 71 | IN_EDIT, 72 | IN_BUILD, 73 | IN_RUNNING, 74 | }; 75 | public: 76 | CompilerWindow(); 77 | 78 | CompilerWindow(BaseObjectType *cobject, const Glib::RefPtr &builder); 79 | 80 | /** 81 | * 初始化 82 | */ 83 | void init(); 84 | 85 | /** 86 | * 初始化菜单 87 | */ 88 | void initMenuBar(); 89 | 90 | /** 91 | * 初始化代码编辑器 92 | */ 93 | void initCodeForm(); 94 | 95 | void on_menu_file_new_activate(); 96 | 97 | void onFileOpen(); 98 | 99 | void onFileExit(); 100 | 101 | void setTitle(const ustring &str); 102 | 103 | void setLatestMessage(const ustring &msg); 104 | 105 | void log(const char *string, const M_STATUS &state = M_STATUS::IN_NONE); 106 | 107 | void setStatus(M_STATUS status); 108 | 109 | /** 110 | * 编译 111 | */ 112 | int buildSrc(const set &opts, 113 | const ustring &code, const ustring &output_path, void (*onSuccess)(CompilerWindow *) = nullptr); 114 | 115 | M_STATUS getMState() const; 116 | 117 | ~CompilerWindow() noexcept override; 118 | 119 | private: 120 | RefPtr file_action_group; 121 | ImageMenuItem *m_menu_file_new; 122 | ImageMenuItem *m_menu_file_open; 123 | ImageMenuItem *m_menu_file_save; 124 | ImageMenuItem *m_menu_file_saveas; 125 | ImageMenuItem *m_menu_file_quit; 126 | ImageMenuItem *m_menu_help_about; 127 | ImageMenuItem *m_menu_build_compile_only; 128 | ImageMenuItem *m_menu_build_compile_obj; 129 | ImageMenuItem *m_menu_build_run; 130 | ImageMenuItem *m_menu_build_compile_asm; 131 | TextView *m_textview; 132 | AboutDialog *m_main_about; 133 | FileChooserDialog *m_main_filechooserdialog; 134 | Label *m_main_bottom_status_label; 135 | Label *m_main_code_pos_label; 136 | Notebook *m_main_build_notebook; 137 | TextView *m_main_runtime_console; 138 | TextView *m_main_build_console; 139 | TextView *m_main_static_analysis_console; 140 | ScrolledWindow *m_main_code_window; 141 | Expander *m_main_control_expander; 142 | // 暂存数据 143 | RefPtr m_file; 144 | // 状态机 145 | volatile M_STATUS m_state; 146 | // buffer 147 | Gsv::View *m_gsv; 148 | RefPtr m_lm; 149 | Pango::FontDescription *m_font_desc; 150 | // 1个守护线程,1个编译线程,一个运行监测线程 151 | boost::asio::thread_pool threads{3}; 152 | bool m_is_dirty = false; 153 | pt::ptime m_last_edit_time; 154 | Glib::Mutex *log_mutex; 155 | RefPtr m_tip_buffer; 156 | RefPtr m_completion_words; 157 | RefPtr m_style_scheme_manager; 158 | }; 159 | 160 | class KingtousCompletionProvider : public Gsv::CompletionProvider { 161 | public: 162 | private: 163 | bool match_vfunc(const RefPtr &context) const override; 164 | }; 165 | 166 | #endif //SYSYPLUS_COMPILER_WIDGETS_H 167 | --------------------------------------------------------------------------------