├── .clang-format ├── .clang-tidy ├── .github └── workflows │ └── workflow.yml ├── .gitignore ├── CMakeLists.txt ├── CMakePresets.json ├── LICENSE ├── README.md ├── cmake ├── 3rd.cmake ├── compile_config.cmake ├── functions.cmake └── gcc.cmake ├── doc └── CMakeLists.txt ├── src ├── CMakeLists.txt ├── CMakeLists_old.txt ├── cxxabi.cpp ├── entry.c ├── format.c ├── include │ ├── cxxabi.h │ ├── iostream │ ├── libcxxrt.h │ ├── port.h │ ├── stdarg.h │ ├── stddef.h │ ├── stdint.h │ ├── stdio.h │ ├── stdlib.h │ ├── string │ ├── string.h │ └── unistd.h ├── iostream.cpp ├── link.ld ├── malloc.c ├── new_delete.cpp ├── stdio.c ├── string.c ├── string.cpp └── test.cpp ├── test ├── CMakeLists.txt ├── integration_test │ ├── CMakeLists.txt │ └── example.cpp ├── system_test │ ├── CMakeLists.txt │ └── example.cpp └── unit_test │ ├── CMakeLists.txt │ └── example.cpp └── tools ├── cppcheck-suppressions.xml └── startup.nsh /.clang-format: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # .clang-format for MRNIU/libcxxrt. 6 | 7 | --- 8 | # @version clang-format version 15 9 | # @see https://clang.llvm.org/docs/ClangFormatStyleOptions.html 10 | # 使用 LLVM 规范 11 | BasedOnStyle: LLVM 12 | ... 13 | -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # .clang-tidy for MRNIU/libcxxrt. 6 | 7 | --- 8 | Checks: '-*,\ 9 | bugprone-*,\ 10 | clang-analyzer-*,\ 11 | cppcoreguidelines-*,\ 12 | hicpp-*,\ 13 | llvm-*,\ 14 | misc-* 15 | modernize-*,\ 16 | performance-*,\ 17 | portability-*,\ 18 | readability-*,\ 19 | -cppcoreguidelines-pro-type-reinterpret-cast' 20 | HeaderFilterRegex: '^${sourceDir}/src' 21 | AnalyzeTemporaryDtors: true 22 | ... 23 | -------------------------------------------------------------------------------- /.github/workflows/workflow.yml: -------------------------------------------------------------------------------- 1 | # This file is a part of MRNIU/libcxxrt 2 | # (https://github.com/MRNIU/libcxxrt). 3 | # 4 | # workflow.yml for MRNIU/libcxxrt. 5 | 6 | name: build 7 | 8 | on: 9 | - push 10 | - pull_request 11 | - release 12 | 13 | env: 14 | CMAKE_BUILD_TYPE: Release 15 | 16 | jobs: 17 | build_docs: 18 | name: Build and publish documentation 19 | runs-on: ubuntu-latest 20 | permissions: 21 | contents: write 22 | steps: 23 | - uses: actions/checkout@v3 24 | 25 | - name: Install dependencies 26 | run: | 27 | sudo apt update 28 | sudo apt install --fix-missing -y doxygen graphviz clang-format clang-tidy cppcheck lcov 29 | sudo apt install --fix-missing -y gcc g++ gcc-riscv64-linux-gnu g++-riscv64-linux-gnu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 30 | 31 | - name: Build 32 | run: | 33 | cmake --preset=build 34 | cmake --build build --target doc 35 | 36 | - name: Publish 37 | uses: peaceiris/actions-gh-pages@v3 38 | with: 39 | github_token: ${{ secrets.GITHUB_TOKEN }} 40 | publish_dir: ${{github.workspace}}/doc/html 41 | 42 | build_ubuntu: 43 | runs-on: ubuntu-latest 44 | steps: 45 | - uses: actions/checkout@v3 46 | 47 | - name: Install dependencies 48 | run: | 49 | sudo apt update 50 | sudo apt install --fix-missing -y doxygen graphviz clang-format clang-tidy cppcheck lcov 51 | sudo apt install --fix-missing -y gcc g++ gcc-riscv64-linux-gnu g++-riscv64-linux-gnu gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 52 | 53 | - name: build 54 | run: | 55 | cmake --preset=build 56 | cmake --build build --target coverage 57 | 58 | - name: Upload coverage reports to Codecov 59 | uses: codecov/codecov-action@v3 60 | with: 61 | files: build/coverage/coverage.info 62 | verbose: true 63 | 64 | # build_osx: 65 | # runs-on: macos-latest 66 | # steps: 67 | # - name: get code 68 | # uses: actions/checkout@v3 69 | # 70 | # - name: setup toolchain 71 | # shell: bash 72 | # run: | 73 | # brew install x86_64-elf-gcc 74 | # brew tap riscv-software-src/riscv 75 | # brew install riscv-tools 76 | # 77 | # - name: make build dir 78 | # shell: bash 79 | # run: | 80 | # mkdir ${{github.workspace}}/build 81 | # 82 | # - name: osx-i386 83 | # shell: bash 84 | # working-directory: ${{github.workspace}}/build 85 | # run: | 86 | # cmake -DTOOLCHAIN_PREFIX=x86_64-elf- -DCMAKE_C_COMPILER=x86_64-elf-gcc -DCMAKE_CXX_COMPILER=x86_64-elf-g++ -DARCH=i386 -DCMAKE_BUILD_TYPE=RELEASE -DHAVE_FLAG_SEARCH_PATHS_FIRST=0 .. 87 | # make 88 | # rm -rf ./* 89 | # 90 | # - name: osx-x86_64 91 | # shell: bash 92 | # working-directory: ${{github.workspace}}/build 93 | # run: | 94 | # cmake -DTOOLCHAIN_PREFIX=x86_64-elf- -DCMAKE_C_COMPILER=x86_64-elf-gcc -DCMAKE_CXX_COMPILER=x86_64-elf-g++ -DARCH=x86_64 -DCMAKE_BUILD_TYPE=RELEASE -DHAVE_FLAG_SEARCH_PATHS_FIRST=0 .. 95 | # make 96 | # rm -rf ./* 97 | # 98 | # - name: osx-riscv64 99 | # shell: bash 100 | # working-directory: ${{github.workspace}}/build 101 | # run: | 102 | # cmake -DTOOLCHAIN_PREFIX=riscv64-unknown-elf- -DCMAKE_C_COMPILER=riscv64-unknown-elf-gcc -DCMAKE_CXX_COMPILER=riscv64-unknown-elf-g++ -DARCH=riscv64 -DCMAKE_BUILD_TYPE=RELEASE -DHAVE_FLAG_SEARCH_PATHS_FIRST=0 .. 103 | # make 104 | # rm -rf ./* 105 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # .gitignore for MRNIU/libcxxrt. 6 | 7 | .DS_Store 8 | build 9 | build_aarch64 10 | build_riscv64 11 | build_x86_64 12 | doc/html 13 | cmake-build* 14 | .gdbinit 15 | tools/opensbi/build 16 | .vscode 17 | .idea 18 | 3rd 19 | Doxyfile 20 | 21 | # Prerequisites 22 | *.d 23 | 24 | # Compiled Object files 25 | *.slo 26 | *.lo 27 | *.o 28 | *.obj 29 | 30 | # Precompiled Headers 31 | *.gch 32 | *.pch 33 | 34 | # Compiled Dynamic libraries 35 | *.so 36 | *.dylib 37 | *.dll 38 | 39 | # Fortran module files 40 | *.mod 41 | *.smod 42 | 43 | # Compiled Static libraries 44 | *.lai 45 | *.la 46 | *.a 47 | *.lib 48 | 49 | # Executables 50 | *.exe 51 | *.out 52 | *.app 53 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置最小 cmake 版本 8 | cmake_minimum_required(VERSION 3.27 FATAL_ERROR) 9 | 10 | # 设置项目名与版本 11 | project( 12 | libcxxrt 13 | VERSION 0.0.1 14 | ) 15 | 16 | # 禁止原地编译 17 | if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR}) 18 | # 如果你看到这句话,cmake 此时已经在根目录下生成了一些临时文件,你需要删除它们 19 | # CMakeFiles, CMakeCache.txt 20 | message( 21 | FATAL_ERROR 22 | "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there." 23 | ) 24 | endif () 25 | 26 | # 设置辅助 cmake 脚本路径 27 | list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") 28 | 29 | # 导入函数 30 | include(functions) 31 | 32 | # 导入第三方依赖 33 | include(3rd) 34 | 35 | # 导入编译配置 36 | include(compile_config) 37 | 38 | # 添加要编译的目录 39 | add_subdirectory(${PROJECT_SOURCE_DIR}/src) 40 | add_subdirectory(${PROJECT_SOURCE_DIR}/test) 41 | add_subdirectory(${PROJECT_SOURCE_DIR}/doc) 42 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 6, 3 | "cmakeMinimumRequired": { 4 | "major": 3, 5 | "minor": 27, 6 | "patch": 0 7 | }, 8 | "configurePresets": [ 9 | { 10 | "name": "std", 11 | "description": "This preset makes sure the project actually builds with at least the specified standard", 12 | "hidden": true, 13 | "cacheVariables": { 14 | "CMAKE_C_EXTENSIONS": "OFF", 15 | "CMAKE_C_STANDARD": "17", 16 | "CMAKE_C_STANDARD_REQUIRED": "ON", 17 | "CMAKE_CXX_EXTENSIONS": "OFF", 18 | "CMAKE_CXX_STANDARD": "20", 19 | "CMAKE_CXX_STANDARD_REQUIRED": "ON" 20 | } 21 | }, 22 | { 23 | "name": "configurePresets_base", 24 | "hidden": true, 25 | "inherits": [ 26 | "std" 27 | ], 28 | "condition": true, 29 | "displayName": "configurePresets_base", 30 | "description": "base configurePresets", 31 | "generator": "Unix Makefiles", 32 | "toolchainFile": "${sourceDir}/cmake/gcc.cmake", 33 | "binaryDir": "${sourceDir}/build", 34 | "installDir": "", 35 | "cacheVariables": { 36 | "CMAKE_VERBOSE_MAKEFILE": { 37 | "type": "BOOL", 38 | "value": "TRUE" 39 | }, 40 | "CMAKE_EXPORT_COMPILE_COMMANDS": { 41 | "type": "BOOL", 42 | "value": "ON" 43 | }, 44 | "CMAKE_BUILD_TYPE": { 45 | "type": "STRING", 46 | "value": "Debug" 47 | }, 48 | "COVERAGE_OUTPUT_DIR": { 49 | "type": "STRING", 50 | "value": "coverage" 51 | } 52 | } 53 | }, 54 | { 55 | "name": "build", 56 | "hidden": false, 57 | "inherits": [ 58 | "configurePresets_base" 59 | ], 60 | "displayName": "build libcxxrt", 61 | "description": "build libcxxrt" 62 | } 63 | ] 64 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libcxxrt 2 | 3 | TODO 4 | 5 | 添加对裸机环境的支持 6 | 7 | 来自 程序员的自我修养——链接、装载与库 8 | 9 | 简单 C/C++ 运行时库实现 10 | Simple C/C++ run time implementation 11 | 12 | ## 支持 Support 13 | 14 | | | X86 | X64 | ARM | AARCH64 | 15 | | :-----: | :--: | :--: | :--: | :-----: | 16 | | WIN10 | | | | | 17 | | OSX | | ✅ | | | 18 | | Manjaro | | ✅ | | | 19 | | Ubuntu | | ✅ | | | 20 | 21 | 22 | 23 | ```c++ 24 | // io 25 | FILE * fopen(const char *filename, const char *mode); 26 | int64_t fread(void *buffer, uint64_t size, uint64_t count, FILE *stream); 27 | int64_t fwrite(const void *buffer, uint64_t size, uint64_t count, FILE *stream); 28 | int64_t fclose(FILE *fp); 29 | int64_t fseek(FILE *fp, uint64_t offest, int set); 30 | int fputc(int c, FILE *stream); 31 | int fputs(const char *str, FILE *stream); 32 | int printf(const char *format, ...); 33 | int fprintf(FILE *stream, const char *format, ...); 34 | // string 35 | int8_t strcmp(const char *src, const char *dst); 36 | char * strcpy(char *dest, const char *src); 37 | uint64_t strlen(const char *str); 38 | void memset(void *dest, uint8_t val, uint32_t len); 39 | void bzero(void *dest, uint32_t len); 40 | // stdlib 41 | void free(void *ptr); 42 | void *malloc(size_t size); 43 | char *itoa(int n, char *str, int radix); 44 | int atexit(atexit_func_t func); 45 | // iostream 46 | // ofstream 47 | class ofstream { 48 | private: 49 | protected: 50 | FILE *fp; 51 | ofstream(const ofstream &lhs); 52 | 53 | public: 54 | enum openmode : uint8_t { 55 | in = 1, 56 | out = 2, 57 | binary = 4, 58 | trunc = 8, 59 | }; 60 | ofstream(void); 61 | explicit ofstream(const char * filename, 62 | ofstream::openmode md = ofstream::out); 63 | ~ofstream(void); 64 | ofstream &operator<<(char c); 65 | ofstream &operator<<(int n); 66 | ofstream &operator<<(const char *lhs); 67 | ofstream &operator<<(ofstream &(*)(ofstream &)); 68 | 69 | void open(const char *filename, ofstream::openmode md = ofstream::out); 70 | void close(void); 71 | ofstream &write(const char *buf, unsigned size); 72 | }; 73 | 74 | // string 75 | class string { 76 | private: 77 | size_t len; 78 | char * pbuf; 79 | 80 | protected: 81 | public: 82 | explicit string(const char *str); 83 | string(const string &s); 84 | ~string(void); 85 | string & operator=(const string &s); 86 | string & operator=(const char *s); 87 | const char &operator[](size_t idx) const; 88 | char & operator[](size_t idx); 89 | const char *c_str(void) const; 90 | size_t length(void) const; 91 | size_t size(void) const; 92 | }; 93 | ``` 94 | 95 | 96 | ## 使用方法 Usage 97 | 98 | ```shell 99 | git clone https://github.com/MRNIU/MiniCRT.git 100 | cd MiniCRT 101 | mkdir build 102 | cmake .. 103 | make 104 | ``` 105 | 106 | 构建完成后,库文件保存在 build/lib/libminicrt.a 107 | 测试程序为 build/bin/test 108 | 109 | ## TODO 110 | 111 | 多平台适配 112 | 113 | -------------------------------------------------------------------------------- /cmake/3rd.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # 3rd.cmake for MRNIU/libcxxrt. 6 | # 依赖管理 7 | 8 | # 设置依赖下载路径 9 | set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/3rd) 10 | # 优先使用本地文件 11 | set(CPM_USE_LOCAL_PACKAGES True) 12 | # https://github.com/cpm-cmake/CPM.cmake 13 | # -------- get_cpm.cmake -------- 14 | set(CPM_DOWNLOAD_VERSION 0.38.2) 15 | 16 | if (CPM_SOURCE_CACHE) 17 | set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 18 | elseif (DEFINED ENV{CPM_SOURCE_CACHE}) 19 | set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 20 | else () 21 | set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake") 22 | endif () 23 | 24 | # Expand relative path. This is important if the provided path contains a tilde (~) 25 | get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE) 26 | 27 | function(download_cpm) 28 | message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}") 29 | file(DOWNLOAD 30 | https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake 31 | ${CPM_DOWNLOAD_LOCATION} 32 | ) 33 | endfunction() 34 | 35 | if (NOT (EXISTS ${CPM_DOWNLOAD_LOCATION})) 36 | download_cpm() 37 | else () 38 | # resume download if it previously failed 39 | file(READ ${CPM_DOWNLOAD_LOCATION} check) 40 | if ("${check}" STREQUAL "") 41 | download_cpm() 42 | endif () 43 | unset(check) 44 | endif () 45 | 46 | include(${CPM_DOWNLOAD_LOCATION}) 47 | # -------- get_cpm.cmake -------- 48 | 49 | # https://github.com/google/googletest 50 | CPMAddPackage( 51 | NAME googletest 52 | GITHUB_REPOSITORY google/googletest 53 | GIT_TAG v1.13.0 54 | VERSION 1.13.0 55 | OPTIONS 56 | "INSTALL_GTEST OFF" 57 | "gtest_force_shared_crt ON" 58 | ) 59 | 60 | # # https://github.com/abumq/easyloggingpp 61 | # CPMAddPackage( 62 | # NAME easylogingpp 63 | # VERSION 9.97.0 64 | # GITHUB_REPOSITORY amrayn/easyloggingpp 65 | # OPTIONS 66 | # "build_static_lib ON" 67 | # "lib_utc_datetime ON" 68 | # ) 69 | 70 | # https://github.com/cpm-cmake/CPMLicenses.cmake 71 | # 保持在 CPMAddPackage 的最后 72 | CPMAddPackage( 73 | NAME CPMLicenses.cmake 74 | GITHUB_REPOSITORY cpm-cmake/CPMLicenses.cmake 75 | VERSION 0.0.7 76 | ) 77 | if (CPMLicenses.cmake_ADDED) 78 | cpm_licenses_create_disclaimer_target( 79 | write-licenses "${CMAKE_CURRENT_SOURCE_DIR}/3rd/LICENSE" "${CPM_PACKAGES}" 80 | ) 81 | endif () 82 | # make 时自动在 3rd 文件夹下生成 LICENSE 文件 83 | add_custom_target(3rd_licenses 84 | ALL 85 | COMMAND 86 | make 87 | write-licenses 88 | ) 89 | 90 | # doxygen 91 | find_package(Doxygen 92 | REQUIRED dot) 93 | if (NOT DOXYGEN_FOUND) 94 | message(FATAL_ERROR "Doxygen not found.\n" 95 | "Following https://www.doxygen.nl/index.html to install.") 96 | endif () 97 | 98 | # cppcheck 99 | find_program(CPPCHECK_EXE NAMES cppcheck) 100 | if (NOT CPPCHECK_EXE) 101 | message(FATAL_ERROR "cppcheck not found.\n" 102 | "Following https://cppcheck.sourceforge.io to install.") 103 | endif () 104 | add_custom_target(cppcheck 105 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 106 | COMMENT "Run cppcheck on ${CMAKE_BINARY_DIR}/compile_commands.json ..." 107 | COMMAND 108 | ${CPPCHECK_EXE} 109 | --enable=all 110 | --project=${CMAKE_BINARY_DIR}/compile_commands.json 111 | --suppress-xml=${CMAKE_SOURCE_DIR}/tools/cppcheck-suppressions.xml 112 | --output-file=${CMAKE_BINARY_DIR}/cppcheck_report.txt 113 | ) 114 | 115 | # 获取全部源文件 116 | file(GLOB_RECURSE ALL_SOURCE_FILES 117 | ${CMAKE_SOURCE_DIR}/src/*.h 118 | ${CMAKE_SOURCE_DIR}/src/*.hpp 119 | ${CMAKE_SOURCE_DIR}/src/*.c 120 | ${CMAKE_SOURCE_DIR}/src/*.cpp 121 | ${CMAKE_SOURCE_DIR}/test/*.h 122 | ${CMAKE_SOURCE_DIR}/test/*.hpp 123 | ${CMAKE_SOURCE_DIR}/test/*.c 124 | ${CMAKE_SOURCE_DIR}/test/*.cpp 125 | ) 126 | 127 | # clang-tidy 128 | find_program(CLANG_TIDY_EXE NAMES clang-tidy) 129 | if (NOT CLANG_TIDY_EXE) 130 | message(FATAL_ERROR "clang-tidy not found.\n" 131 | "Following https://clang.llvm.org/extra/clang-tidy to install.") 132 | endif () 133 | add_custom_target(clang-tidy 134 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 135 | COMMENT "Run clang-tidy on ${ALL_SOURCE_FILES} ..." 136 | COMMAND 137 | ${CLANG_TIDY_EXE} 138 | --config-file=${CMAKE_SOURCE_DIR}/.clang-tidy 139 | -p=${CMAKE_BINARY_DIR} 140 | ${ALL_SOURCE_FILES} 141 | > ${CMAKE_BINARY_DIR}/clang_tidy_report.log 2>&1 142 | ) 143 | 144 | # clang-format 145 | find_program(CLANG_FORMAT_EXE NAMES clang-format) 146 | if (NOT CLANG_FORMAT_EXE) 147 | message(FATAL_ERROR "clang-format not found.\n" 148 | "Following https://clang.llvm.org/docs/ClangFormat.html to install.") 149 | endif () 150 | add_custom_target(clang-format 151 | WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} 152 | COMMENT "Run clang-format on ${ALL_SOURCE_FILES} ..." 153 | COMMAND ${CLANG_FORMAT_EXE} -i -style=file ${ALL_SOURCE_FILES} 154 | ) 155 | 156 | # genhtml 生成测试覆盖率报告网页 157 | find_program(GENHTML_EXE genhtml) 158 | if (NOT GENHTML_EXE) 159 | message(FATAL_ERROR "genhtml not found.\n" 160 | "Following https://github.com/linux-test-project/lcov to install.") 161 | endif () 162 | 163 | # lcov 生成测试覆盖率报告 164 | find_program(LCOV_EXE lcov) 165 | if (NOT LCOV_EXE) 166 | message(FATAL_ERROR "lcov not found.\n" 167 | "Following https://github.com/linux-test-project/lcov to install.") 168 | endif () 169 | -------------------------------------------------------------------------------- /cmake/compile_config.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # compile_config.cmake for MRNIU/libcxxrt. 6 | # 配置信息 7 | 8 | # 通用编译选项 9 | list(APPEND COMMON_COMPILE_OPTIONS 10 | # 如果 CMAKE_BUILD_TYPE 为 Release 则使用 -O3 -Werror,否则使用 -O0 -g -ggdb 11 | $<$:-O3;-Werror> 12 | $<$:-O0;-g;-ggdb> 13 | # 打开全部警告 14 | -Wall 15 | # 打开额外警告 16 | -Wextra 17 | # 启用异常处理机制 18 | -fexceptions 19 | 20 | # gcc 特定选项 21 | $<$: 22 | > 23 | 24 | # clang 特定选项 25 | $<$: 26 | > 27 | 28 | # 平台相关 29 | $<$: 30 | > 31 | ) 32 | 33 | # 通用链接选项 34 | list(APPEND COMMON_LINK_OPTIONS 35 | # 不链接 ctr0 等启动代码 36 | -nostartfiles 37 | ) 38 | -------------------------------------------------------------------------------- /cmake/functions.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # functions.cmake for MRNIU/libcxxrt. 6 | # 辅助函数 7 | 8 | # 添加测试覆盖率 target 9 | # DEPENDS 要生成的 targets 10 | # SOURCE_DIR 源码路径 11 | # BINARY_DIR 二进制文件路径 12 | # EXCLUDE_DIR 要排除的目录 13 | function(add_coverage) 14 | # 解析参数 15 | set(options) 16 | set(one_value_keywords SOURCE_DIR BINARY_DIR) 17 | set(multi_value_keywords DEPENDS EXCLUDE_DIR) 18 | cmake_parse_arguments( 19 | ARG "${options}" "${one_value_keywords}" "${multi_value_keywords}" ${ARGN} 20 | ) 21 | 22 | # 不检查的目录 23 | list(APPEND EXCLUDES --exclude) 24 | foreach (_item ${ARG_EXCLUDE_DIR}) 25 | list(APPEND EXCLUDES '${_item}') 26 | endforeach () 27 | 28 | # 添加 target 29 | add_custom_target(coverage DEPENDS ${ARG_DEPENDS} 30 | COMMAND ${CMAKE_CTEST_COMMAND} 31 | ) 32 | # 在 coverage 执行完毕后生成报告 33 | add_custom_command(TARGET coverage 34 | COMMENT "Generating coverage report ..." 35 | POST_BUILD 36 | WORKING_DIRECTORY ${ARG_BINARY_DIR} 37 | COMMAND ${CMAKE_COMMAND} -E make_directory ${COVERAGE_OUTPUT_DIR} 38 | COMMAND ${LCOV_EXE} 39 | -c 40 | -o ${COVERAGE_OUTPUT_DIR}/coverage.info 41 | -d ${ARG_BINARY_DIR} 42 | -b ${ARG_SOURCE_DIR} 43 | --no-external 44 | ${EXCLUDES} 45 | --rc lcov_branch_coverage=1 46 | COMMAND ${GENHTML_EXE} 47 | ${COVERAGE_OUTPUT_DIR}/coverage.info 48 | -o ${COVERAGE_OUTPUT_DIR} 49 | --branch-coverage 50 | ) 51 | endfunction() 52 | -------------------------------------------------------------------------------- /cmake/gcc.cmake: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # gcc.cmake for MRNIU/libcxxrt. 6 | 7 | if (APPLE) 8 | message(STATUS "Now is Apple systens.") 9 | # GCC 10 | find_program(Compiler_gcc g++-13) 11 | if (NOT Compiler_gcc) 12 | message(FATAL_ERROR "g++-13 not found.\n" 13 | "Run `brew install gcc` to install.") 14 | else () 15 | message(STATUS "Found g++-13 ${Compiler_gcc}") 16 | endif () 17 | 18 | set(CMAKE_C_COMPILER gcc-13) 19 | set(CMAKE_CXX_COMPILER g++-13) 20 | endif () 21 | -------------------------------------------------------------------------------- /doc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置项目名与版本 8 | project( 9 | doc 10 | VERSION 0.0.1 11 | ) 12 | 13 | # 设置 doxygen 相关参数 14 | set(DOXYGEN_HAVE_DOT YES) 15 | set(DOXYGEN_DOT_MULTI_TARGETS YES) 16 | set(DOXYGEN_GENERATE_LATEX NO) 17 | set(DOXYGEN_PROJECT_NAME ${CMAKE_PROJECT_NAME}) 18 | set(DOXYGEN_PROJECT_NUMBER ${CMAKE_PROJECT_VERSION}) 19 | set(DOXYGEN_PROJECT_BRIEF ${PROJECT_DESCRIPTION}) 20 | set(DOXYGEN_RECURSIVE YES) 21 | set(DOXYGEN_EXCLUDE_PATTERNS */3rd/*, */.vscode/*, */.idea/*, */.github/*, */.git/*, */build*/*, */cmake-/*) 22 | set(DOXYGEN_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) 23 | set(DOXYGEN_EXTRACT_ALL YES) 24 | set(DOXYGEN_EXTRACT_PRIVATE YES) 25 | set(DOXYGEN_EXTRACT_STATIC YES) 26 | set(DOXYGEN_EXTRACT_LOCAL_CLASSES YES) 27 | set(DOXYGEN_SOURCE_BROWSER YES) 28 | set(DOXYGEN_INLINE_SOURCES YES) 29 | set(DOXYGEN_ALPHABETICAL_INDEX YES) 30 | set(DOXYGEN_GENERATE_TREEVIEW YES) 31 | set(DOXYGEN_ENABLE_PREPROCESSING YES) 32 | set(DOXYGEN_CLASS_DIAGRAMS YES) 33 | set(DOXYGEN_CLASS_GRAPH YES) 34 | set(DOXYGEN_GRAPHICAL_HIERARCHY YES) 35 | set(DOXYGEN_CALLER_GRAPH YES) 36 | set(DOXYGEN_CALL_GRAPH YES) 37 | set(DOXYGEN_UML_LOOK YES) 38 | set(DOXYGEN_HTML_TIMESTAMP YES) 39 | 40 | # 创建 target 并通过 VERBATIM 将 cmake 参数传递给 doxygen 41 | doxygen_add_docs(doc 42 | COMMENT "Generating docs at ${PROJECT_SOURCE_DIR}/html/index.html ..." 43 | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} 44 | ${CMAKE_SOURCE_DIR} 45 | ) 46 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | enable_language(C) 8 | enable_language(CXX) 9 | 10 | set(SOURCE 11 | entry.c 12 | format.c 13 | malloc.c 14 | stdio.c 15 | string.c 16 | cxxabi.cpp 17 | new_delete.cpp 18 | string.cpp 19 | iostream.cpp 20 | ) 21 | 22 | add_library(cxxrt-static STATIC 23 | ${SOURCE} 24 | ) 25 | 26 | target_compile_options(cxxrt-static PRIVATE 27 | ${COMMON_COMPILE_OPTIONS} 28 | ) 29 | target_link_options(cxxrt-static PRIVATE 30 | ${COMMON_LINK_OPTIONS} 31 | ) 32 | target_include_directories(cxxrt-static PRIVATE 33 | ${CMAKE_CURRENT_LIST_DIR}/include 34 | ) 35 | 36 | # add_library(cxxrt-shared SHARED 37 | # ${SOURCE} 38 | # ) 39 | 40 | # target_compile_options(cxxrt-shared PRIVATE 41 | # ${COMMON_COMPILE_OPTIONS} 42 | # ) 43 | # target_link_options(cxxrt-shared PRIVATE 44 | # ${COMMON_LINK_OPTIONS} 45 | # ) 46 | # target_include_directories(cxxrt-shared PRIVATE 47 | # ${CMAKE_CURRENT_LIST_DIR}/include 48 | # ) 49 | -------------------------------------------------------------------------------- /src/CMakeLists_old.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/MiniCRT (https://github.com/MRNIU/MiniCRT). 3 | # 4 | # CMakeLists.txt for MRNIU/MiniCRT. 5 | 6 | # 由于 x64 变长参数难以实现,需要借助 builtin 函数 7 | message(STATUS "C compiler: ${CMAKE_C_COMPILER_ID}, version: ${CMAKE_C_COMPILER_VERSION}") 8 | message(STATUS "C++ compiler: ${CMAKE_CXX_COMPILER_ID}, version: ${CMAKE_CXX_COMPILER_VERSION}") 9 | 10 | if (CMAKE_C_COMPILER_ID STREQUAL "MSVC") 11 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 12 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Wall") 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} /GR-") 14 | add_link_options(/ENTRY:mini_crt_entry /NODEFAULTLIB) 15 | 16 | else () 17 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m64") 18 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -Wall -Wextra -g -ggdb") 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdlib -fno-builtin") 20 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffreestanding -fno-exceptions") 21 | if (CMAKE_C_COMPILER_ID STREQUAL "AppleClang") 22 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") 23 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -fno-rtti") 24 | add_link_options(-e _mini_crt_entry -lSystem -nostartfiles) 25 | elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU") 26 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -nostdinc") 27 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_C_FLAGS} -fno-rtti -nostdinc++") 28 | add_link_options(-e mini_crt_entry -nostartfiles) 29 | endif () 30 | endif () 31 | 32 | message(STATUS "C FLAGS: ${CMAKE_C_FLAGS}") 33 | message(STATUS "CXX FLAGS: ${CMAKE_CXX_FLAGS}") 34 | 35 | include_directories(${MiniCRT_SOURCE_CODE_DIR}/include) 36 | 37 | add_library(minicrt STATIC 38 | entry.c 39 | format.c 40 | malloc.c 41 | stdio.c 42 | string.c 43 | cxxabi.cpp 44 | new_delete.cpp 45 | string.cpp 46 | iostream.cpp) 47 | 48 | add_executable(test 49 | $ 50 | test.cpp) 51 | -------------------------------------------------------------------------------- /src/cxxabi.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file cxxabi.cpp 4 | * @brief cxxabi cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "cxxabi.h" 18 | #include "stddef.h" 19 | 20 | #ifdef WIN32 21 | extern "C" void do_global_ctors(void) { 22 | init_func *p = ctors_begin; 23 | while (p < ctors_end) { 24 | if (*p != NULL) { 25 | (**p)(); 26 | } 27 | p++; 28 | } 29 | return; 30 | } 31 | #else 32 | atexit_func_entry_t __atexit_funcs[ATEXIT_MAX_FUNCS]; 33 | uarch_t __atexit_func_count = 0; 34 | 35 | void *__dso_handle = 0; 36 | void *__stack_chk_guard(0); 37 | 38 | int __cxa_atexit(void (*f)(void *), void *objptr, void *dso) { 39 | if (__atexit_func_count >= ATEXIT_MAX_FUNCS) { 40 | return -1; 41 | }; 42 | __atexit_funcs[__atexit_func_count].destructor_func = f; 43 | __atexit_funcs[__atexit_func_count].obj_ptr = objptr; 44 | __atexit_funcs[__atexit_func_count].dso_handle = dso; 45 | __atexit_func_count++; 46 | return 0; 47 | }; 48 | 49 | void __cxa_finalize(void *f) { 50 | uarch_t i = __atexit_func_count; 51 | if (!f) { 52 | while (i--) { 53 | if (__atexit_funcs[i].destructor_func) { 54 | (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); 55 | }; 56 | }; 57 | return; 58 | }; 59 | 60 | while (i--) { 61 | if (__atexit_funcs[i].destructor_func == f) { 62 | (*__atexit_funcs[i].destructor_func)(__atexit_funcs[i].obj_ptr); 63 | __atexit_funcs[i].destructor_func = 0; 64 | } 65 | } 66 | return; 67 | } 68 | 69 | void __cxa_pure_virtual() { return; } 70 | 71 | void __attribute__((noreturn)) __stack_chk_fail() { 72 | for (;;) { 73 | ; 74 | } 75 | } 76 | 77 | void __stack_chk_guard_setup() { 78 | unsigned char *Guard; 79 | Guard = (unsigned char *)&__stack_chk_guard; 80 | Guard[sizeof(__stack_chk_guard) - 1] = 255; 81 | Guard[sizeof(__stack_chk_guard) - 2] = '\n'; 82 | Guard[0] = 0; 83 | return; 84 | } 85 | 86 | void _Unwind_Resume() { return; } 87 | 88 | namespace __cxxabiv1 { 89 | int __cxa_guard_acquire(__guard *g) { return !*(char *)(g); } 90 | 91 | void __cxa_guard_release(__guard *g) { 92 | *(char *)g = 1; 93 | return; 94 | } 95 | 96 | void __cxa_guard_abort(__guard *) { return; } 97 | } // namespace __cxxabiv1 98 | 99 | void *__gxx_personality_v0 = (void *)0xDEADBEAF; 100 | 101 | #if __clang__ 102 | extern "C" void do_global_ctors(void) { 103 | const Initializer *p; 104 | for (p = &inits_start; p < &inits_end; ++p) { 105 | (*p)(0, 0, 0, 0); 106 | } 107 | return; 108 | } 109 | 110 | #elif __linux__ 111 | extern "C" void do_global_ctors(void) { 112 | constructor_func *f; 113 | for (f = ctors_start; f < ctors_end; f++) { 114 | (*f)(); 115 | } 116 | return; 117 | } 118 | #endif 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /src/entry.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file entry.c 4 | * @brief entry c 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "libcxxrt.h" 18 | #include "stddef.h" 19 | #include "stdio.h" 20 | #include "unistd.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #ifdef WIN32 27 | #include 28 | #endif 29 | 30 | extern int main(int argc, char *argv[]); 31 | void exit(int); 32 | 33 | static void crt_fatal_error(const char *msg) { 34 | printf("fatal error: %s", msg); 35 | exit(1); 36 | return; 37 | } 38 | 39 | void mini_crt_entry(void) { 40 | int ret = 0; 41 | 42 | #ifdef WIN32 43 | int flag = 0; 44 | int argc = 0; 45 | char *argv[16]; 46 | char *cl = GetCommandLineA(); 47 | 48 | // 解析命令行 49 | argv[0] = cl; 50 | argc++; 51 | while (*cl) { 52 | if (*cl == '\"') 53 | if (flag == 0) 54 | flag = 1; 55 | else 56 | flag = 0; 57 | else if (*cl == ' ' && flag == 0) { 58 | if (*(cl + 1)) { 59 | argv[argc] = cl + 1; 60 | argc++; 61 | } 62 | *cl = '\0'; 63 | } 64 | cl++; 65 | } 66 | 67 | #else 68 | int argc = 0; 69 | char **argv = NULL; 70 | 71 | #if defined(__i386__) 72 | char *ebp_reg = NULL; 73 | __asm__ __volatile__("movl %%ebp, %0" : "=r"(ebp_reg)); 74 | argc = *(int *)(ebp_reg + 4); 75 | argv = (char **)(ebp_reg + 8); 76 | #elif defined(__x86_64__) 77 | #if __APPLE__ 78 | long argcL = 0; 79 | long argvL = 0; 80 | __asm__ __volatile__("mov %%rdi, %0" : "=r"(argcL)); 81 | __asm__ __volatile__("mov %%rsi, %0" : "=r"(argvL)); 82 | argc = (int)argcL; 83 | argv = (char **)argvL; 84 | #elif __linux__ 85 | char *rbp_reg = NULL; 86 | __asm__ __volatile__("mov %%rbp, %0" : "=r"(rbp_reg)); 87 | argc = *(long *)(rbp_reg + 8); 88 | argv = (char **)(rbp_reg + 16); 89 | #endif 90 | #endif 91 | #endif 92 | 93 | if (mini_crt_heap_init() != 0) { 94 | crt_fatal_error("heap initialize failed"); 95 | } 96 | 97 | if (mini_crt_io_init() != 0) { 98 | crt_fatal_error("IO initialize failed"); 99 | } 100 | /*do_global_ctors();*/ 101 | ret = main(argc, argv); 102 | exit(ret); 103 | return; 104 | } 105 | 106 | void exit(int exitCode) { 107 | // mini_crt_call_exit_routine(); 108 | #ifdef WIN32 109 | ExitProcess(exitCode); 110 | #elif defined(__i386__) 111 | __asm__ __volatile__("int $80" : : "a"(SYSCALL_exit), "b"(exitCode)); 112 | #elif defined(__x86_64__) 113 | __asm__ __volatile__("syscall" : : "a"(SYSCALL_exit), "D"(exitCode)); 114 | #endif 115 | return; 116 | } 117 | 118 | #ifdef __cplusplus 119 | } 120 | #endif 121 | -------------------------------------------------------------------------------- /src/format.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file format.c 4 | * @brief format c 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "port.h" 22 | #include "stdarg.h" 23 | #include "stdint.h" 24 | #include "stdio.h" 25 | #include "string.h" 26 | 27 | int fputc(int c, FILE *stream) { 28 | int res = c; 29 | if (fwrite(&c, 1, 1, stream) != 1) { 30 | res = EOF; 31 | } 32 | return res; 33 | } 34 | 35 | int fputs(const char *str, FILE *stream) { 36 | int len = strlen(str); 37 | if (fwrite(str, len, 1, stream) != len) { 38 | len = EOF; 39 | } 40 | return len; 41 | } 42 | 43 | // 判断字符是否数字字符 44 | #define is_digit(c) ((c) >= '0' && (c) <= '9') 45 | 46 | // 该函数将字符数字转换成整数。输入是数字串指针的指针,返回值是结果数值。另外指针将前移。 47 | static int skip_atoi(const char **s) { 48 | int i = 0; 49 | while (is_digit(**s)) { 50 | i = i * 10 + *((*s)++) - '0'; 51 | } 52 | return i; 53 | } 54 | 55 | // 这里定义转换类型的各种符号常数 56 | // pad with zero 填充 0 57 | #define ZEROPAD 1 58 | // unsigned/signed long 无符号/符号长整数 59 | #define SIGN 2 60 | // show plus 显示加 61 | #define PLUS 4 62 | // space if plus 如是加,则置空格 63 | #define SPACE 8 64 | // left justified 左调整 65 | #define LEFT 16 66 | // 0x 67 | #define SPECIAL 32 68 | // use 'abcdef' instead of 'ABCDEF' 使用小写字母 69 | #define SMALL 64 70 | 71 | // 除操作。n 被除数;base 除数。结果 n 为商,函数返回值为余数。 72 | int32_t do_div(int *n, int base) { 73 | int32_t res = 0; 74 | res = *n % base; 75 | *n = *n / base; 76 | return res; 77 | } 78 | 79 | // 将整数转换为指定进制的字符串。输入:num-整数;base-进制;size-字符串长度;precision-数字长度 80 | // (精读);type-类型选项。输出:str-字符串指针 81 | static char *number(char *str, int num, int base, int size, int precision, 82 | int type) { 83 | char c, sign, tmp[36]; 84 | const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 85 | int i; 86 | // 若类型 type 87 | // 指出用小写字母,则定义小写字母集。若类型指出要左调整(靠左边界),则屏蔽填零标志。 88 | // 若进制基数小于 2 或大于 36,则退出处理,也即本程序只能处理基数在 2-32 89 | // 之间的数 90 | if (type & SMALL) { 91 | digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 92 | } 93 | if (type & LEFT) { 94 | type &= ~ZEROPAD; 95 | } 96 | if (base < 2 || base > 36) { 97 | return 0; 98 | } 99 | // 若类型指出要填零,则置字符变量 c='0' (即 ''),否则 c 100 | // 等于空格字符。若类型指出是带符号数并且 数值 num 小于 0,则置符号变量 101 | // sign=负号,并使 num 取绝对值。否则如果类型指出是加号, 则置 102 | // sign=加号,否则若类型带空格标志则 sign=空格,否则置 0 103 | c = (type & ZEROPAD) ? '0' : ' '; 104 | if (type & SIGN && num < 0) { 105 | sign = '-'; 106 | num -= num; 107 | } else { 108 | sign = (type & PLUS) ? '+' : ((type & SPACE) ? ' ' : 0); 109 | } 110 | // 若带符号,则宽度值减 1.若类型指出是特殊转换,则对于十六进制宽度再减少 2 111 | // 位(用于 0x),对于 八进制宽度减 1 (用于八进制转换结果) 112 | if (sign) { 113 | size--; 114 | } 115 | if (type & SPECIAL) { 116 | if (base == 16) { 117 | size -= 2; 118 | } else if (base == 8) { 119 | size--; 120 | } 121 | } 122 | // 如果数值 num 为 0,则临时字符串='0';否则根据给定的基数将数值 num 123 | // 转换成字符形式 124 | i = 0; 125 | if (num == 0) { 126 | tmp[i++] = '0'; 127 | } else { 128 | while (num != 0) { 129 | tmp[i++] = digits[do_div(&num, base)]; 130 | } 131 | } 132 | // 若数值字符个数大于精读值,则精度值扩展为数字个数值。宽度值减去用于存放数值字符的个数。 133 | if (i > precision) { 134 | precision = i; 135 | } 136 | size -= precision; 137 | // 从这里真正开始形成所需要的转换结果,并暂时放在字符串 str 138 | // 中。若类型中没有填零(ZEROPAD) 和左调整标志,则在 str 139 | // 中首先填放剩余宽度值指出的空格数。若需带符号位,则存入符号。 140 | if (!(type & (ZEROPAD + LEFT))) { 141 | while (size-- > 0) { 142 | *str++ = ' '; 143 | } 144 | } 145 | if (sign) { 146 | *str++ = sign; 147 | } 148 | // 若类型指出是特殊转换,则对于八进制转换结果头一位放置一个 149 | // '0';而对于十六进制则存放 '0x'. 150 | if (type & SPECIAL) { 151 | if (base == 8) { 152 | *str++ = '0'; 153 | } else if (base == 16) { 154 | *str++ = '0'; 155 | // 'X' 或 'x' 156 | *str++ = digits[33]; 157 | } 158 | } 159 | // 若类型中没有左调整(左靠齐)标志,则在剩余宽度中存放 c 字符('0' 或空格),见 160 | // 49 行。 161 | if (!(type & LEFT)) { 162 | while (size-- > 0) { 163 | *str++ = c; 164 | } 165 | } 166 | // 此时 i 存有数值 num 的数字个数。若数字个数小于精读值,则 str 167 | // 中放入(精度值 - i)个 '0'. 168 | while (i < precision--) { 169 | *str++ = '0'; 170 | } 171 | // 将转换好的数字字符填入 str 中。共 i 个。 172 | while (i-- > 0) { 173 | *str++ = tmp[i]; 174 | } 175 | // 若宽度值仍大于零,则表示类型标志中有左靠齐标志标志。则在剩余宽度中放入空格。 176 | while (size-- > 0) { 177 | *str++ = ' '; 178 | } 179 | // 返回转换好的字符串。 180 | return str; 181 | } 182 | 183 | // fmt 是格式字符串;args 是个数变化的值;buf 是输出字符缓冲区。 184 | // 下面函数是送格式化输出到字符串。为了能在内核中使用格式化的输出,Linus 185 | // 在内核实现了该 C 标准函数。 其中参数 fmt 是格式字符串;args 186 | // 是个数变化的值;buf 是输出字符缓冲区。请参见本代码列表后面 187 | // 的有关格式转换字符的介绍。 188 | int32_t vsprintf(char *buf, const char *fmt, va_list args) { 189 | int32_t len; 190 | int32_t i; 191 | // 用于存放转换过程中的字符串 192 | char *str; 193 | char *s; 194 | int32_t *ip; 195 | // flags to number() 196 | uint32_t flags; 197 | // width of output field 198 | int32_t field_width; 199 | // min. # of digits for integers;max number of chars for from 200 | int32_t precision; 201 | // fields. min.整数数字个数;max. 字符串中字符个数 202 | // 'h','l',or 'L' for integer fields 203 | int32_t qualifier __attribute__((unused)); 204 | 205 | // 首先将字符指针指向 206 | // buf,然后扫描格式字符串,对各个格式转换只是进行相应的处理. 207 | // 格式转换指示字符串均以 '%' 开始,这里从 fmt 格式字符串中扫描 208 | // '%',寻找格式转换字符串的开始。 不是格式指示的一般字符均被依次存入 str 209 | for (str = buf; *fmt; ++fmt) { 210 | if (*fmt != '%') { 211 | *str++ = *fmt; 212 | continue; 213 | } 214 | // 下面取得格式指示字符串中的标志域,并将标志常量放入 flags 变量中 215 | // prcess flags. 216 | flags = 0; 217 | repeat: 218 | // this also skips first '%' 219 | ++fmt; 220 | switch (*fmt) { 221 | // 左靠齐调整 222 | case '-': { 223 | flags |= LEFT; 224 | goto repeat; 225 | } 226 | // 放加号 227 | case '+': { 228 | flags |= PLUS; 229 | goto repeat; 230 | } 231 | // 放空格 232 | case ' ': { 233 | flags |= SPACE; 234 | goto repeat; 235 | } 236 | // 是特殊转换 237 | case '#': { 238 | flags |= SPECIAL; 239 | goto repeat; 240 | } 241 | // 要填零(即 ‘0’) 242 | case '0': { 243 | flags |= ZEROPAD; 244 | goto repeat; 245 | } 246 | } 247 | // 去参数字段宽度阈值放入 field_width 248 | // 变量中。若宽度域中是数值则直接取其为宽度值。若宽度域是 字符 '*' 249 | // ,表示下一参数指定宽度,调用 va_arg 取宽度值。若此时宽度值 < 250 | // 0,则该负数表示其带有 标志域 '-' 251 | // 标志(左靠齐),因此需在标志变量中添入该标志,并将字段宽度值取为其绝对值。 252 | // get field field_width 253 | field_width = -1; 254 | if (is_digit(*fmt)) { 255 | field_width = skip_atoi(&fmt); 256 | } else if (*fmt == '*') { 257 | // it's the next argument 这里应该插入 ++fmt; 258 | field_width = va_arg(args, int); 259 | if (field_width < 0) { 260 | field_width = -field_width; 261 | flags |= LEFT; 262 | } 263 | } 264 | // 下面代码取格式转换串精度域,并放入 precision 265 | // 变量中。精度域的开始标志是 '.'。其处理过程与上面 266 | // 宽度域类似。若精度域中是数值则直接取其为精度值。若精度域中是字符 267 | // '*',表示下一个参数指定精度。 因此调用 va_arg 268 | // 取精度值。若此时宽度值小于 0,则将字段精度值取为 0. get the 269 | // precision 270 | precision = -1; 271 | if (*fmt == '.') { 272 | ++fmt; 273 | if (is_digit(*fmt)) { 274 | precision = skip_atoi(&fmt); 275 | } else if (*fmt == '*') { 276 | // it's the next argument 277 | precision = va_arg(args, int); 278 | } 279 | if (precision < 0) { 280 | precision = 0; 281 | } 282 | } 283 | // 下面这段代码分析长度修饰符,并将其存入 qualifier 变量。(h,l,L 284 | // 的含义参见列表后的说明) get the conversion qualifier 285 | qualifier = -1; 286 | if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') { 287 | qualifier = *fmt; 288 | ++fmt; 289 | } 290 | // 下面分析转换指示符。如果转换指示符是 291 | // 'c',则表示对应参数应是字符。此时如果标志域表明不是左 292 | // 对齐,则该字段前面放入宽度域值 -1 293 | // 个空格字符,然后再被放入参数字符。如果宽度域还大于 0, 294 | // 则表示为左对齐,则在参数字符后面添加宽度值 -1 个空格字符 295 | switch (*fmt) { 296 | case 'c': { 297 | if (!(flags & LEFT)) { 298 | while (--field_width > 0) { 299 | *str++ = ' '; 300 | } 301 | } 302 | *str++ = (uint8_t)va_arg(args, int); 303 | while (--field_width > 0) { 304 | *str++ = ' '; 305 | } 306 | break; 307 | } 308 | // 如果转换指示符是 309 | // 's',则表示对应参数是字符串。首先取参数字符串的长度,若其超过了精度域值,则 310 | // 拓展精度域=字符串长度。此时如果标志域表明不是左靠齐,则该字段前放入(宽度值-字符串长度)个空格 311 | // 字符。然后再放入参数字符串。如果宽度域还大于 312 | // 0,则表示为左靠齐,则在参数字符串后面添加(宽度值- 313 | // 字符串长度)个空格字符。 314 | case 's': { 315 | s = va_arg(args, char *); 316 | len = strlen(s); 317 | if (precision < 0) { 318 | precision = len; 319 | } else if (len > precision) { 320 | len = precision; 321 | } 322 | if (!(flags & LEFT)) { 323 | while (len < field_width--) { 324 | *str++ = ' '; 325 | } 326 | } 327 | for (i = 0; i < len; ++i) { 328 | *str++ = *s++; 329 | } 330 | while (len < field_width--) { 331 | *str++ = ' '; 332 | } 333 | break; 334 | } 335 | // 如果格式转换符是 336 | // 'o',则表示需要将对应的参数转换成八进制数的字符串。调用 number() 337 | // 函数处理。 338 | case 'o': { 339 | str = 340 | number(str, va_arg(args, uint32_t), 8, field_width, precision, flags); 341 | break; 342 | } 343 | // 如果格式转换符是 344 | // 'p',表示对应参数的一个指针类型。此时若该参数没有设置宽度域,则默认宽度为 345 | // 8, 并且需要添零。然后调用 number() 函数进行处理。 346 | case 'p': { 347 | if (field_width == -1) { 348 | field_width = 8; 349 | flags |= ZEROPAD; 350 | } 351 | str = number(str, (uint32_t)(long)va_arg(args, void *), 16, field_width, 352 | precision, flags); 353 | break; 354 | } 355 | // 若格式转换指示是 'x' 或 356 | // 'X',则表示对应参数需打印成十六进制数输出。'x' 357 | // 表示用小写字母表示。 358 | case 'x': { 359 | flags |= SMALL; 360 | FALLTHROUHT; 361 | } 362 | case 'X': { 363 | str = number(str, va_arg(args, uint32_t), 16, field_width, precision, 364 | flags); 365 | break; 366 | } 367 | // 如果格式转换字符是 'd','i' 或 'u',则表示对应参数是整数。'd','i' 368 | // 代表符号整数, 因此需要加上带符号标志。'u' 代表无符号整数。 369 | case 'd': 370 | case 'i': { 371 | flags |= SIGN; 372 | FALLTHROUHT; 373 | } 374 | case 'u': { 375 | str = number(str, va_arg(args, uint32_t), 10, field_width, precision, 376 | flags); 377 | break; 378 | } 379 | // 若格式转换指示符是 380 | // 'n',则表示要把到目前为止转换输出的字符保存到对应参数指针指定的位置中。 381 | // 首先利用 va_arg() 382 | // 取得该参数指针,然后将已经转换好的字符存入该指针所指的位置。 383 | case 'n': { 384 | ip = va_arg(args, int *); 385 | *ip = (str - buf); 386 | break; 387 | } 388 | // 若格式转换符不是 '%' ,则表示格式字符串有错,直接将一个 '%' 389 | // 写入输出中。如果格式转换符的 390 | // 位置处还有字符,则也直接将该字符写入输出串中,并返回到 117 391 | // 行处继续处理格式字符串。否则表示 392 | // 已经处理到格式字符串的结尾处,则退出循环。 393 | default: { 394 | if (*fmt != '%') { 395 | *str++ = '%'; 396 | } 397 | if (*fmt) { 398 | *str++ = *fmt; 399 | } else { 400 | --fmt; 401 | } 402 | break; 403 | } 404 | } 405 | } 406 | // 最后在转换好的字符串结尾处添上 null 407 | *str = '\0'; 408 | // 返回转换好的字符串长度值 409 | return str - buf; 410 | } 411 | 412 | int printf(const char *format, ...) { 413 | va_list args; 414 | int32_t i; 415 | va_start(args, format); 416 | char buf[128]; 417 | i = vsprintf(buf, format, args); 418 | va_end(args); 419 | fputs(buf, stdout); 420 | bzero(buf, 128); 421 | return i; 422 | } 423 | 424 | int fprintf(FILE *stream, const char *format, ...) { 425 | va_list args; 426 | int32_t i; 427 | va_start(args, format); 428 | char buf[128]; 429 | i = vsprintf(buf, format, args); 430 | va_end(args); 431 | fputs(buf, stream); 432 | bzero(buf, 128); 433 | return i; 434 | } 435 | 436 | #ifdef __cplusplus 437 | } 438 | #endif 439 | -------------------------------------------------------------------------------- /src/include/cxxabi.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file cxxabi.h 4 | * @brief cxxabi header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_CXXABI_H 18 | #define LIBCXXRT_CXXABI_H 19 | 20 | // See https://gcc.gnu.org/onlinedocs/gccint/Initialization.html for more info 21 | 22 | #define ATEXIT_MAX_FUNCS 128 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | typedef unsigned uarch_t; 29 | 30 | struct atexit_func_entry_t { 31 | void (*destructor_func)(void *); 32 | void *obj_ptr; 33 | void *dso_handle; 34 | }; 35 | 36 | #ifdef WIN32 37 | typedef void (*init_func)(void); 38 | #pragma section(".CRT$XCA", long, read) 39 | #pragma section(".CRT$XCZ", long, read) 40 | __declspec(allocate(".CRT$XCA")) init_func ctors_begin[] = {0}; 41 | __declspec(allocate(".CRT$XCZ")) init_func ctors_end[] = {0}; 42 | #else 43 | int __cxa_atexit(void (*f)(void *), void *objptr, void *dso); 44 | void __cxa_finalize(void *f); 45 | void __cxa_pure_virtual(); 46 | void __stack_chk_guard_setup(); 47 | void __attribute__((noreturn)) __stack_chk_fail(); 48 | void _Unwind_Resume(); 49 | 50 | namespace __cxxabiv1 { 51 | /* guard variables */ 52 | 53 | /* The ABI requires a 64-bit type. */ 54 | __extension__ typedef int __guard __attribute__((mode(__DI__))); 55 | 56 | extern "C" int __cxa_guard_acquire(__guard *); 57 | extern "C" void __cxa_guard_release(__guard *); 58 | extern "C" void __cxa_guard_abort(__guard *); 59 | } // namespace __cxxabiv1 60 | 61 | void __cxa_finalize(void *f); 62 | #endif 63 | 64 | #if __clang__ 65 | typedef void (*Initializer)(int argc, const char *argv[], const char *envp[], 66 | const char *apple[]); 67 | extern const Initializer 68 | inits_start __asm__("section$start$__DATA$__mod_init_func"); 69 | extern const Initializer 70 | inits_end __asm__("section$end$__DATA$__mod_init_func"); 71 | #elif __linux__ 72 | typedef void (*constructor_func)(); 73 | constructor_func ctors_start[1] 74 | __attribute__((section(".ctors"))) = {(constructor_func)-1}; 75 | constructor_func ctors_end[1] 76 | __attribute__((section(".ctors"))) = {(constructor_func)-1}; 77 | #endif 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* LIBCXXRT_CXXABI_H */ 84 | -------------------------------------------------------------------------------- /src/include/iostream: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file iostream 4 | * @brief iostream 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_IOSTREAM 18 | #define LIBCXXRT_IOSTREAM 19 | 20 | #include "stdint.h" 21 | #include "stdio.h" 22 | 23 | namespace std { 24 | class ofstream { 25 | private: 26 | protected: 27 | FILE *fp; 28 | ofstream(const ofstream &lhs); 29 | 30 | public: 31 | enum openmode : uint8_t { 32 | in = 1, 33 | out = 2, 34 | binary = 4, 35 | trunc = 8, 36 | }; 37 | 38 | ofstream(void); 39 | explicit ofstream(const char *filename, 40 | ofstream::openmode md = ofstream::out); 41 | ~ofstream(void); 42 | ofstream &operator<<(char c); 43 | ofstream &operator<<(int n); 44 | ofstream &operator<<(const char *lhs); 45 | ofstream &operator<<(ofstream &(*)(ofstream &)); 46 | 47 | void open(const char *filename, ofstream::openmode md = ofstream::out); 48 | void close(void); 49 | ofstream &write(const char *buf, unsigned size); 50 | }; 51 | 52 | inline ofstream &endl(ofstream &lhs) { return lhs << '\n'; } 53 | 54 | class stdout_stream : public ofstream { 55 | private: 56 | protected: 57 | public: 58 | stdout_stream(void); 59 | stdout_stream(const stdout_stream &s); 60 | ~stdout_stream(void); 61 | }; 62 | 63 | extern stdout_stream cout; 64 | }; // namespace std 65 | 66 | #endif /* LIBCXXRT_IOSTREAM */ 67 | -------------------------------------------------------------------------------- /src/include/libcxxrt.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file minicrt.h 4 | * @brief minicrt header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_LIBCXXRT_H 18 | #define LIBCXXRT_LIBCXXRT_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "stdint.h" 25 | 26 | /// @todo 改名 27 | int mini_crt_io_init(); 28 | int32_t mini_crt_heap_init(); 29 | 30 | // internal 31 | void do_global_ctors(); 32 | void mini_crt_call_exit_routine(); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* LIBCXXRT_LIBCXXRT_H */ 39 | -------------------------------------------------------------------------------- /src/include/port.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file port.h 4 | * @brief port header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | #ifndef LIBCXXRT_PORT_H 17 | #define LIBCXXRT_PORT_H 18 | 19 | #ifdef WIN32 20 | #define UNUSED(x) 21 | #else 22 | #define UNUSED(x) (x) __attribute__((unused)) 23 | #define FALLTHROUHT __attribute__((fallthrough)) 24 | #endif 25 | 26 | #endif /* LIBCXXRT_PORT_H */ 27 | -------------------------------------------------------------------------------- /src/include/stdarg.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stdarg.h 4 | * @brief stdarg header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STDARG_H 18 | #define LIBCXXRT_STDARG_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #ifdef WIN32 25 | #include 26 | 27 | #elif defined(__i386__) 28 | typedef char *va_list; 29 | #define __va_SIZE(TYPE) \ 30 | (((sizeof(TYPE) + sizeof(int) - 1) / sizeof(int)) * sizeof(int)) 31 | #define va_start(AP, LASTARG) \ 32 | (AP = ((va_list) & (LASTARG) + __va_SIZE(LASTARG))) 33 | #define va_arg(AP, TYPE) \ 34 | (AP += __va_SIZE(TYPE), *((TYPE *)(AP - __va_SIZE(TYPE)))) 35 | #define va_end(AP) (AP = (va_list)0) 36 | 37 | #elif defined(__x86_64__) 38 | // TODO: 独立实现 39 | #define va_list __builtin_va_list 40 | #define va_arg(ap, type) __builtin_va_arg(ap, type) 41 | #define va_start(v, l) __builtin_va_start(v, l) 42 | #define va_end(v) __builtin_va_end(v) 43 | #endif 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif 48 | 49 | #endif /* LIBCXXRT_STDARG_H */ 50 | -------------------------------------------------------------------------------- /src/include/stddef.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stddef.h 4 | * @brief stddef header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STDDEF_H 18 | #define LIBCXXRT_STDDEF_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #ifndef NULL 25 | #define NULL ((void *)0) 26 | #endif 27 | 28 | #ifndef size_t 29 | #if defined(__i386__) 30 | typedef unsigned int size_t; 31 | #elif defined(__x86_64__) 32 | typedef unsigned long size_t; 33 | #endif 34 | #endif 35 | 36 | #ifdef __cplusplus 37 | } 38 | #endif 39 | 40 | #endif /* LIBCXXRT_STDDEF_H */ 41 | -------------------------------------------------------------------------------- /src/include/stdint.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stdint.h 4 | * @brief stdint header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STDINT_H 18 | #define LIBCXXRT_STDINT_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | typedef signed char int8_t; 25 | typedef short int int16_t; 26 | typedef int int32_t; 27 | typedef long long int64_t; 28 | 29 | typedef unsigned char uint8_t; 30 | typedef unsigned short int uint16_t; 31 | typedef unsigned int uint32_t; 32 | typedef unsigned long long uint64_t; 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* LIBCXXRT_STDINT_H */ 39 | -------------------------------------------------------------------------------- /src/include/stdio.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stdio.h 4 | * @brief stdio header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STDIO_H 18 | #define LIBCXXRT_STDIO_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "stdint.h" 25 | 26 | typedef int FILE; 27 | #define EOF (-1) 28 | 29 | #ifdef WIN32 30 | #define stdin ((FILE *)(GetStdHandle(STD_INPUT_HANDLE))) 31 | #define stdout ((FILE *)(GetStdHandle(STD_OUTPUT_HANDLE))) 32 | #define stderr ((FILE *)(GetStdHandle(STD_ERROR_HANDLE))) 33 | #else 34 | #define stdin ((FILE *)0) 35 | #define stdout ((FILE *)1) 36 | #define stderr ((FILE *)2) 37 | #endif 38 | 39 | FILE *fopen(const char *filename, const char *mode); 40 | int64_t fread(void *buffer, uint64_t size, uint64_t count, FILE *stream); 41 | int64_t fwrite(const void *buffer, uint64_t size, uint64_t count, FILE *stream); 42 | int64_t fclose(FILE *fp); 43 | int64_t fseek(FILE *fp, uint64_t offest, int set); 44 | 45 | int fputc(int c, FILE *stream); 46 | int fputs(const char *str, FILE *stream); 47 | int printf(const char *format, ...); 48 | int fprintf(FILE *stream, const char *format, ...); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif 53 | 54 | #endif /* LIBCXXRT_STDIO_H */ 55 | -------------------------------------------------------------------------------- /src/include/stdlib.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stdlib.h 4 | * @brief stdlib header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STDLIB_H 18 | #define LIBCXXRT_STDLIB_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #ifndef NULL 25 | #define NULL ((void *)0) 26 | #endif 27 | 28 | #ifndef size_t 29 | #if defined(__i386__) 30 | typedef unsigned int size_t; 31 | #elif defined(__x86_64__) 32 | typedef unsigned long size_t; 33 | #endif 34 | #endif 35 | 36 | void free(void *ptr); 37 | void *malloc(size_t size); 38 | 39 | char *itoa(int n, char *str, int radix); 40 | 41 | typedef void (*atexit_func_t)(void); 42 | int atexit(atexit_func_t func); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* LIBCXXRT_STDLIB_H */ 49 | -------------------------------------------------------------------------------- /src/include/string: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file string 4 | * @brief string 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STRING 18 | #define LIBCXXRT_STRING 19 | 20 | #include "iostream" 21 | #include "stddef.h" 22 | 23 | namespace std { 24 | class string { 25 | private: 26 | size_t len; 27 | char *pbuf; 28 | 29 | protected: 30 | public: 31 | explicit string(const char *str); 32 | string(const string &s); 33 | ~string(void); 34 | string &operator=(const string &s); 35 | string &operator=(const char *s); 36 | const char &operator[](size_t idx) const; 37 | char &operator[](size_t idx); 38 | const char *c_str(void) const; 39 | size_t length(void) const; 40 | size_t size(void) const; 41 | }; 42 | ofstream &operator<<(ofstream &o, const string &s); 43 | }; // namespace std 44 | 45 | #endif /* LIBCXXRT_STRING */ 46 | -------------------------------------------------------------------------------- /src/include/string.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file string.h 4 | * @brief string header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_STRING_H 18 | #define LIBCXXRT_STRING_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "stdint.h" 25 | 26 | int8_t strcmp(const char *src, const char *dst); 27 | char *strcpy(char *dest, const char *src); 28 | uint64_t strlen(const char *str); 29 | void memset(void *dest, uint8_t val, uint32_t len); 30 | void bzero(void *dest, uint32_t len); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* LIBCXXRT_STRING_H */ 37 | -------------------------------------------------------------------------------- /src/include/unistd.h: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file unistd.h 4 | * @brief unistd header 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifndef LIBCXXRT_UNISTD_H 18 | #define LIBCXXRT_UNISTD_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | // linux 系统调用号 25 | #if __linux__ 26 | #define SYSCALL_read 0 27 | #define SYSCALL_write 1 28 | #define SYSCALL_open 2 29 | #define SYSCALL_close 3 30 | #define SYSCALL_lseek 8 31 | #define SYSCALL_mmap 9 32 | #define SYSCALL_exit 60 33 | 34 | #define PROT_READ 0x1 35 | #define PROT_WRITE 0x2 36 | #define MAP_ANON 0x20 37 | #define MAP_PRIVATE 0x2 38 | #define MAP_FAILED ((void *)-1) 39 | 40 | #define O_RDONLY 00000000 41 | #define O_WRONLY 00000001 42 | #define O_RDWR 00000002 43 | #define O_ADDMODE 00000003 44 | #define O_CREAT 00000100 45 | #define O_TRUNC 00001000 46 | #define O_EXCL 00000200 47 | #endif 48 | 49 | #if __APPLE__ 50 | // OSX 的系统调用基于 BSD,需要加上 0x2000000 51 | #define BSD 0x2000000 52 | #define SYSCALL_exit (BSD + 1) 53 | #define SYSCALL_read (BSD + 3) 54 | #define SYSCALL_write (BSD + 4) 55 | #define SYSCALL_open (BSD + 5) 56 | #define SYSCALL_close (BSD + 6) 57 | #define SYSCALL_mmap (BSD + 197) 58 | #define SYSCALL_lseek (BSD + 199) 59 | // mmap 调用参数 60 | #define PROT_READ 0x1 61 | #define PROT_WRITE 0x2 62 | #define MAP_ANON 0x1000 63 | #define MAP_PRIVATE 0x2 64 | #define MAP_FAILED ((void *)-1) 65 | // open mode 66 | // open for reading only 67 | #define O_RDONLY 0x0000 68 | // open for writing only 69 | #define O_WRONLY 0x0001 70 | // open for reading and writing 71 | #define O_RDWR 0x0002 72 | // mask for above modes 73 | #define O_ACCMODE 0x0003 74 | // create if nonexistant 75 | #define O_CREAT 0x0200 76 | // truncate to zero length 77 | #define O_TRUNC 0x0400 78 | // error if already exists 79 | #define O_EXCL 0x0800 80 | #endif 81 | 82 | #ifdef __cplusplus 83 | } 84 | #endif 85 | 86 | #endif /* LIBCXXRT_UNISTD_H */ 87 | -------------------------------------------------------------------------------- /src/iostream.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file iostream.cpp 4 | * @brief iostream cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "iostream" 18 | #include "stddef.h" 19 | #include "string.h" 20 | 21 | #ifdef WIN32 22 | #include 23 | #endif 24 | 25 | namespace std { 26 | ofstream::ofstream(void) : fp(0) { return; } 27 | 28 | ofstream::ofstream(const char *filename, ofstream::openmode md) { 29 | open(filename, md); 30 | return; 31 | } 32 | 33 | ofstream::~ofstream(void) { 34 | close(); 35 | return; 36 | } 37 | 38 | ofstream &ofstream::operator<<(char c) { 39 | fputc(c, fp); 40 | return *this; 41 | } 42 | 43 | ofstream &ofstream::operator<<(int n) { 44 | fprintf(fp, "%d", n); 45 | return *this; 46 | } 47 | 48 | ofstream &ofstream::operator<<(const char *lhs) { 49 | fprintf(fp, "%s", lhs); 50 | return *this; 51 | } 52 | 53 | ofstream &ofstream::operator<<(ofstream &(*manip)(ofstream &)) { 54 | return manip(*this); 55 | } 56 | 57 | void ofstream::open(const char *filename, ofstream::openmode md) { 58 | char mode[4]; 59 | close(); 60 | 61 | switch ((uint8_t)md) { 62 | case out | trunc: { 63 | strcpy(mode, "w"); 64 | break; 65 | } 66 | case out | in | trunc: { 67 | strcpy(mode, "w+"); 68 | break; 69 | } 70 | case out | trunc | binary: { 71 | strcpy(mode, "wb"); 72 | break; 73 | } 74 | case out | in | trunc | binary: { 75 | strcpy(mode, "wb+"); 76 | break; 77 | } 78 | } 79 | fp = fopen(filename, mode); 80 | return; 81 | } 82 | 83 | void ofstream::close(void) { 84 | if (fp != NULL && fp != stdin && fp != stdout && fp != stderr) { 85 | fclose(fp); 86 | fp = 0; 87 | } 88 | return; 89 | } 90 | 91 | ofstream &ofstream::write(const char *buf, unsigned size) { 92 | fwrite(buf, 1, size, fp); 93 | return *this; 94 | } 95 | 96 | stdout_stream::stdout_stream(void) : ofstream() { 97 | fp = stdout; 98 | return; 99 | } 100 | 101 | stdout_stream::stdout_stream(const stdout_stream &) : ofstream() { return; } 102 | 103 | stdout_stream::~stdout_stream(void) { return; } 104 | 105 | // 这里的警告实在消不掉,出此下策 106 | #if __clang__ 107 | #pragma clang diagnostic push 108 | #pragma clang diagnostic ignored "-Wglobal-constructors" 109 | stdout_stream cout; 110 | #pragma clang diagnostic pop 111 | #elif __linux__ 112 | stdout_stream cout; 113 | #endif 114 | }; // namespace std 115 | -------------------------------------------------------------------------------- /src/link.ld: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file link.ld 4 | * @brief link script 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | /* OUTPUT_FORMAT(macho64) */ 18 | 19 | ENTRY(mini_crt_entry) 20 | 21 | SECTIONS { 22 | .text : ALIGN(4K) { 23 | *(.text) 24 | } 25 | 26 | .rodata : ALIGN(4K) { 27 | *(.rodata) 28 | } 29 | 30 | .data : ALIGN(4K) { 31 | PROVIDE(ctors_start = .); 32 | *(.ctor*) 33 | PROVIDE(ctors_end = .); 34 | PROVIDE(dtors_start = .); 35 | *(.dtor*) 36 | PROVIDE(dtors_end = .); 37 | *(.data) 38 | } 39 | 40 | .bss : ALIGN(4K) { 41 | *(COMMON) 42 | *(.bss) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/malloc.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file malloc.c 4 | * @brief malloc c 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "libcxxrt.h" 22 | #include "stddef.h" 23 | #include "unistd.h" 24 | 25 | typedef struct heap_header { 26 | enum { 27 | // magic number of free block 28 | HEAP_BLOCK_FREE = 0xABABABAB, 29 | // magic number of used block 30 | HEAP_BLOCK_USED = 0xCDCDCDCD, 31 | } type; 32 | 33 | uint32_t size; 34 | struct heap_header *prev; 35 | struct heap_header *next; 36 | } heap_header_t; 37 | 38 | #define ADDR_ADD(a, o) (((char *)(a)) + o) 39 | #define HEADER_SIZE (sizeof(heap_header_t)) 40 | 41 | static heap_header_t *list_head = NULL; 42 | 43 | void free(void *ptr) { 44 | heap_header_t *header = (heap_header_t *)ADDR_ADD(ptr, -HEADER_SIZE); 45 | if (header->type != HEAP_BLOCK_USED) { 46 | return; 47 | } 48 | 49 | header->type = HEAP_BLOCK_FREE; 50 | if (header->prev != NULL && header->prev->type == HEAP_BLOCK_FREE) { 51 | // merge 52 | header->prev->next = header->prev; 53 | if (header->next != NULL) { 54 | header->next->prev = header->prev; 55 | } 56 | header->prev->size += header->size; 57 | header = header->prev; 58 | } 59 | if (header->next != NULL && header->next->type == HEAP_BLOCK_FREE) { 60 | // merge 61 | header->size += header->next->size; 62 | header->next = header->next->next; 63 | } 64 | } 65 | 66 | void *malloc(uint64_t size) { 67 | if (size == 0) { 68 | return NULL; 69 | } 70 | heap_header_t *header = list_head; 71 | while (header != NULL) { 72 | if (header->type == HEAP_BLOCK_USED) { 73 | header = header->next; 74 | continue; 75 | } 76 | // 块大小足够 size,但是不够分配 HEADER_SIZE 77 | if (header->size > size + HEADER_SIZE && 78 | header->size <= size + HEADER_SIZE * 2) { 79 | // 设置后返回 80 | header->type = HEAP_BLOCK_USED; 81 | return ADDR_ADD(header, HEADER_SIZE); 82 | } 83 | 84 | // 块大小足够切割出 next 块 85 | if (header->size > size + HEADER_SIZE * 2) { 86 | // 切割 87 | heap_header_t *next = 88 | (heap_header_t *)ADDR_ADD(header, size + HEADER_SIZE); 89 | next->prev = header; 90 | next->next = header->next; 91 | next->type = HEAP_BLOCK_FREE; 92 | next->size = header->size - (size - HEADER_SIZE); 93 | header->next = next; 94 | header->size = size + HEADER_SIZE; 95 | header->type = HEAP_BLOCK_USED; 96 | // 返回 97 | return ADDR_ADD(header, HEADER_SIZE); 98 | } 99 | header = header->next; 100 | } 101 | // 执行到这里说明没有找到 102 | return NULL; 103 | } 104 | 105 | #ifdef WIN32 106 | #include 107 | #else 108 | static void *mmap(uint64_t len) { 109 | void *ret = NULL; 110 | void *addr = NULL; 111 | int64_t prot = PROT_READ | PROT_WRITE; 112 | int64_t flag = MAP_ANON | MAP_PRIVATE; 113 | int64_t fd = -1; 114 | uint64_t off = 0; 115 | #if defined(__i386__) 116 | asm("__syscall6:\n" 117 | " pushl %ebp\n" 118 | " pushl %edi\n" 119 | " pushl %esi\n" 120 | " pushl %ebx\n" 121 | " movl (0+5)*4(%esp),%eax\n" 122 | " movl (1+5)*4(%esp),%ebx\n" 123 | " movl (2+5)*4(%esp),%ecx\n" 124 | " movl (3+5)*4(%esp),%edx\n" 125 | " movl (4+5)*4(%esp),%esi\n" 126 | " movl (5+5)*4(%esp),%edi\n" 127 | " movl (6+5)*4(%esp),%ebp\n" 128 | " int $0x80\n" 129 | " popl %ebx\n" 130 | " popl %esi\n" 131 | " popl %edi\n" 132 | " popl %ebp\n" 133 | " ret"); 134 | extern long __syscall6(long n, long a, long b, long c, long d, long e, 135 | long f); 136 | 137 | long syscall6(long call, long a, long b, long c, long d, long e, long f) { 138 | return __syscall6(call, a, b, c, d, e, f); 139 | } 140 | 141 | ret = (void *)syscall6(SYSCALL_mmap, (long)addr, len, prot, flag, fd, off); 142 | 143 | #elif defined(__x86_64__) 144 | register int64_t r10 __asm__("r10") = flag; 145 | register int64_t r8 __asm__("r8") = fd; 146 | register uint64_t r9 __asm__("r9") = off; 147 | __asm__ __volatile__("syscall" 148 | : "=a"(ret) 149 | : "a"(SYSCALL_mmap), "D"(addr), "S"(len), "d"(prot), 150 | "r"(r10), "r"(r8), "r"(r9) 151 | : "rcx", "r11", "memory"); 152 | #endif 153 | return ret; 154 | } 155 | #endif 156 | 157 | int32_t mini_crt_heap_init() { 158 | // 32MB heap size 159 | uint64_t heap_size = 1024 * 1024 * 32; 160 | 161 | #ifdef WIN32 162 | list_head = (heap_header_t *)VirtualAlloc( 163 | 0, heap_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); 164 | if (list_head == NULL) { 165 | return 0; 166 | } 167 | #else 168 | list_head = (heap_header_t *)mmap(heap_size); 169 | if (list_head == MAP_FAILED) { 170 | return -1; 171 | } 172 | #endif 173 | 174 | list_head->size = heap_size; 175 | list_head->type = HEAP_BLOCK_FREE; 176 | list_head->next = NULL; 177 | list_head->prev = NULL; 178 | return 0; 179 | } 180 | 181 | #ifdef __cplusplus 182 | } 183 | #endif 184 | -------------------------------------------------------------------------------- /src/new_delete.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file new_delete.cpp 4 | * @brief new_delete cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "port.h" 18 | #include "stdlib.h" 19 | 20 | void *operator new(size_t size) { return malloc(size); } 21 | 22 | void *operator new[](size_t size) { return malloc(size); } 23 | 24 | void operator delete(void *p) { 25 | if (p != NULL) { 26 | free(p); 27 | } 28 | } 29 | 30 | void operator delete[](void *p) { 31 | if (p != NULL) { 32 | free(p); 33 | } 34 | } 35 | 36 | void operator delete(void *p, size_t UNUSED(size)) { 37 | if (p != NULL) { 38 | free(p); 39 | } 40 | } 41 | 42 | void operator delete[](void *p, size_t UNUSED(size)) { 43 | if (p != NULL) { 44 | free(p); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/stdio.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file stdio.cpp 4 | * @brief stdio cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "stdio.h" 22 | #include "string.h" 23 | #include "unistd.h" 24 | 25 | int mini_crt_io_init() { return 0; } 26 | 27 | #ifdef WIN32 28 | #include 29 | FILE *fopen(const char **filename, const char *mode) { 30 | HANDLE hfile = 0; 31 | int access = 0; 32 | int creation = 0; 33 | 34 | if (strcmp(mode, "w") == 0) { 35 | access |= GENERIC_WRITE; 36 | creation |= CREATE_ALWAYS; 37 | } 38 | 39 | if (strcmp(mode, "w+") == 0) { 40 | access |= GENERIC_WRITE | GENERIC_READ; 41 | creation |= CREATE_ALWAYS; 42 | } 43 | 44 | if (strcmp(mode, "r") == 0) { 45 | access |= GENERIC_READ; 46 | creation += OPEN_EXISTING; 47 | } 48 | 49 | if (strcmp(mode, "r+") == 0) { 50 | access |= GENERIC_WRITE | GENERIC_READ; 51 | creation |= TRUNCATE_EXISTING; 52 | } 53 | 54 | hFile = CreateFileA(filename, access, 0, 0, creation, 0, 0); 55 | if (hFile == INVALID_HANDLE_VALUE) { 56 | return 0; 57 | } 58 | 59 | return (FILE *)hFile; 60 | } 61 | 62 | int fread(void *buffer, int size, int count, FILE *stream) { 63 | int read = 0; 64 | if (!ReadFile((HANDLE)stream, buffer, size * count, &read, 0)) { 65 | return 0; 66 | } 67 | return read; 68 | } 69 | 70 | int fwrite(const void *buffer, int size, int count, FILE *stream) { 71 | int written = 0; 72 | if (!WriteFile((HANDLE)stream, buffer, size * count, &written, 0)) { 73 | return 0; 74 | } 75 | return written; 76 | } 77 | 78 | int fclose(FILE *fp) { return CloseHandle((HANDLE)fp); } 79 | 80 | int fseek(FILE *fp, int offest, int set) { 81 | return SetFilePointer((HANDLE)fp, offest, 0, set); 82 | } 83 | 84 | #else 85 | 86 | static int64_t read(int fd, void *buffer, uint64_t size) { 87 | int64_t ret = 0; 88 | #if defined(__i386__) 89 | // __asm__ __volatile__("mov $3,%%eax \n\t" 90 | // "mov %1,%%ebx \n\t" 91 | // "mov %2,%%ecx \n\t" 92 | // "mov %3,%%edx \n\t" 93 | // "int $0x80 \n\t" 94 | // : "=m"(ret) 95 | // : "m"(fd), "m"(buffer), "m"(size)); 96 | __asm__ __volatile__("int $0x80" 97 | : "=m"(ret) 98 | : "a"(SYSCALL_read), "b"(fd), "c"(buffer), 99 | "d"((uint32_t)size)); 100 | #elif defined(__x86_64__) 101 | __asm__ __volatile__("syscall" 102 | : "=a"(ret) 103 | : "a"(SYSCALL_read), "D"(fd), "S"(buffer), "d"(size)); 104 | #endif 105 | return ret; 106 | } 107 | 108 | static int64_t write(int fd, const void *buffer, uint64_t size) { 109 | int64_t ret = 0; 110 | #if defined(__i386__) 111 | // __asm__ __volatile__("mov $4,%%eax \n\t" 112 | // "mov %1,%%ebx \n\t" 113 | // "mov %2,%%ecx \n\t" 114 | // "mov %3,%%edx \n\t" 115 | // "int $0x80 \n\t" 116 | // "mov %%eax,%0 \n\t" 117 | // : "=m"(ret) 118 | // : "m"(fd), "m"(buffer), "m"(size)); 119 | __asm__ __volatile__("int $0x80" 120 | : "=m"(ret) 121 | : "a"(SYSCALL_write), "b"(fd), "c"(buffer), 122 | "d"((uint32_t)size)); 123 | #elif defined(__x86_64__) 124 | __asm__ __volatile__("syscall" 125 | : "=a"(ret) 126 | : "a"(SYSCALL_write), "D"(fd), "S"(buffer), "d"(size)); 127 | #endif 128 | return ret; 129 | } 130 | 131 | static int64_t open(const char *pathname, int flags, int mode) { 132 | int fd = 0; 133 | #if defined(__i386__) 134 | // __asm__ __volatile__("mov $5,%%eax \n\t" 135 | // "mov %1,%%ebx \n\t" 136 | // "mov %2,%%ecx \n\t" 137 | // "mov %3,%%edx \n\t" 138 | // "int $0x80 \n\t" 139 | // : "=m"(fd) 140 | // : "m"(pathname), "m"(flags), "m"(mode)); 141 | __asm__ __volatile__("int $0x80" 142 | : "=m"(fd) 143 | : "a"(SYSCALL_open), "b"(pathname), "c"(flags), 144 | "d"(mode)); 145 | #elif defined(__x86_64__) 146 | __asm__ __volatile__("syscall" 147 | : "=a"(fd) 148 | : "a"(SYSCALL_open), "D"(pathname), "S"(flags), 149 | "d"(mode)); 150 | #endif 151 | return fd; 152 | } 153 | 154 | static int64_t close(int fd) { 155 | int64_t ret = 0; 156 | #if defined(__i386__) 157 | __asm__ __volatile__("mov $6,%%eax \n\t" 158 | "mov %1,%%ebx \n\t" 159 | "int $0x80 \n\t" 160 | "mov %%eax,%0 \n\t" 161 | : "=m"(ret) 162 | : "m"(fd)); 163 | #elif defined(__x86_64__) 164 | __asm__ __volatile__("syscall" : "=a"(ret) : "a"(SYSCALL_close), "D"(fd)); 165 | #endif 166 | return ret; 167 | } 168 | 169 | static int64_t seek(int fd, uint64_t offest, int mode) { 170 | int64_t ret = 0; 171 | #if defined(__i386__) 172 | // __asm__ __volatile__("mov $19,%%eax \n\t" 173 | // "mov %1,%%ebx \n\t" 174 | // "mov %2,%%ecx \n\t" 175 | // "mov %3,%%edx \n\t" 176 | // "int $0x80 \n\t" 177 | // "mov %%eax,%0 \n\t" 178 | // : "=m"(ret) 179 | // : "m"(fd), "m"(offest), "m"(mode)); 180 | __asm__ __volatile__("int $0x80" 181 | : "=m"(ret) 182 | : "a"(SYSCALL_lseek), "b"(fd), "c"((uint32_t)offest), 183 | "d"(mode)); 184 | #elif defined(__x86_64__) 185 | __asm__ __volatile__("syscall" 186 | : "=a"(ret) 187 | : "a"(SYSCALL_lseek), "D"(fd), "S"(offest), "d"(mode)); 188 | #endif 189 | return ret; 190 | } 191 | 192 | int64_t fread(void *buffer, uint64_t size, uint64_t count, FILE *stream) { 193 | return read((int)(long)stream, buffer, size * count); 194 | } 195 | 196 | int64_t fwrite(const void *buffer, uint64_t size, uint64_t count, 197 | FILE *stream) { 198 | return write((int)(long)stream, buffer, size * count); 199 | } 200 | 201 | FILE *fopen(const char *filename, const char *mode) { 202 | int fd = -1; 203 | int flags = 0; 204 | // 文件权限 205 | int access = 00700; 206 | 207 | if (strcmp(mode, "w") == 0) { 208 | flags |= O_WRONLY | O_CREAT | O_TRUNC; 209 | } 210 | if (strcmp(mode, "w+") == 0) { 211 | flags |= O_RDWR | O_CREAT | O_TRUNC; 212 | } 213 | if (strcmp(mode, "r") == 0) { 214 | flags |= O_RDONLY; 215 | } 216 | if (strcmp(mode, "r+") == 0) { 217 | flags |= O_RDWR | O_CREAT; 218 | } 219 | fd = open(filename, flags, access); 220 | return (FILE *)(long)fd; 221 | } 222 | 223 | int64_t fclose(FILE *fp) { return close((int)(long)fp); } 224 | 225 | int64_t fseek(FILE *fp, uint64_t offest, int set) { 226 | return seek((int)(long)fp, offest, set); 227 | } 228 | 229 | #ifdef __cplusplus 230 | } 231 | #endif 232 | 233 | #endif /* WIN32 */ 234 | -------------------------------------------------------------------------------- /src/string.c: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file string.c 4 | * @brief string c 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #include "string.h" 22 | #include "stddef.h" 23 | 24 | // 获取字符串长度 25 | uint64_t strlen(const char *str) { 26 | if (str == NULL) { 27 | return 0; 28 | } 29 | uint64_t len = 0; 30 | while (str[len]) { 31 | len++; 32 | } 33 | return len; 34 | } 35 | 36 | // 如果 src > dest, 则返回值大于 0,如果 src = dest, 则返回值等于 0, 37 | // 如果 srd < dest ,则返回值小于 0。 38 | int8_t strcmp(const char *src, const char *dest) { 39 | while (*src && *dest && (*src == *dest)) { 40 | src++; 41 | dest++; 42 | } 43 | return *src - *dest; 44 | } 45 | 46 | char *strcpy(char *dest, const char *src) { 47 | char *address = dest; 48 | while ((*dest++ = *src++) != '\0') { 49 | ; 50 | } 51 | return address; 52 | } 53 | 54 | void backspace(char *src) { 55 | uint64_t len = strlen(src); 56 | src[len - 1] = '\0'; 57 | } 58 | 59 | void append(char *src, char dest) { 60 | uint64_t len = strlen(src); 61 | src[len] = dest; 62 | src[len + 1] = '\0'; 63 | } 64 | 65 | char *strcat(char *dest, const char *src) { 66 | uint8_t *add_d = (uint8_t *)dest; 67 | if (dest != NULL && src != NULL) { 68 | while (*add_d) { 69 | add_d++; 70 | } 71 | while (*src) { 72 | *add_d++ = *src++; 73 | } 74 | } 75 | return dest; 76 | } 77 | 78 | void memcpy(void *dest, void *src, uint32_t len) { 79 | uint8_t *sr = (uint8_t *)src; 80 | uint8_t *dst = (uint8_t *)dest; 81 | while (len != 0) { 82 | *dst++ = *sr++; 83 | len--; 84 | } 85 | } 86 | void memset(void *dest, uint8_t val, uint32_t len) { 87 | for (uint8_t *dst = (uint8_t *)dest; len != 0; len--) { 88 | *dst++ = val; 89 | } 90 | } 91 | 92 | void bzero(void *dest, uint32_t len) { memset(dest, 0, len); } 93 | 94 | char *itoa(int n, char *str, int radix) { 95 | char digit[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 96 | char *p = str; 97 | char *head = str; 98 | if (!p || radix < 2 || radix > 36) { 99 | return p; 100 | } 101 | if (radix != 10 && n < 0) { 102 | return p; 103 | } 104 | if (n == 0) { 105 | *p++ = '0'; 106 | *p = 0; 107 | return p; 108 | } 109 | if (radix == 10 && n < 0) { 110 | *p++ = '-'; 111 | n = -n; 112 | } 113 | while (n) { 114 | *p++ = digit[n % radix]; 115 | n /= radix; 116 | } 117 | *p = 0; 118 | for (--p; head < p; ++head, --p) { 119 | char temp = *head; 120 | *head = *p; 121 | *p = temp; 122 | } 123 | return str; 124 | } 125 | 126 | #ifdef __cplusplus 127 | } 128 | #endif 129 | -------------------------------------------------------------------------------- /src/string.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file string.cpp 4 | * @brief string cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "string.h" 18 | #include "stdint.h" 19 | #include "string" 20 | 21 | namespace std { 22 | string::string(const char *str) : len(0), pbuf(0) { 23 | *this = str; 24 | return; 25 | } 26 | 27 | string::string(const string &s) : len(0), pbuf(0) { 28 | *this = s; 29 | return; 30 | } 31 | 32 | string::~string(void) { 33 | if (pbuf != NULL) { 34 | delete[] pbuf; 35 | pbuf = 0; 36 | } 37 | return; 38 | } 39 | 40 | string &string::operator=(const string &s) { 41 | if (&s == this) { 42 | return *this; 43 | } 44 | this->~string(); 45 | len = s.len; 46 | pbuf = strcpy(new char[len + 1], s.pbuf); 47 | return *this; 48 | } 49 | 50 | string &string::operator=(const char *s) { 51 | this->~string(); 52 | len = strlen(s); 53 | pbuf = strcpy(new char[len + 1], s); 54 | return *this; 55 | } 56 | 57 | const char &string::operator[](size_t idx) const { return pbuf[idx]; } 58 | 59 | char &string::operator[](size_t idx) { return pbuf[idx]; } 60 | 61 | const char *string::c_str(void) const { return pbuf; } 62 | 63 | size_t string::length(void) const { return len; } 64 | 65 | size_t string::size(void) const { return len; } 66 | 67 | ofstream &operator<<(ofstream &o, const string &s) { return o << s.c_str(); } 68 | }; // namespace std 69 | -------------------------------------------------------------------------------- /src/test.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file test.cpp 4 | * @brief test cpp 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-07 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-07Zone.N迁移到 doxygen 14 | *
15 | */ 16 | 17 | #include "iostream" 18 | #include "stdio.h" 19 | #include "stdlib.h" 20 | #include "string" 21 | #include "string.h" 22 | 23 | extern "C" int main(int argc, char *argv[]) { 24 | char buf[128] = {0}; 25 | FILE *fpw = fopen("test.txt", "w"); 26 | char **v = (char **)malloc(argc * sizeof(char *)); 27 | for (int i = 0; i < argc; i++) { 28 | v[i] = (char *)malloc(strlen(argv[i]) + 1); 29 | strcpy(v[i], argv[i]); 30 | } 31 | 32 | for (int i = 0; i < argc; i++) { 33 | fprintf(fpw, "%s\t", v[i]); 34 | } 35 | fclose(fpw); 36 | 37 | FILE *fpr = fopen("test.txt", "r"); 38 | int len = 128; 39 | fread(buf, len, 1, fpr); 40 | printf("%s\n", buf); 41 | fclose(fpr); 42 | 43 | std::cout << "abcd" << std::endl; 44 | std::cout << 233 << std::endl; 45 | std::string msg("msg"); 46 | std::cout << msg << std::endl; 47 | std::cout << msg.c_str() << std::endl; 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置项目名与版本 8 | project( 9 | test 10 | VERSION 0.0.1 11 | ) 12 | 13 | enable_testing() 14 | include(GoogleTest) 15 | 16 | list(APPEND COMMON_TEST_COMPILE_OPTIONS 17 | --coverage 18 | ) 19 | 20 | list(APPEND COMMON_TEST_LINK_OPTIONS 21 | --coverage 22 | -fsanitize=leak 23 | -fsanitize=address 24 | -fno-omit-frame-pointer 25 | ) 26 | 27 | list(APPEND COMMON_TEST_LINK_LIB 28 | gtest_main 29 | ) 30 | 31 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/unit_test) 32 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/integration_test) 33 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/system_test) 34 | 35 | add_coverage( 36 | DEPENDS unit_test integration_test system_test 37 | SOURCE_DIR ${CMAKE_SOURCE_DIR} 38 | BINARY_DIR ${CMAKE_BINARY_DIR} 39 | EXCLUDE_DIR ${CMAKE_SOURCE_DIR}/3rd/* 40 | ) 41 | -------------------------------------------------------------------------------- /test/integration_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置项目名与版本 8 | project( 9 | integration-test 10 | VERSION 0.0.1 11 | ) 12 | 13 | add_executable(integration_test 14 | example.cpp 15 | ) 16 | 17 | target_compile_options(integration_test PRIVATE 18 | ${COMMON_TEST_COMPILE_OPTIONS} 19 | ) 20 | 21 | target_link_options(integration_test PRIVATE 22 | ${COMMON_TEST_LINK_OPTIONS} 23 | ) 24 | 25 | target_link_libraries(integration_test PRIVATE 26 | ${COMMON_TEST_LINK_LIB} 27 | ) 28 | 29 | gtest_discover_tests(integration_test) 30 | -------------------------------------------------------------------------------- /test/integration_test/example.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file example.cpp 4 | * @brief 集成测试示例 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-02 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-02Zone.N创建文件 14 | *
15 | */ 16 | 17 | #include "gtest/gtest.h" 18 | 19 | TEST(example, test_group1) { EXPECT_EQ(0, 0); } 20 | -------------------------------------------------------------------------------- /test/system_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置项目名与版本 8 | project( 9 | system-test 10 | VERSION 0.0.1 11 | ) 12 | 13 | add_executable(system_test 14 | example.cpp 15 | ) 16 | 17 | target_compile_options(system_test PRIVATE 18 | ${COMMON_TEST_COMPILE_OPTIONS} 19 | ) 20 | 21 | target_link_options(system_test PRIVATE 22 | ${COMMON_TEST_LINK_OPTIONS} 23 | ) 24 | 25 | target_link_libraries(system_test PRIVATE 26 | ${COMMON_TEST_LINK_LIB} 27 | ) 28 | 29 | gtest_discover_tests(system_test) 30 | -------------------------------------------------------------------------------- /test/system_test/example.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file example.cpp 4 | * @brief 集成测试示例 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-02 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-02Zone.N创建文件 14 | *
15 | */ 16 | 17 | #include "gtest/gtest.h" 18 | 19 | TEST(example, test_group1) { EXPECT_EQ(0, 0); } 20 | -------------------------------------------------------------------------------- /test/unit_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # This file is a part of MRNIU/libcxxrt 3 | # (https://github.com/MRNIU/libcxxrt). 4 | # 5 | # CMakeLists.txt for MRNIU/libcxxrt. 6 | 7 | # 设置项目名与版本 8 | project( 9 | unit-test 10 | VERSION 0.0.1 11 | ) 12 | 13 | add_executable(unit_test 14 | example.cpp 15 | ) 16 | 17 | target_compile_options(unit_test PRIVATE 18 | ${COMMON_TEST_COMPILE_OPTIONS} 19 | ) 20 | 21 | target_link_options(unit_test PRIVATE 22 | ${COMMON_TEST_LINK_OPTIONS} 23 | ) 24 | 25 | target_link_libraries(unit_test PRIVATE 26 | ${COMMON_TEST_LINK_LIB} 27 | ) 28 | 29 | gtest_discover_tests(unit_test) 30 | -------------------------------------------------------------------------------- /test/unit_test/example.cpp: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * @file example.cpp 4 | * @brief 单元测试示例 5 | * @author Zone.N (Zone.Niuzh@hotmail.com) 6 | * @version 1.0 7 | * @date 2023-09-02 8 | * @copyright MIT LICENSE 9 | * https://github.com/MRNIU/libcxxrt 10 | * @par change log: 11 | * 12 | *
DateAuthorDescription 13 | *
2023-09-02Zone.N创建文件 14 | *
15 | */ 16 | 17 | #include "gtest/gtest.h" 18 | 19 | TEST(example, test_group1) { EXPECT_EQ(0, 0); } 20 | -------------------------------------------------------------------------------- /tools/cppcheck-suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | * 12 | */build* 13 | 14 | 15 | 16 | * 17 | */3rd/* 18 | 19 | 20 | 21 | missingInclude 22 | * 23 | 24 | 25 | 26 | unmatchedSuppression 27 | * 28 | 29 | 30 | -------------------------------------------------------------------------------- /tools/startup.nsh: -------------------------------------------------------------------------------- 1 | fs0: 2 | boot.efi 3 | --------------------------------------------------------------------------------