diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1ed925a..0000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -os: - - linux - - osx - -language: c - -env: - - BRANCH=devel - -addons: - apt: - packages: - - libssh2-1-dev - -before_install: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then HOMEBREW_NO_AUTO_UPDATE=1 brew install libssh2; fi - -install: - - export CHOOSENIM_CHOOSE_VERSION=$BRANCH - - | - curl https://nim-lang.org/choosenim/init.sh -sSf > init.sh - sh init.sh -y - - export PATH=$HOME/.nimble/bin:$PATH - -script: - - nimble install -y - - nimble test diff --git a/README.md b/README.md index 818b8cd..8b4be53 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,3 @@ -[![Chat on Gitter](https://badges.gitter.im/gitterHQ/gitter.png)](https://gitter.im/nimgen/Lobby) -[![Build status](https://ci.appveyor.com/api/projects/status/05t5ja88lmv1rt3r/branch/master?svg=true)](https://ci.appveyor.com/project/genotrance/nimgen/branch/master) -[![Build Status](https://travis-ci.org/genotrance/nimgen.svg?branch=master)](https://travis-ci.org/genotrance/nimgen) - Nimgen is a helper for [c2nim](https://github.com/nim-lang/c2nim/) to simplify and automate the wrapping of C libraries. Nimgen can be used to automate the process of manipulating C files so that c2nim can be run on them without issues. This includes adding/removing code snippets, removal of complex preprocessor definitions that c2nim doesn't yet comprehend and recursively running on #include files. @@ -43,35 +39,25 @@ To see examples of nimgen in action check out the following wrappers:- * [nim-clblast](https://github.com/numforge/nim-clblast) - OpenCL BLAS wrapper * static -* Compile C/C++ code into binary +* Compile C code into binary * [nim7z](https://github.com/genotrance/nim7z) - 7z decoder wrapper: [docs](http://nimgen.genotrance.com/nim7z) * git sparse checkout * [nimarchive](https://github.com/genotrance/nimarchive) - libarchive wrapper: [docs](http://nimgen.genotrance.com/nimarchive) * git sparse checkout * [nimbigwig](https://github.com/genotrance/nimbigwig) - libbigWig wrapper: [docs](http://nimgen.genotrance.com/nimbigwig) * git checkout - * [nimclipboard](https://github.com/genotrance/nimclipboard) - libclipboard wrapper: [docs](http://nimgen.genotrance.com/nimclipboard) - * git checkout - * [nimfastText](https://github.com/genotrance/nimfastText) - fastText wrapper: [docs](http://nimgen.genotrance.com/nimfastText) - * git sparse checkout - * [nimfuzzy](https://github.com/genotrance/nimfuzzy) - fts_fuzzy_match wrapper: [docs](http://nimgen.genotrance.com/nimfuzzy) + * [nimfuzz](https://github.com/genotrance/nimfuzz) - fts_fuzzy_match wrapper: [docs](http://nimgen.genotrance.com/nimfuzz) * download header file * [nimkerberos](https://github.com/genotrance/nimkerberos) - WinKerberos wrapper: [docs](http://nimgen.genotrance.com/nimkerberos) * git sparse checkout - * [nimmonocypher](https://github.com/genotrance/nimmonocypher) - monocypher wrapper: [docs](http://nimgen.genotrance.com/nimmonocypher) - * git sparse checkout - * [nimnuklear](https://github.com/genotrance/nimnuklear) - nuklear wrapper: [docs](https://nimgen.genotrance.com/nimnuklear) - * git sparse checkout * [nimpcre](https://github.com/genotrance/nimpcre) - PCRE wrapper: [docs](http://nimgen.genotrance.com/nimpcre) * git checkout * [nimrax](https://github.com/genotrance/nimrax) - Radix tree wrapper: [docs](http://nimgen.genotrance.com/nimrax) * git checkout * [nimssl](https://github.com/genotrance/nimssl) - OpenSSL wrapper: [docs](http://nimgen.genotrance.com/nimssl) * git sparse checkout - * [nimtess2](https://github.com/genotrance/nimtess2) - libtess2 wrapper: [docs](http://nimgen.genotrance.com/nimtess2) - * git checkout - * [duktape-nim](https://github.com/manguluka/duktape-nim) - Duktape wrapper - * static + * [libsvm](https://github.com/genotrance/libsvm) - libsvm wrapper: [docs](http://nimgen.genotrance.com/libsvm) + * git sparse checkout * Compile in as static binary * [nimssh2](https://github.com/genotrance/nimssh2) - libssh2 wrapper: [docs](http://nimgen.genotrance.com/nimssh2) @@ -92,8 +78,6 @@ In all sections below, environment variables are supported via Nim's string inte "${output}/library/include" "${MY_INCLUDE_PATH}/include" -Append -win, -lin and -mac/osx for OS specific sections and tasks. E.g. n.global-win, n.post-lin, download-win, execute-lin-mac.unique1. -unix can be used as a shortcut for -lin-mac. - _[n.global]_ ```output``` = name of the Nimble project once installed, also location to place generated .nim files @@ -120,21 +104,17 @@ List of all directories or files to exclude from all parsing. If an entry here m _[n.prepare]_ -The following keys can be used to prepare dependencies such as downloading ZIP files, cloning Git repositories, etc. Multiple entries are possible by appending any .string to the key. E.g. download.file1. +The following keys can be used to prepare dependencies such as downloading ZIP files, cloning Git repositories, etc. Multiple entries are possible by appending any .string to the key. E.g. download.file1. -win, -lin and -osx can be used for OS specific tasks. E.g. download-win ```download``` = url to download to the output directory. ZIP files are automatically extracted. Files are not redownloaded if already present but re-extracted ```extract``` = ZIP file to extract in case they are local and don't need to be downloaded. Path is relative to output directory. -```gitcheckout``` = branch, commit or tag of repository to checkout in following Git command, resets after each use. Use "-b name" for branches - -```gitoutput``` = directory for all following Git commands relative to `n.global:output` [default: `n.global:output` directory] - -```git``` = url of Git repository to clone. Full repo is pulled so gitremote + gitsparse is preferable. Resets if already present +```git``` = url of Git repository to clone. Full repo is pulled so gitremote + gitsparse is preferable. Resets to HEAD if already present ```gitremote``` = url of Git repository to partially checkout. Use with gitsparse to pull only files and dirs of interest -```gitsparse``` = list of files and/or dirs to include in partial checkout, one per line. Resets if already present +```gitsparse``` = list of files and/or dirs to include in partial checkout, one per line. Resets to HEAD if already present ```execute``` = command to run during preparation @@ -144,9 +124,7 @@ _[n.post]_ This section is the same as the prepare section, but for performing actions after the project has been processed. -```gitoutput``` = output directory for Git reset [default: `n.global:output` directory] - -```reset``` = perform a Git reset on all files after processing [default: false] +```reset``` = whether or not to perform a git reset on all files after processing [default: false] ```execute``` = command to run after processing @@ -156,13 +134,9 @@ File wildcards such as *.nim, ssl*.h, etc. can be used to perform tasks across a ```wildcard``` = pattern to match against. All keys following the wildcard declaration will apply to matched files -_[n.sourcefile]_ - -This section allows selection of multiple sourcefiles without requiring a detailed section for each file. Each specific file can be listed one line at a time and file wildcards can be used to include multiple source files. E.g. `$output/include/*/h`. `[n.wildcard]` definitions can be used to perform common operations on these source files if required. - _[sourcefile]_ -The following keys apply to library source code and help with generating the .nim files. -win, -lin and -osx can be used for OS specific tasks. E.g. dynlib-win, pragma-win. +The following keys apply to library source code and help with generating the .nim files. -win, -lin and -osx can be used for OS specific tasks. E.g. dynlib-win, pragma-win ```recurse``` = find #include files and process them [default: false] @@ -180,13 +154,9 @@ The following keys apply to library source code and help with generating the .ni ```noprocess``` = do not process this source file with c2nim [default: false] - this is useful if a file only needs to be manipulated -```nowildcard``` = ignore any wildcard definitions for this sourcefile - -```reset``` = reset the file back to original state after all processing [default: false] - Multiple entries for the all following keys are possible by appending any .string to the key. E.g. dynlib.win, compile.dir -```compile``` = file or dir of files of source code to {.compile.} into generated .nim. If directory, picks *.c if C mode and *.cxx, *.cpp, *.cc, *.c++ and *.C for cpp mode. Dir can also include wildcards. e.g. compile = """dir/A*.cxx""" +```compile``` = file or dir of files of source code to {.compile.} into generated .nim ```pragma``` = pragmas to define in generated .nim file. E.g. pragma = "passL: \"-lssl\"" => {.passL: "-lssl".} @@ -196,19 +166,15 @@ The following keys apply to library source code (before processing) and generate ```create``` = create a file at exact location with contents specified. File needs to be in the _[n.exclude]_ list in order to be created. -```pipe``` = execute a command on a file and store the output of the command as the new file contents. E.g. pipe = "cat $file | grep 'static inline'" - ```search``` = search string providing context for following prepend/append/replace directives -```regex``` = regex search string providing context for the following replace directive. Specify using """ to avoid regex parsing issues +```pipe``` = execute a command on a file and store the output of the command as the new file contents. Ex: pipe = "cat $file | grep 'static inline'" ```prepend``` = string value to prepend into file at beginning or before search ```append``` = string value to append into file at the end or after search -```replace``` = string value to replace search string in file. Regex captures can be referred to using $1, $2, etc. - -```move``` = search string providing context for location to move the results of a preceding search or regex match +```replace``` = string value to replace search string in file ```comment``` = number of lines to comment from search location @@ -222,41 +188,6 @@ The following key only applies before processing and allows renaming the generat `$replace(srch1=repl1, srch2=reply2)` = rename specific portions in `$nimout` -__Command Line__ - -A subset of capabilities are available through the command line to enable quick tests using nimgen. Command line flags only apply to source files specified on the command line and do not influence any ```cfg``` files which are expected to be self-sufficient. - -``` -Usage: - nimgen [options] file.cfg|file.h ... - -Params: - -C add compile entry * - -E add n.exclude entry * - -F set c2nim flags * - -I add n.include dir * - -O set output directory - -P set preprocessor flags * - -Options: - -c set ctags = true - -d set defines = true - -i set inline = true - -n set noprocess = true - -p set preprocess = true - -r set recurse = true - -Editing: - -a append string * - -e prepend string * - -l replace string * - -o#lines comment X lines * - -s search string * - -x regex search string * - -* supports multiple instances -``` - __Feedback__ Nimgen is a work in progress and any feedback or suggestions are welcome. It is hosted on [GitHub](https://github.com/genotrance/nimgen) with an MIT license so issues, forks and PRs are most appreciated. Also join us at https://gitter.im/nimgen/Lobby to chat about nimgen and the future of Nim wrappers. diff --git a/appveyor.yml b/appveyor.yml index 7d8dabf..a54b7ce 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,11 +7,6 @@ image: matrix: fast_finish: true -environment: - matrix: - - NIM_VERSION: 0.20.0 - - NIM_VERSION: 0.19.6 - for: - matrix: @@ -19,80 +14,90 @@ for: - image: Visual Studio 2017 environment: - ARCH: 32 - MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf + MINGW_DIR: mingw32 + MINGW_URL: https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/8.1.0/threads-posix/dwarf/i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z/download MINGW_ARCHIVE: i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z - SFNET_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686 - LIBSSH2_ARCHIVE: mingw-w64-i686-libssh2-1.8.0-1-any.pkg - LIBCRYPTO_ARCHIVE: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg + NIM_URL: https://nim-lang.org/download/nim-0.18.0_x32.zip + NIM_ARCHIVE: nim-0.18.0_x32.zip + NIM_VERSION: nim-0.18.0 + LIBSSH2_ARCHIVE: mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz + LIBSSH2_ARCHIVE2: mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar + LIBSSH2_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz/download + LIBCRYPTO_ARCHIVE: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz + LIBCRYPTO_ARCHIVE2: mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar + LIBCRYPTO_URL: https://sourceforge.net/projects/msys2/files/REPOS/MINGW/i686/mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz/download + DLLS_URL: http://nim-lang.org/download/dlls.zip + DLLS_ARCHIVE: dlls.zip + BASE_DIR: c:\projects install: - - CD c:\ - - IF not exist "binaries" ( - echo %NIM_VERSION% && - MKDIR binaries && - CD binaries && - appveyor DownloadFile "%MINGW_URL%/%MINGW_ARCHIVE%/download" -FileName "%MINGW_ARCHIVE%" && - 7z x -y "%MINGW_ARCHIVE%"> nul && - del "%MINGW_ARCHIVE%" && - appveyor DownloadFile "%SFNET_URL%/%LIBSSH2_ARCHIVE%.tar.xz/download" -FileName "%LIBSSH2_ARCHIVE%.tar.xz" && - 7z x -y "%LIBSSH2_ARCHIVE%.tar.xz"> nul && - del "%LIBSSH2_ARCHIVE%.tar.xz" && - 7z x -y "%LIBSSH2_ARCHIVE%.tar"> nul && - del "%LIBSSH2_ARCHIVE%.tar" && - appveyor DownloadFile "%SFNET_URL%/%LIBCRYPTO_ARCHIVE%.tar.xz/download" -FileName "%LIBCRYPTO_ARCHIVE%.tar.xz" && - 7z x -y "%LIBCRYPTO_ARCHIVE%.tar.xz"> nul && - del "%LIBCRYPTO_ARCHIVE%.tar.xz" && - 7z x -y "%LIBCRYPTO_ARCHIVE%.tar"> nul && - del "%LIBCRYPTO_ARCHIVE%.tar" && - appveyor DownloadFile "https://nim-lang.org/download/nim-%NIM_VERSION%_x%ARCH%.zip" -FileName "nim-%NIM_VERSION%_x%ARCH%.zip" && - 7z x -y "nim-%NIM_VERSION%_x%ARCH%.zip"> nul && - del "nim-%NIM_VERSION%_x%ARCH%.zip") - - SET PATH=c:\binaries\mingw%ARCH%\bin;c:\binaries\nim-%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH% - - CD c:\projects\nimgen + - CD %BASE_DIR% + - IF not exist "%MINGW_ARCHIVE%" appveyor DownloadFile "%MINGW_URL%" -FileName "%MINGW_ARCHIVE%" + - 7z x -y "%MINGW_ARCHIVE%"> nul + - IF not exist "%LIBSSH2_ARCHIVE%" appveyor DownloadFile "%LIBSSH2_URL%" -FileName "%LIBSSH2_ARCHIVE%" + - 7z x -y "%LIBSSH2_ARCHIVE%"> nul + - 7z x -y "%LIBSSH2_ARCHIVE2%"> nul + - IF not exist "%LIBCRYPTO_ARCHIVE%" appveyor DownloadFile "%LIBCRYPTO_URL%" -FileName "%LIBCRYPTO_ARCHIVE%" + - 7z x -y "%LIBCRYPTO_ARCHIVE%"> nul + - 7z x -y "%LIBCRYPTO_ARCHIVE2%"> nul + - IF not exist "%NIM_ARCHIVE%" appveyor DownloadFile "%NIM_URL%" -FileName "%NIM_ARCHIVE%" + - 7z x -y "%NIM_ARCHIVE%"> nul + - SET PATH=%BASE_DIR%\%MINGW_DIR%\bin;%BASE_DIR%\%NIM_VERSION%\bin;%USERPROFILE%\.nimble\bin;%PATH% + - CD %BASE_DIR%\nimgen + # - git clone --depth 1 https://github.com/nim-lang/nim + # - cd nim + # - git clone --depth 1 https://github.com/nim-lang/csources + # - cd csources + # - IF "%PLATFORM%" == "x64" ( build64.bat ) else ( build.bat ) + # - cd .. + # - IF not exist "%DLLS_ARCHIVE%" appveyor DownloadFile "%DLLS_URL%" -FileName "%DLLS_ARCHIVE%" + # - 7z x -y "%DLLS_ARCHIVE%" -o"%CD%\bin"> nul + # - bin\nim c -d:release koch + # - koch boot -d:release + # - koch nimble -d:release + # - SET PATH=%CD%\bin;%PATH% + # - cd .. on_finish: - - 7z a -r buildlogs-win-pkgs.zip %USERPROFILE%\.nimble\pkgs - - appveyor PushArtifact buildlogs-win-pkgs.zip - - 7z a -r buildlogs-win-projects.zip c:\projects\* - - appveyor PushArtifact buildlogs-win-projects.zip - - 7z a -r nimgen-docs.zip c:\projects\nimgen\web - - appveyor PushArtifact nimgen-docs.zip + - 7z a -r buildlogs-win.zip %USERPROFILE%\.nimble\pkgs + - appveyor PushArtifact buildlogs-win.zip cache: - - c:\binaries + - c:\projects\i686-8.1.0-release-posix-dwarf-rt_v6-rev0.7z + - c:\projects\mingw-w64-i686-libssh2-1.8.0-1-any.pkg.tar.xz + - c:\projects\mingw-w64-i686-openssl-1.0.2.o-1-any.pkg.tar.xz + - c:\projects\nim-0.18.0_x32.zip - matrix: only: - image: Ubuntu + environment: + NIM_URL: https://nim-lang.org/download/nim-0.18.0.tar.xz + NIM_ARCHIVE: nim-0.18.0.tar.xz + NIM_VERSION: nim-0.18.0 + install: - sudo apt -qq update - - sudo apt -qq install --yes libssh2-1-dev libgcrypt20-dev libgpg-error-dev - - if [ ! -e /home/appveyor/binaries ]; then - echo $NIM_VERSION && - mkdir /home/appveyor/binaries && - cd /home/appveyor/binaries && - curl -s -o nim-$NIM_VERSION.tar.xz https://nim-lang.org/download/nim-$NIM_VERSION.tar.xz && - tar xJf nim-$NIM_VERSION.tar.xz && - cd nim-$NIM_VERSION && - sh build.sh && - bin/nim c -d:release koch && - ./koch boot -d:release && - ./koch nimble -d:release; - fi - - export PATH=/home/appveyor/binaries/nim-$NIM_VERSION/bin:~/.nimble/bin:$PATH - - cd /home/appveyor/projects/nimgen + - sudo apt -qq install --yes python-pygments libssh2-1-dev libgcrypt20-dev libgpg-error-dev + - cd ~/projects + - if [ ! -e $NIM_ARCHIVE ]; then curl -s -o $NIM_ARCHIVE $NIM_URL; fi + - tar xJf $NIM_ARCHIVE + - cd $NIM_VERSION + - sh build.sh + - bin/nim c -d:release koch + - ./koch boot -d:release + - ./koch nimble -d:release + - export PATH=~/projects/$NIM_VERSION/bin:~/.nimble/bin:$PATH + - cd ~/projects/nimgen on_finish: - - zip -r -q buildlogs-lin-pkgs.zip ~/.nimble/pkgs - - appveyor PushArtifact buildlogs-lin-pkgs.zip - - zip -r -q buildlogs-lin-projects.zip /home/appveyor/projects - - appveyor PushArtifact buildlogs-lin-projects.zip + - zip -r -q buildlogs-lin.zip ~/.nimble/pkgs + - appveyor PushArtifact buildlogs-lin.zip cache: - - /home/appveyor/binaries + - ~/projects/nim-0.18.0.tar.xz build_script: - nimble install -y diff --git a/nimgen.nimble b/nimgen.nimble index fc7409e..59de8ed 100644 --- a/nimgen.nimble +++ b/nimgen.nimble @@ -1,18 +1,17 @@ # Package -version = "0.5.1" +version = "0.3.0" author = "genotrance" description = "c2nim helper to simplify and automate the wrapping of C libraries" license = "MIT" bin = @["nimgen"] srcDir = "src" -skipDirs = @["nimgen", "tests", "web"] +skipDirs = @["nimgen", "tests"] # Dependencies -requires "nim >= 0.19.0", "c2nim >= 0.9.14", "regex >= 0.10.0" +requires "nim >= 0.17.0", "c2nim >= 0.9.13", "regex >= 0.7.1" task test, "Test nimgen": - exec "nim c -r tests/rununittests.nim" exec "nim e tests/nimgentest.nims" diff --git a/src/nimgen.nim b/src/nimgen.nim index dc98ae4..5777398 100644 --- a/src/nimgen.nim +++ b/src/nimgen.nim @@ -2,4 +2,6 @@ import os import nimgen/runcfg -runCli() +for i in commandLineParams(): + if i != "-f": + runCfg(i) diff --git a/src/nimgen/c2nim.nim b/src/nimgen/c2nim.nim index c9ccff7..07b15e0 100644 --- a/src/nimgen/c2nim.nim +++ b/src/nimgen/c2nim.nim @@ -1,63 +1,58 @@ -import os, regex, strutils - -when (NimMajor, NimMinor, NimPatch) < (0, 19, 9): - import ospaths +import os, ospaths, regex, strutils import external, file, fileops, gencore, globals -proc relativePath(path: string): string = - if gOutput.len() == 0: - result = path - else: - # multiReplace() bug - #9557 - result = path.replace(gOutput, "") - return result.multiReplace([("\\", "/"), ("//", "/")]) +template relativePath(path: untyped): untyped = + path.multiReplace([(gOutput, ""), ("\\", "/"), ("//", "/")]) proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = var file = search(fl) - if file.len() == 0: + if file == "": return - echo "Generating " & outfile + if file in gDoneRecursive: + return + + echo "Processing $# => $#" % [file, outfile] + gDoneRecursive.add(file) + + # Remove static inline function bodies + removeStatic(file) + + fixFuncProtos(file) var cfile = file if c2nimConfig.preprocess: cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFileFlush(cfile, runPreprocess(file, c2nimConfig.ppflags, c2nimConfig.flags, c2nimConfig.inline)) + writeFile(cfile, runPreprocess(file, c2nimConfig.ppflags, c2nimConfig.flags, c2nimConfig.inline)) elif c2nimConfig.ctags: cfile = "temp-$#.c" % [outfile.extractFilename()] - writeFileFlush(cfile, runCtags(file)) - - if c2nimConfig.removeBodies: - removeBodies(cfile) + writeFile(cfile, runCtags(file)) if c2nimConfig.defines and (c2nimConfig.preprocess or c2nimConfig.ctags): prepend(cfile, getDefines(file, c2nimConfig.inline)) - removeStatic(cfile) var extflags = "" passC = "" outlib = "" outpragma = "" - passC = "import strutils\n" - - passC &= """const sourcePath = currentSourcePath().split({'\\', '/'})[0..^2].join("/")""" & "\n" + passC = "import ospaths, strutils\n" for inc in gIncludes: if inc.isAbsolute(): - passC &= ("""{.passC: "-I\"$#\"".}""" % [inc.sanitizePath()]) & "\n" + passC &= ("""{.passC: "-I\"$#\"".}""" % [inc]) & "\n" else: passC &= ( - """{.passC: "-I\"" & sourcePath & "$#\"".}""" % + """{.passC: "-I\"" & currentSourcePath().splitPath().head & "$#\"".}""" % inc.relativePath() ) & "\n" for prag in c2nimConfig.pragma: outpragma &= "{." & prag & ".}\n" - let fname = file.splitFile().name.multiReplace([(".", "_"), ("-", "_")]) + let fname = file.splitFile().name.replace(re"[\.\-]", "_") if c2nimConfig.dynlib.len() != 0: let @@ -91,13 +86,14 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = if file.isAbsolute(): passC &= "const header$# = \"$#\"\n" % [fname, file] else: - passC &= "const header$# = sourcePath & \"$#\"\n" % + passC &= "const header$# = currentSourcePath().splitPath().head & \"$#\"\n" % [fname, file.relativePath()] extflags = "--header:header$#" % fname + # Run c2nim on generated file var cmd = "c2nim $# $# --out:$# $#" % [c2nimConfig.flags, extflags, outfile, cfile] when defined(windows): - cmd = "cmd /c " & cmd.quoteShell + cmd = "cmd /c " & cmd discard execProc(cmd) if c2nimConfig.preprocess or c2nimConfig.ctags: @@ -105,18 +101,18 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = removeFile(cfile) except: discard - else: - if c2nimConfig.removeBodies: - reAddBodies(cfile) - reAddStatic(cfile) # Nim doesn't like {.cdecl.} for type proc() - freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$1") + freplace(outfile, re"(?m)(.*? = proc.*?)\{.cdecl.\}", "$#") freplace(outfile, " {.cdecl.})", ")") # Include {.compile.} directives for cpl in c2nimConfig.compile: - prepend(outfile, compile(cpl, c2nimConfig.flags)) + let fcpl = search(cpl) + if getFileInfo(fcpl).kind == pcFile: + prepend(outfile, compile(file=fcpl)) + else: + prepend(outfile, compile(dir=fcpl)) # Add any pragmas if outpragma != "": @@ -129,3 +125,6 @@ proc c2nim*(fl, outfile: string, c2nimConfig: c2nimConfigObj) = # Add dynamic library if outlib != "": prepend(outfile, outlib) + + # Add back static functions for compilation + reAddStatic(file) diff --git a/src/nimgen/external.nim b/src/nimgen/external.nim index a887e20..f642cfb 100644 --- a/src/nimgen/external.nim +++ b/src/nimgen/external.nim @@ -1,30 +1,28 @@ -import os, osproc, regex, streams, strutils +import os, osproc, regex, ropes, streams, strutils import globals -proc sanitizePath*(path: string): string = - path.multiReplace([("\\", "/"), ("//", "/")]) - proc execProc*(cmd: string): string = - var ret: int + result = "" + var + p = startProcess(cmd, options = {poStdErrToStdOut, poUsePath, poEvalCommand}) - (result, ret) = execCmdEx(cmd) - if ret != 0: - echo "Command failed: " & $ret + outp = outputStream(p) + line = newStringOfCap(120).TaintedString + + while true: + if outp.readLine(line): + result.add(line) + result.add("\n") + elif not running(p): break + + var x = p.peekExitCode() + if x != 0: + echo "Command failed: " & $x echo cmd echo result quit(1) -proc execAction*(cmd: string): string = - var ccmd = "" - when defined(Windows): - ccmd = "cmd /c " & cmd.replace("/", "\\") - when defined(Linux) or defined(MacOSX): - ccmd = "bash -c '" & cmd & "'" - - echo "Running '" & ccmd[0.. 4: if spl[0] != "main" and spl[3] != "member": var fn = "" diff --git a/src/nimgen/file.nim b/src/nimgen/file.nim index 81e1d86..1a316bf 100644 --- a/src/nimgen/file.nim +++ b/src/nimgen/file.nim @@ -1,17 +1,14 @@ -import os, pegs, regex, strutils, tables +import os, ospaths, pegs, regex, strutils, tables -when (NimMajor, NimMinor, NimPatch) < (0, 19, 9): - import ospaths - -import globals, external +import globals # ### # File loction proc getNimout*(file: string, rename=true): string = - result = file.splitFile().name.multiReplace([("-", "_"), (".", "_")]) & ".nim" + result = file.splitFile().name.replace(re"[\-\.]", "_") & ".nim" if gOutput != "": - result = gOutput & "/" & result + result = gOutput/result if not rename: return @@ -19,7 +16,8 @@ proc getNimout*(file: string, rename=true): string = if gRenames.hasKey(file): result = gRenames[file] - createDir(parentDir(result)) + if not dirExists(parentDir(result)): + createDir(parentDir(result)) proc exclude*(file: string): bool = for excl in gExcludes: @@ -37,7 +35,7 @@ proc search*(file: string): string = elif not fileExists(result) and not dirExists(result): var found = false for inc in gIncludes: - result = inc & "/" & file + result = inc/file if fileExists(result) or dirExists(result): found = true break @@ -46,7 +44,7 @@ proc search*(file: string): string = quit(1) # Only keep relative directory - return result.sanitizePath.replace(gProjectDir & "/", "") + return result.multiReplace([("\\", $DirSep), ("//", $DirSep), (gProjectDir & $DirSep, "")]) proc rename*(file: string, renfile: string) = if file.splitFile().ext == ".nim": @@ -71,7 +69,7 @@ proc rename*(file: string, renfile: string) = final = final.replace(srch, repl) newname = newname.replace(matches[0], final) - gRenames[file] = gOutput & "/" & newname + gRenames[file] = gOutput/newname # ### # Actions @@ -84,12 +82,6 @@ proc openRetry*(file: string, mode: FileMode = fmRead): File = except IOError: sleep(100) -template writeFileFlush*(file, content: string): untyped = - let f = openRetry(file, fmWrite) - f.write(content) - f.flushFile() - f.close() - template withFile*(file: string, body: untyped): untyped = if fileExists(file): var f = openRetry(file) @@ -101,7 +93,9 @@ template withFile*(file: string, body: untyped): untyped = body if content != contentOrig: - writeFileFlush(file, content) + f = openRetry(file, fmWrite) + write(f, content) + f.close() else: echo "Missing file " & file diff --git a/src/nimgen/fileops.nim b/src/nimgen/fileops.nim index 7f16139..c4e67a0 100644 --- a/src/nimgen/fileops.nim +++ b/src/nimgen/fileops.nim @@ -31,25 +31,20 @@ proc append*(file: string, data: string, search="") = if idx != -1: content = content[0.. add compile entry * - -E add n.exclude entry * - -F set c2nim flags * - -I add n.include dir * - -O set output directory - -P set preprocessor flags * - -Options: - -c set ctags = true - -d set defines = true - -i set inline = true - -n set noprocess = true - -p set preprocess = true - -r set recurse = true - -Editing: - -a append string * - -e prepend string * - -l replace string * - -o#lines comment X lines * - -s search string * - -x regex search string * - -* supports multiple instances -""" - -proc runCli*() = - var - cfg = newOrderedTable[string, string]() - files: seq[string] - uniq = 1 - - gProjectDir = getCurrentDir().sanitizePath - for param in commandLineParams(): - let flag = if param.len() <= 2: param else: param[0..<2] - - if fileExists(param): - if param.splitFile().ext.toLowerAscii() == ".cfg": - runCfg(param) - else: - files.add(param) - - elif flag == "-C": - cfg["compile." & $uniq] = param[2..^1] - elif flag == "-E": - gExcludes.add(param[2..^1].addEnv().sanitizePath) - elif flag == "-F": - if cfg.hasKey("flags"): - cfg["flags"] = cfg["flags"] & " " & param[2..^1] - else: - cfg["flags"] = param[2..^1] - elif flag == "-I": - gIncludes.add(param[2..^1].addEnv().sanitizePath) - elif flag == "-O": - setOutputDir(param[2..^1]) - elif flag == "-P": - if cfg.hasKey("ppflags"): - cfg["ppflags"] = cfg["ppflags"] & " " & param[2..^1] - else: - cfg["ppflags"] = param[2..^1] - - elif flag == "-c": - cfg["ctags"] = "true" - elif flag == "-d": - cfg["defines"] = "true" - elif flag == "-i": - cfg["inline"] = "true" - elif flag == "-n": - cfg["noprocess"] = "true" - elif flag == "-p": - cfg["preprocess"] = "true" - elif flag == "-r": - cfg["recurse"] = "true" - - elif flag == "-a": - cfg["append." & $uniq] = param[2..^1] - elif flag == "-e": - cfg["prepend." & $uniq] = param[2..^1] - elif flag == "-l": - cfg["replace." & $uniq] = param[2..^1] - elif flag == "-o": - cfg["comment." & $uniq] = param[2..^1] - elif flag == "-s": - cfg["search." & $uniq] = param[2..^1] - elif flag == "-x": - cfg["regex." & $uniq] = param[2..^1] - - elif param == "-h" or param == "-?" or param == "--help": - echo gHelp - quit(0) - - uniq += 1 - - for file in files: - runFile(file, cfg) + if gConfig.hasKey("n.post"): + for post in gConfig["n.post"].keys(): + let (key, val) = getKey(post) + if val == true: + let postVal = gConfig["n.post"][post] + if key == "reset": + gitReset() + elif key == "execute": + discard execProc(postVal) diff --git a/tests/nimgentest.nims b/tests/nimgentest.nims index 0de436a..f5136c6 100644 --- a/tests/nimgentest.nims +++ b/tests/nimgentest.nims @@ -1,78 +1,54 @@ -import distros, ospaths, strutils +import distros +import ospaths +import strutils var - pygonly = false - comps = @["nim7z", #"nimarchive", - "nimbass", "nimbigwig", - "nimclipboard", "nimfuzzy", "nimmonocypher", - #"nimnuklear", - "nimpcre", "nimrax", "nimssl", "nimssh2", - "nimtess2" - ] - -let - gccver = staticExec("gcc --version").split("\n")[0].split(" ")[^1] - nimver = staticExec("nim -v").split("\n")[0].split(" ")[3] - -if nimver >= "0.19.0" and (gccver >= "5.0.0" or detectOs(MacOSX)): - comps.add("nimfastText") + full = false + comps = @["libsvm", "nim7z", "nimarchive", "nimbass", "nimbigwig", "nimfuzz", + "nimpcre", "nimrax", "nimssl", "nimssh2"] if detectOs(Windows): comps.add("nimkerberos") -if not detectOs(MacOSX): - comps.add("nimzbar") - -echo "Nim version: " & nimver -echo "GCC version: " & gccver - -echo "Testing comps:" -for comp in comps: - echo " " & comp - if paramCount() > 2: for i in 3 .. paramCount(): - if paramStr(i) == "--pygonly": - pygonly = true + if paramStr(i) == "--full": + full = true elif paramStr(i).len() > 10 and "--comps=" in paramStr(i)[0 ..< 8]: comps = paramStr(i)[8 .. ^1].split(",") for comp in comps: - if not pygonly: - if not dirExists(".."/comp): - withDir(".."): - exec "git clone --depth=1 https://github.com/genotrance/" & comp + if not dirExists(".."/comp): + withDir(".."): + exec "git clone --depth=1 https://github.com/genotrance/" & comp - exec "nimble uninstall -y " & comp, "", "" - withDir(".."/comp): - exec "git pull" + exec "nimble uninstall -y " & comp, "", "" + withDir(".."/comp): + exec "git pull" + if full: rmDir(comp) exec "nimble install -y" exec "nimble test" - exec "nimble install -y" - exec "nimble test" + exec "nimble install -y" + exec "nimble test" - when defined(windows): - if not pygonly: - if dirExists("web"/comp): - rmDir("web"/comp) + if dirExists("web"/comp): + rmDir("web"/comp) - mkDir("web"/comp) - for file in listFiles(".."/comp/comp) & listFiles(".."/comp): - if file.splitFile().ext == ".nim": - cpFile(file, "web"/comp/extractFilename(file)) + mkDir("web"/comp) + for file in listFiles(".."/comp/comp) & listFiles(".."/comp): + if file.splitFile().ext == ".nim": + cpFile(file, "web"/comp/extractFilename(file)) - cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg") - withDir("web"/comp): - for file in listFiles("."): - if file.splitFile().ext == ".nim": - if not pygonly: - exec "nim doc --git.url:. --index:on -o:" & file.changeFileExt("html") & " " & file - exec "pygmentize -f html -O full,linenos=1,anchorlinenos=True,lineanchors=L,style=vs -o " & file & ".html " & file + cpFile("web"/"nimdoc.cfg", "web"/comp/"nimdoc.cfg") + withDir("web"/comp): + for file in listFiles("."): + if file.splitFile().ext == ".nim": + exec "nim doc --git.url:. --index:on -o:" & file.changeFileExt("html") & " " & file + exec "pygmentize -f html -O full,linenos=1,anchorlinenos=True,lineanchors=L,style=vs -o " & file & ".html " & file - if not pygonly: - exec "nim buildIndex -o:index.html ." - rmFile("web"/comp/"nimdoc.cfg") + exec "nim buildIndex -o:index.html ." + rmFile("web"/comp/"nimdoc.cfg") diff --git a/tests/rununittests.nim b/tests/rununittests.nim deleted file mode 100644 index 865f77d..0000000 --- a/tests/rununittests.nim +++ /dev/null @@ -1,10 +0,0 @@ -import os, osproc, strutils - -proc main() = - var failures = 0 - for file in walkFiles(currentSourcePath().splitPath().head / "unittests/*.nim"): - let (path, fname, ext) = file.splitFile() - if fname.startswith("test"): - failures += execCmd "nim c -r " & file - quit(failures) -main() diff --git a/tests/unittests/common.nim b/tests/unittests/common.nim deleted file mode 100644 index 1769b01..0000000 --- a/tests/unittests/common.nim +++ /dev/null @@ -1,5 +0,0 @@ -import unittest - -proc checkFile*(filepath, expected: string) = - let result = readFile(filepath) - check result == expected diff --git a/tests/unittests/data/teststaticexpectedfrontbraces.h b/tests/unittests/data/teststaticexpectedfrontbraces.h deleted file mode 100644 index d8c6a0d..0000000 --- a/tests/unittests/data/teststaticexpectedfrontbraces.h +++ /dev/null @@ -1,675 +0,0 @@ -/** - * @file ipc.h - * @brief Inter-process communication handling - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../result.h" -#include "../arm/tls.h" -#include "../kernel/svc.h" - -/// IPC input header magic -#define SFCI_MAGIC 0x49434653 -/// IPC output header magic -#define SFCO_MAGIC 0x4f434653 - -/// IPC invalid object ID -#define IPC_INVALID_OBJECT_ID UINT32_MAX - -///@name IPC request building -///@{ - -/// IPC command (request) structure. -#define IPC_MAX_BUFFERS 8 -#define IPC_MAX_OBJECTS 8 - -typedef enum { - BufferType_Normal=0, ///< Regular buffer. - BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory. - BufferType_Invalid=2, - BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping. -} BufferType; - -typedef enum { - BufferDirection_Send=0, - BufferDirection_Recv=1, - BufferDirection_Exch=2, -} BufferDirection; - -typedef enum { - IpcCommandType_Invalid = 0, - IpcCommandType_LegacyRequest = 1, - IpcCommandType_Close = 2, - IpcCommandType_LegacyControl = 3, - IpcCommandType_Request = 4, - IpcCommandType_Control = 5, - IpcCommandType_RequestWithContext = 6, - IpcCommandType_ControlWithContext = 7, -} IpcCommandType; - -typedef enum { - DomainMessageType_Invalid = 0, - DomainMessageType_SendMessage = 1, - DomainMessageType_Close = 2, -} DomainMessageType; - -/// IPC domain message header. -typedef struct { - u8 Type; - u8 NumObjectIds; - u16 Length; - u32 ThisObjectId; - u32 Pad[2]; -} DomainMessageHeader; - -typedef struct { - size_t NumSend; // A - size_t NumRecv; // B - size_t NumExch; // W - const void* Buffers[IPC_MAX_BUFFERS]; - size_t BufferSizes[IPC_MAX_BUFFERS]; - BufferType BufferTypes[IPC_MAX_BUFFERS]; - - size_t NumStaticIn; // X - size_t NumStaticOut; // C - const void* Statics[IPC_MAX_BUFFERS]; - size_t StaticSizes[IPC_MAX_BUFFERS]; - u8 StaticIndices[IPC_MAX_BUFFERS]; - - bool SendPid; - size_t NumHandlesCopy; - size_t NumHandlesMove; - Handle Handles[IPC_MAX_OBJECTS]; - - size_t NumObjectIds; - u32 ObjectIds[IPC_MAX_OBJECTS]; -} IpcCommand; - -/** - * @brief Initializes an IPC command structure. - * @param cmd IPC command structure. - */ -static inline void ipcInitialize(IpcCommand* cmd);//{ -// *cmd = (IpcCommand){0}; -//} - -/// IPC buffer descriptor. -typedef struct { - u32 Size; ///< Size of the buffer. - u32 Addr; ///< Lower 32-bits of the address of the buffer - u32 Packed; ///< Packed data (including higher bits of the address) -} IpcBufferDescriptor; - -/// IPC static send-buffer descriptor. -typedef struct { - u32 Packed; ///< Packed data (including higher bits of the address) - u32 Addr; ///< Lower 32-bits of the address -} IpcStaticSendDescriptor; - -/// IPC static receive-buffer descriptor. -typedef struct { - u32 Addr; ///< Lower 32-bits of the address of the buffer - u32 Packed; ///< Packed data (including higher bits of the address) -} IpcStaticRecvDescriptor; - -/** - * @brief Adds a buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type);//{ -// size_t off = cmd->NumSend; -// cmd->Buffers[off] = buffer; -// cmd->BufferSizes[off] = size; -// cmd->BufferTypes[off] = type; -// cmd->NumSend++; -//} - -/** - * @brief Adds a receive-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type);//{ -// size_t off = cmd->NumSend + cmd->NumRecv; -// cmd->Buffers[off] = buffer; -// cmd->BufferSizes[off] = size; -// cmd->BufferTypes[off] = type; -// cmd->NumRecv++; -//} - -/** - * @brief Adds an exchange-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type);//{ -// size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch; -// cmd->Buffers[off] = buffer; -// cmd->BufferSizes[off] = size; -// cmd->BufferTypes[off] = type; -// cmd->NumExch++; -//} - -/** - * @brief Adds a static-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index);//{ -// size_t off = cmd->NumStaticIn; -// cmd->Statics[off] = buffer; -// cmd->StaticSizes[off] = size; -// cmd->StaticIndices[off] = index; -// cmd->NumStaticIn++; -//} - -/** - * @brief Adds a static-receive-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index);//{ -// size_t off = cmd->NumStaticIn + cmd->NumStaticOut; -// cmd->Statics[off] = buffer; -// cmd->StaticSizes[off] = size; -// cmd->StaticIndices[off] = index; -// cmd->NumStaticOut++; -//} - -/** - * @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure. - * @param cmd IPC command structure. - * @param ipc_buffer_size IPC buffer size. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, const void* buffer, size_t size, u8 index);//{ -// if (ipc_buffer_size != 0 && size <= ipc_buffer_size) { -// ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal); -// ipcAddSendStatic(cmd, buffer, size, index); -// } else { -// ipcAddSendBuffer(cmd, buffer, size, BufferType_Normal); -// ipcAddSendStatic(cmd, NULL, 0, index); -// } -//} - -/** - * @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure. - * @param cmd IPC command structure. - * @param ipc_buffer_size IPC buffer size. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t ipc_buffer_size, void* buffer, size_t size, u8 index);//{ -// if (ipc_buffer_size != 0 && size <= ipc_buffer_size) { -// ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal); -// ipcAddRecvStatic(cmd, buffer, size, index); -// } else { -// ipcAddRecvBuffer(cmd, buffer, size, BufferType_Normal); -// ipcAddRecvStatic(cmd, NULL, 0, index); -// } -//} - -/** - * @brief Tags an IPC command structure to send the PID. - * @param cmd IPC command structure. - */ -static inline void ipcSendPid(IpcCommand* cmd);//{ -// cmd->SendPid = true; -//} - -/** - * @brief Adds a copy-handle to be sent through an IPC command structure. - * @param cmd IPC command structure. - * @param h Handle to send. - * @remark The receiving process gets a copy of the handle. - */ -static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h);//{ -// cmd->Handles[cmd->NumHandlesCopy++] = h; -//} - -/** - * @brief Adds a move-handle to be sent through an IPC command structure. - * @param cmd IPC command structure. - * @param h Handle to send. - * @remark The sending process loses ownership of the handle, which is transferred to the receiving process. - */ -static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h);//{ -// cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h; -//} - -/** - * @brief Prepares the header of an IPC command structure. - * @param cmd IPC command structure. - * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request - * @return Pointer to the raw embedded data structure in the request, ready to be filled out. - */ -static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw);//{ -// u32* buf = (u32*)armGetTls(); -// size_t i; -// *buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28); -// -// u32* fill_in_size_later = buf; -// -// if (cmd->NumStaticOut > 0) { -// *buf = (cmd->NumStaticOut + 2) << 10; -// } -// else { -// *buf = 0; -// } -// -// if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) { -// *buf++ |= 0x80000000; -// *buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5); -// -// if (cmd->SendPid) -// buf += 2; -// -// for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++) -// *buf++ = cmd->Handles[i]; -// } -// else { -// buf++; -// } -// -// for (i=0; iNumStaticIn; i++, buf+=2) { -// IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf; -// -// uintptr_t ptr = (uintptr_t) cmd->Statics[i]; -// desc->Addr = ptr; -// desc->Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) | -// (((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6); -// } -// -// for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) { -// IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf; -// desc->Size = cmd->BufferSizes[i]; -// -// uintptr_t ptr = (uintptr_t) cmd->Buffers[i]; -// desc->Addr = ptr; -// desc->Packed = cmd->BufferTypes[i] | -// (((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2); -// } -// -// u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4; -// u32* raw = (u32*) (buf + padding); -// -// size_t raw_size = (sizeof_raw/4) + 4; -// buf += raw_size; -// -// u16* buf_u16 = (u16*) buf; -// -// for (i=0; iNumStaticOut; i++) { -// size_t off = cmd->NumStaticIn + i; -// size_t sz = (uintptr_t) cmd->StaticSizes[off]; -// -// buf_u16[i] = (sz > 0xFFFF) ? 0 : sz; -// } -// -// size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4; -// buf += u16s_size; -// raw_size += u16s_size; -// -// *fill_in_size_later |= raw_size; -// -// for (i=0; iNumStaticOut; i++, buf+=2) { -// IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf; -// size_t off = cmd->NumStaticIn + i; -// -// uintptr_t ptr = (uintptr_t) cmd->Statics[off]; -// desc->Addr = ptr; -// desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16); -// } -// -// return (void*) raw; -//} - -/** - * @brief Dispatches an IPC request. - * @param session IPC session handle. - * @return Result code. - */ -static inline Result ipcDispatch(Handle session);//{ -// return svcSendSyncRequest(session); -//} - -///@} - -///@name IPC response parsing -///@{ - -/// IPC parsed command (response) structure. -typedef struct { - IpcCommandType CommandType; ///< Type of the command - - bool HasPid; ///< true if the 'Pid' field is filled out. - u64 Pid; ///< PID included in the response (only if HasPid is true) - - size_t NumHandles; ///< Number of handles copied. - Handle Handles[IPC_MAX_OBJECTS]; ///< Handles. - bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied. - - bool IsDomainMessage; ///< true if the the message is a Domain message. - DomainMessageType MessageType; ///< Type of the domain message. - u32 MessageLength; ///< Size of rawdata (for domain messages). - u32 ThisObjectId; ///< Object ID to call the command on (for domain messages). - size_t NumObjectIds; ///< Number of object IDs (for domain messages). - u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages). - - size_t NumBuffers; ///< Number of buffers in the response. - void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers. - size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers. - BufferType BufferTypes[IPC_MAX_BUFFERS]; ///< Types of the buffers. - BufferDirection BufferDirections[IPC_MAX_BUFFERS]; ///< Direction of each buffer. - - size_t NumStatics; ///< Number of statics in the response. - void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics. - size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics. - u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics. - - size_t NumStaticsOut; ///< Number of output statics available in the response. - - void* Raw; ///< Pointer to the raw embedded data structure in the response. - void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding. - size_t RawSize; ///< Size of the raw embedded data. -} IpcParsedCommand; - -/** - * @brief Parse an IPC command response into an IPC parsed command structure. - * @param IPC parsed command structure to fill in. - * @return Result code. - */ -static inline Result ipcParse(IpcParsedCommand* r);//{ -// u32* buf = (u32*)armGetTls(); -// u32 ctrl0 = *buf++; -// u32 ctrl1 = *buf++; -// size_t i; -// -// r->IsDomainMessage = false; -// -// r->CommandType = (IpcCommandType) (ctrl0 & 0xffff); -// r->HasPid = false; -// r->RawSize = (ctrl1 & 0x1ff) * 4; -// r->NumHandles = 0; -// -// r->NumStaticsOut = (ctrl1 >> 10) & 15; -// if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor -// if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors -// -// if (ctrl1 & 0x80000000) { -// u32 ctrl2 = *buf++; -// -// if (ctrl2 & 1) { -// r->HasPid = true; -// r->Pid = *buf++; -// r->Pid |= ((u64)(*buf++)) << 32; -// } -// -// size_t num_handles_copy = ((ctrl2 >> 1) & 15); -// size_t num_handles_move = ((ctrl2 >> 5) & 15); -// -// size_t num_handles = num_handles_copy + num_handles_move; -// u32* buf_after_handles = buf + num_handles; -// -// if (num_handles > IPC_MAX_OBJECTS) -// num_handles = IPC_MAX_OBJECTS; -// -// for (i=0; iHandles[i] = *(buf+i); -// r->WasHandleCopied[i] = (i < num_handles_copy); -// } -// -// r->NumHandles = num_handles; -// buf = buf_after_handles; -// } -// -// size_t num_statics = (ctrl0 >> 16) & 15; -// u32* buf_after_statics = buf + num_statics*2; -// -// if (num_statics > IPC_MAX_BUFFERS) -// num_statics = IPC_MAX_BUFFERS; -// -// for (i=0; iPacked; -// -// r->Statics[i] = (void*) (desc->Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36)); -// r->StaticSizes[i] = packed >> 16; -// r->StaticIndices[i] = packed & 63; -// } -// -// r->NumStatics = num_statics; -// buf = buf_after_statics; -// -// size_t num_bufs_send = (ctrl0 >> 20) & 15; -// size_t num_bufs_recv = (ctrl0 >> 24) & 15; -// size_t num_bufs_exch = (ctrl0 >> 28) & 15; -// -// size_t num_bufs = num_bufs_send + num_bufs_recv + num_bufs_exch; -// r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15); -// r->RawWithoutPadding = (void*)((uintptr_t)(buf + num_bufs*3)); -// -// if (num_bufs > IPC_MAX_BUFFERS) -// num_bufs = IPC_MAX_BUFFERS; -// -// for (i=0; iPacked; -// -// r->Buffers[i] = (void*) (desc->Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36)); -// r->BufferSizes[i] = desc->Size; -// r->BufferTypes[i] = (BufferType) (packed & 3); -// -// if (i < num_bufs_send) -// r->BufferDirections[i] = BufferDirection_Send; -// else if (i < (num_bufs_send + num_bufs_recv)) -// r->BufferDirections[i] = BufferDirection_Recv; -// else -// r->BufferDirections[i] = BufferDirection_Exch; -// } -// -// r->NumBuffers = num_bufs; -// return 0; -//} - -/** - * @brief Queries the size of an IPC pointer buffer. - * @param session IPC session handle. - * @param size Output variable in which to store the size. - * @return Result code. - */ -static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size);//{ -// u32* buf = (u32*)armGetTls(); -// -// buf[0] = IpcCommandType_Control; -// buf[1] = 8; -// buf[2] = 0; -// buf[3] = 0; -// buf[4] = SFCI_MAGIC; -// buf[5] = 0; -// buf[6] = 3; -// buf[7] = 0; -// -// Result rc = ipcDispatch(session); -// -// if (R_SUCCEEDED(rc)) { -// IpcParsedCommand r; -// ipcParse(&r); -// -// struct ipcQueryPointerBufferSizeResponse { -// u64 magic; -// u64 result; -// u32 size; -// } *raw = (struct ipcQueryPointerBufferSizeResponse*)r.Raw; -// -// rc = raw->result; -// -// if (R_SUCCEEDED(rc)) { -// *size = raw->size & 0xffff; -// } -// } -// -// return rc; -//} - -/** - * @brief Closes the IPC session with proper clean up. - * @param session IPC session handle. - * @return Result code. - */ -static inline Result ipcCloseSession(Handle session);//{ -// u32* buf = (u32*)armGetTls(); -// buf[0] = IpcCommandType_Close; -// buf[1] = 0; -// return ipcDispatch(session); -//} -///@} - -///@name IPC domain handling -///@{ - -/** - * @brief Converts an IPC session handle into a domain. - * @param session IPC session handle. - * @param object_id_out Output variable in which to store the object ID. - * @return Result code. - */ -static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out);//{ -// u32* buf = (u32*)armGetTls(); -// -// buf[0] = IpcCommandType_Control; -// buf[1] = 8; -// buf[4] = SFCI_MAGIC; -// buf[5] = 0; -// buf[6] = 0; -// buf[7] = 0; -// -// Result rc = ipcDispatch(session); -// -// if (R_SUCCEEDED(rc)) { -// IpcParsedCommand r; -// ipcParse(&r); -// -// struct ipcConvertSessionToDomainResponse { -// u64 magic; -// u64 result; -// u32 object_id; -// } *raw = (struct ipcConvertSessionToDomainResponse*)r.Raw; -// -// rc = raw->result; -// -// if (R_SUCCEEDED(rc)) { -// *object_id_out = raw->object_id; -// } -// } -// -// return rc; -//} - -/** - * @brief Adds an object ID to be sent through an IPC domain command structure. - * @param cmd IPC domain command structure. - * @param object_id Object ID to send. - */ -static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id);//{ -// cmd->ObjectIds[cmd->NumObjectIds++] = object_id; -//} - -/** - * @brief Prepares the header of an IPC command structure (domain version). - * @param cmd IPC command structure. - * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request - * @oaram object_id Domain object ID. - * @return Pointer to the raw embedded data structure in the request, ready to be filled out. - */ -static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id);//{ -// void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader)); -// DomainMessageHeader* hdr = (DomainMessageHeader*) raw; -// u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw); -// -// hdr->Type = DomainMessageType_SendMessage; -// hdr->NumObjectIds = (u8)cmd->NumObjectIds; -// hdr->Length = sizeof_raw; -// hdr->ThisObjectId = object_id; -// hdr->Pad[0] = hdr->Pad[1] = 0; -// -// for(size_t i = 0; i < cmd->NumObjectIds; i++) -// object_ids[i] = cmd->ObjectIds[i]; -// return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader)); -//} - -/** - * @brief Parse an IPC command response into an IPC parsed command structure (domain version). - * @param IPC parsed command structure to fill in. - * @return Result code. - */ -static inline Result ipcParseForDomain(IpcParsedCommand* r);//{ -// Result rc = ipcParse(r); -// DomainMessageHeader *hdr; -// u32 *object_ids; -// if(R_FAILED(rc)) -// return rc; -// -// hdr = (DomainMessageHeader*) r->Raw; -// object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length); -// r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader)); -// -// r->IsDomainMessage = true; -// r->MessageType = (DomainMessageType)(hdr->Type); -// switch (r->MessageType) { -// case DomainMessageType_SendMessage: -// case DomainMessageType_Close: -// break; -// default: -// return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType); -// } -// r->ThisObjectId = hdr->ThisObjectId; -// r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds; -// if ((uintptr_t)object_ids + sizeof(u32) * r->NumObjectIds - (uintptr_t)armGetTls() >= 0x100) { -// return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds); -// } -// for(size_t i = 0; i < r->NumObjectIds; i++) -// r->ObjectIds[i] = object_ids[i]; -// -// return rc; -//} - -/** - * @brief Closes a domain object by ID. - * @param session IPC session handle. - * @param object_id ID of the object to close. - * @return Result code. - */ -static inline Result ipcCloseObjectById(Handle session, u32 object_id);//{ -// IpcCommand c; -// DomainMessageHeader* hdr; -// -// ipcInitialize(&c); -// hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader)); -// -// hdr->Type = 2; -// hdr->NumObjectIds = 0; -// hdr->Length = 0; -// hdr->ThisObjectId = object_id; -// hdr->Pad[0] = hdr->Pad[1] = 0; -// -// return ipcDispatch(session); // this command has no associated response -//} - -///@} - diff --git a/tests/unittests/data/teststaticexpectednewlinebraces.h b/tests/unittests/data/teststaticexpectednewlinebraces.h deleted file mode 100644 index 3f90ab6..0000000 --- a/tests/unittests/data/teststaticexpectednewlinebraces.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file condvar.h - * @brief Condition variable synchronization primitive. - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../types.h" -#include "../kernel/mutex.h" - -/// Condition variable structure. -typedef struct { - u32 tag; - Mutex* mutex; -} CondVar; - -/** - * @brief Initializes a condition variable. - * @param[in] c Condition variable object. - * @param[in] m Mutex object to use inside the condition variable. - */ -void condvarInit(CondVar* c, Mutex* m); - -/** - * @brief Waits on a condition variable with a timeout. - * @param[in] c Condition variable object. - * @param[in] timeout Timeout in nanoseconds. - * @return Result code (0xEA01 on timeout). - * @remark On function return, the underlying mutex is acquired. - */ -Result condvarWaitTimeout(CondVar* c, u64 timeout); - -/** - * @brief Waits on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - * @remark On function return, the underlying mutex is acquired. - */ -static inline Result condvarWait(CondVar* c);//{ -// return condvarWaitTimeout(c, -1ull); -//} - -/** - * @brief Wakes up up to the specified number of threads waiting on a condition variable. - * @param[in] c Condition variable object. - * @param[in] num Maximum number of threads to wake up (or -1 to wake them all up). - * @return Result code. - */ -Result condvarWake(CondVar* c, int num); - -/** - * @brief Wakes up a single thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeOne(CondVar* c);//{ -// return condvarWake(c, 1); -//} - -/** - * @brief Wakes up all thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeAll(CondVar* c);//{ -// return condvarWake(c, -1); -//} - diff --git a/tests/unittests/data/teststaticfrontbraces.h b/tests/unittests/data/teststaticfrontbraces.h deleted file mode 100644 index d62f694..0000000 --- a/tests/unittests/data/teststaticfrontbraces.h +++ /dev/null @@ -1,675 +0,0 @@ -/** - * @file ipc.h - * @brief Inter-process communication handling - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../result.h" -#include "../arm/tls.h" -#include "../kernel/svc.h" - -/// IPC input header magic -#define SFCI_MAGIC 0x49434653 -/// IPC output header magic -#define SFCO_MAGIC 0x4f434653 - -/// IPC invalid object ID -#define IPC_INVALID_OBJECT_ID UINT32_MAX - -///@name IPC request building -///@{ - -/// IPC command (request) structure. -#define IPC_MAX_BUFFERS 8 -#define IPC_MAX_OBJECTS 8 - -typedef enum { - BufferType_Normal=0, ///< Regular buffer. - BufferType_Type1=1, ///< Allows ProcessMemory and shared TransferMemory. - BufferType_Invalid=2, - BufferType_Type3=3 ///< Same as Type1 except remote process is not allowed to use device-mapping. -} BufferType; - -typedef enum { - BufferDirection_Send=0, - BufferDirection_Recv=1, - BufferDirection_Exch=2, -} BufferDirection; - -typedef enum { - IpcCommandType_Invalid = 0, - IpcCommandType_LegacyRequest = 1, - IpcCommandType_Close = 2, - IpcCommandType_LegacyControl = 3, - IpcCommandType_Request = 4, - IpcCommandType_Control = 5, - IpcCommandType_RequestWithContext = 6, - IpcCommandType_ControlWithContext = 7, -} IpcCommandType; - -typedef enum { - DomainMessageType_Invalid = 0, - DomainMessageType_SendMessage = 1, - DomainMessageType_Close = 2, -} DomainMessageType; - -/// IPC domain message header. -typedef struct { - u8 Type; - u8 NumObjectIds; - u16 Length; - u32 ThisObjectId; - u32 Pad[2]; -} DomainMessageHeader; - -typedef struct { - size_t NumSend; // A - size_t NumRecv; // B - size_t NumExch; // W - const void* Buffers[IPC_MAX_BUFFERS]; - size_t BufferSizes[IPC_MAX_BUFFERS]; - BufferType BufferTypes[IPC_MAX_BUFFERS]; - - size_t NumStaticIn; // X - size_t NumStaticOut; // C - const void* Statics[IPC_MAX_BUFFERS]; - size_t StaticSizes[IPC_MAX_BUFFERS]; - u8 StaticIndices[IPC_MAX_BUFFERS]; - - bool SendPid; - size_t NumHandlesCopy; - size_t NumHandlesMove; - Handle Handles[IPC_MAX_OBJECTS]; - - size_t NumObjectIds; - u32 ObjectIds[IPC_MAX_OBJECTS]; -} IpcCommand; - -/** - * @brief Initializes an IPC command structure. - * @param cmd IPC command structure. - */ -static inline void ipcInitialize(IpcCommand* cmd) { - *cmd = (IpcCommand){0}; -} - -/// IPC buffer descriptor. -typedef struct { - u32 Size; ///< Size of the buffer. - u32 Addr; ///< Lower 32-bits of the address of the buffer - u32 Packed; ///< Packed data (including higher bits of the address) -} IpcBufferDescriptor; - -/// IPC static send-buffer descriptor. -typedef struct { - u32 Packed; ///< Packed data (including higher bits of the address) - u32 Addr; ///< Lower 32-bits of the address -} IpcStaticSendDescriptor; - -/// IPC static receive-buffer descriptor. -typedef struct { - u32 Addr; ///< Lower 32-bits of the address of the buffer - u32 Packed; ///< Packed data (including higher bits of the address) -} IpcStaticRecvDescriptor; - -/** - * @brief Adds a buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddSendBuffer(IpcCommand* cmd, const void* buffer, size_t size, BufferType type) { - size_t off = cmd->NumSend; - cmd->Buffers[off] = buffer; - cmd->BufferSizes[off] = size; - cmd->BufferTypes[off] = type; - cmd->NumSend++; -} - -/** - * @brief Adds a receive-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddRecvBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) { - size_t off = cmd->NumSend + cmd->NumRecv; - cmd->Buffers[off] = buffer; - cmd->BufferSizes[off] = size; - cmd->BufferTypes[off] = type; - cmd->NumRecv++; -} - -/** - * @brief Adds an exchange-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param type Buffer type. - */ -static inline void ipcAddExchBuffer(IpcCommand* cmd, void* buffer, size_t size, BufferType type) { - size_t off = cmd->NumSend + cmd->NumRecv + cmd->NumExch; - cmd->Buffers[off] = buffer; - cmd->BufferSizes[off] = size; - cmd->BufferTypes[off] = type; - cmd->NumExch++; -} - -/** - * @brief Adds a static-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddSendStatic(IpcCommand* cmd, const void* buffer, size_t size, u8 index) { - size_t off = cmd->NumStaticIn; - cmd->Statics[off] = buffer; - cmd->StaticSizes[off] = size; - cmd->StaticIndices[off] = index; - cmd->NumStaticIn++; -} - -/** - * @brief Adds a static-receive-buffer to an IPC command structure. - * @param cmd IPC command structure. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddRecvStatic(IpcCommand* cmd, void* buffer, size_t size, u8 index) { - size_t off = cmd->NumStaticIn + cmd->NumStaticOut; - cmd->Statics[off] = buffer; - cmd->StaticSizes[off] = size; - cmd->StaticIndices[off] = index; - cmd->NumStaticOut++; -} - -/** - * @brief Adds a smart-buffer (buffer + static-buffer pair) to an IPC command structure. - * @param cmd IPC command structure. - * @param ipc_buffer_size IPC buffer size. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddSendSmart(IpcCommand* cmd, size_t ipc_buffer_size, const void* buffer, size_t size, u8 index) { - if (ipc_buffer_size != 0 && size <= ipc_buffer_size) { - ipcAddSendBuffer(cmd, NULL, 0, BufferType_Normal); - ipcAddSendStatic(cmd, buffer, size, index); - } else { - ipcAddSendBuffer(cmd, buffer, size, BufferType_Normal); - ipcAddSendStatic(cmd, NULL, 0, index); - } -} - -/** - * @brief Adds a smart-receive-buffer (buffer + static-receive-buffer pair) to an IPC command structure. - * @param cmd IPC command structure. - * @param ipc_buffer_size IPC buffer size. - * @param buffer Address of the buffer. - * @param size Size of the buffer. - * @param index Index of buffer. - */ -static inline void ipcAddRecvSmart(IpcCommand* cmd, size_t ipc_buffer_size, void* buffer, size_t size, u8 index) { - if (ipc_buffer_size != 0 && size <= ipc_buffer_size) { - ipcAddRecvBuffer(cmd, NULL, 0, BufferType_Normal); - ipcAddRecvStatic(cmd, buffer, size, index); - } else { - ipcAddRecvBuffer(cmd, buffer, size, BufferType_Normal); - ipcAddRecvStatic(cmd, NULL, 0, index); - } -} - -/** - * @brief Tags an IPC command structure to send the PID. - * @param cmd IPC command structure. - */ -static inline void ipcSendPid(IpcCommand* cmd) { - cmd->SendPid = true; -} - -/** - * @brief Adds a copy-handle to be sent through an IPC command structure. - * @param cmd IPC command structure. - * @param h Handle to send. - * @remark The receiving process gets a copy of the handle. - */ -static inline void ipcSendHandleCopy(IpcCommand* cmd, Handle h) { - cmd->Handles[cmd->NumHandlesCopy++] = h; -} - -/** - * @brief Adds a move-handle to be sent through an IPC command structure. - * @param cmd IPC command structure. - * @param h Handle to send. - * @remark The sending process loses ownership of the handle, which is transferred to the receiving process. - */ -static inline void ipcSendHandleMove(IpcCommand* cmd, Handle h) { - cmd->Handles[cmd->NumHandlesCopy + cmd->NumHandlesMove++] = h; -} - -/** - * @brief Prepares the header of an IPC command structure. - * @param cmd IPC command structure. - * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request - * @return Pointer to the raw embedded data structure in the request, ready to be filled out. - */ -static inline void* ipcPrepareHeader(IpcCommand* cmd, size_t sizeof_raw) { - u32* buf = (u32*)armGetTls(); - size_t i; - *buf++ = IpcCommandType_Request | (cmd->NumStaticIn << 16) | (cmd->NumSend << 20) | (cmd->NumRecv << 24) | (cmd->NumExch << 28); - - u32* fill_in_size_later = buf; - - if (cmd->NumStaticOut > 0) { - *buf = (cmd->NumStaticOut + 2) << 10; - } - else { - *buf = 0; - } - - if (cmd->SendPid || cmd->NumHandlesCopy > 0 || cmd->NumHandlesMove > 0) { - *buf++ |= 0x80000000; - *buf++ = (!!cmd->SendPid) | (cmd->NumHandlesCopy << 1) | (cmd->NumHandlesMove << 5); - - if (cmd->SendPid) - buf += 2; - - for (i=0; i<(cmd->NumHandlesCopy + cmd->NumHandlesMove); i++) - *buf++ = cmd->Handles[i]; - } - else { - buf++; - } - - for (i=0; iNumStaticIn; i++, buf+=2) { - IpcStaticSendDescriptor* desc = (IpcStaticSendDescriptor*) buf; - - uintptr_t ptr = (uintptr_t) cmd->Statics[i]; - desc->Addr = ptr; - desc->Packed = cmd->StaticIndices[i] | (cmd->StaticSizes[i] << 16) | - (((ptr >> 32) & 15) << 12) | (((ptr >> 36) & 15) << 6); - } - - for (i=0; i<(cmd->NumSend + cmd->NumRecv + cmd->NumExch); i++, buf+=3) { - IpcBufferDescriptor* desc = (IpcBufferDescriptor*) buf; - desc->Size = cmd->BufferSizes[i]; - - uintptr_t ptr = (uintptr_t) cmd->Buffers[i]; - desc->Addr = ptr; - desc->Packed = cmd->BufferTypes[i] | - (((ptr >> 32) & 15) << 28) | ((ptr >> 36) << 2); - } - - u32 padding = ((16 - (((uintptr_t) buf) & 15)) & 15) / 4; - u32* raw = (u32*) (buf + padding); - - size_t raw_size = (sizeof_raw/4) + 4; - buf += raw_size; - - u16* buf_u16 = (u16*) buf; - - for (i=0; iNumStaticOut; i++) { - size_t off = cmd->NumStaticIn + i; - size_t sz = (uintptr_t) cmd->StaticSizes[off]; - - buf_u16[i] = (sz > 0xFFFF) ? 0 : sz; - } - - size_t u16s_size = ((2*cmd->NumStaticOut) + 3)/4; - buf += u16s_size; - raw_size += u16s_size; - - *fill_in_size_later |= raw_size; - - for (i=0; iNumStaticOut; i++, buf+=2) { - IpcStaticRecvDescriptor* desc = (IpcStaticRecvDescriptor*) buf; - size_t off = cmd->NumStaticIn + i; - - uintptr_t ptr = (uintptr_t) cmd->Statics[off]; - desc->Addr = ptr; - desc->Packed = (ptr >> 32) | (cmd->StaticSizes[off] << 16); - } - - return (void*) raw; -} - -/** - * @brief Dispatches an IPC request. - * @param session IPC session handle. - * @return Result code. - */ -static inline Result ipcDispatch(Handle session) { - return svcSendSyncRequest(session); -} - -///@} - -///@name IPC response parsing -///@{ - -/// IPC parsed command (response) structure. -typedef struct { - IpcCommandType CommandType; ///< Type of the command - - bool HasPid; ///< true if the 'Pid' field is filled out. - u64 Pid; ///< PID included in the response (only if HasPid is true) - - size_t NumHandles; ///< Number of handles copied. - Handle Handles[IPC_MAX_OBJECTS]; ///< Handles. - bool WasHandleCopied[IPC_MAX_OBJECTS]; ///< true if the handle was moved, false if it was copied. - - bool IsDomainMessage; ///< true if the the message is a Domain message. - DomainMessageType MessageType; ///< Type of the domain message. - u32 MessageLength; ///< Size of rawdata (for domain messages). - u32 ThisObjectId; ///< Object ID to call the command on (for domain messages). - size_t NumObjectIds; ///< Number of object IDs (for domain messages). - u32 ObjectIds[IPC_MAX_OBJECTS]; ///< Object IDs (for domain messages). - - size_t NumBuffers; ///< Number of buffers in the response. - void* Buffers[IPC_MAX_BUFFERS]; ///< Pointers to the buffers. - size_t BufferSizes[IPC_MAX_BUFFERS]; ///< Sizes of the buffers. - BufferType BufferTypes[IPC_MAX_BUFFERS]; ///< Types of the buffers. - BufferDirection BufferDirections[IPC_MAX_BUFFERS]; ///< Direction of each buffer. - - size_t NumStatics; ///< Number of statics in the response. - void* Statics[IPC_MAX_BUFFERS]; ///< Pointers to the statics. - size_t StaticSizes[IPC_MAX_BUFFERS]; ///< Sizes of the statics. - u8 StaticIndices[IPC_MAX_BUFFERS]; ///< Indices of the statics. - - size_t NumStaticsOut; ///< Number of output statics available in the response. - - void* Raw; ///< Pointer to the raw embedded data structure in the response. - void* RawWithoutPadding; ///< Pointer to the raw embedded data structure, without padding. - size_t RawSize; ///< Size of the raw embedded data. -} IpcParsedCommand; - -/** - * @brief Parse an IPC command response into an IPC parsed command structure. - * @param IPC parsed command structure to fill in. - * @return Result code. - */ -static inline Result ipcParse(IpcParsedCommand* r) { - u32* buf = (u32*)armGetTls(); - u32 ctrl0 = *buf++; - u32 ctrl1 = *buf++; - size_t i; - - r->IsDomainMessage = false; - - r->CommandType = (IpcCommandType) (ctrl0 & 0xffff); - r->HasPid = false; - r->RawSize = (ctrl1 & 0x1ff) * 4; - r->NumHandles = 0; - - r->NumStaticsOut = (ctrl1 >> 10) & 15; - if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 2 -> Single descriptor - if (r->NumStaticsOut >> 1) r->NumStaticsOut--; // Value 3+ -> (Value - 2) descriptors - - if (ctrl1 & 0x80000000) { - u32 ctrl2 = *buf++; - - if (ctrl2 & 1) { - r->HasPid = true; - r->Pid = *buf++; - r->Pid |= ((u64)(*buf++)) << 32; - } - - size_t num_handles_copy = ((ctrl2 >> 1) & 15); - size_t num_handles_move = ((ctrl2 >> 5) & 15); - - size_t num_handles = num_handles_copy + num_handles_move; - u32* buf_after_handles = buf + num_handles; - - if (num_handles > IPC_MAX_OBJECTS) - num_handles = IPC_MAX_OBJECTS; - - for (i=0; iHandles[i] = *(buf+i); - r->WasHandleCopied[i] = (i < num_handles_copy); - } - - r->NumHandles = num_handles; - buf = buf_after_handles; - } - - size_t num_statics = (ctrl0 >> 16) & 15; - u32* buf_after_statics = buf + num_statics*2; - - if (num_statics > IPC_MAX_BUFFERS) - num_statics = IPC_MAX_BUFFERS; - - for (i=0; iPacked; - - r->Statics[i] = (void*) (desc->Addr | (((packed >> 12) & 15) << 32) | (((packed >> 6) & 15) << 36)); - r->StaticSizes[i] = packed >> 16; - r->StaticIndices[i] = packed & 63; - } - - r->NumStatics = num_statics; - buf = buf_after_statics; - - size_t num_bufs_send = (ctrl0 >> 20) & 15; - size_t num_bufs_recv = (ctrl0 >> 24) & 15; - size_t num_bufs_exch = (ctrl0 >> 28) & 15; - - size_t num_bufs = num_bufs_send + num_bufs_recv + num_bufs_exch; - r->Raw = (void*)(((uintptr_t)(buf + num_bufs*3) + 15) &~ 15); - r->RawWithoutPadding = (void*)((uintptr_t)(buf + num_bufs*3)); - - if (num_bufs > IPC_MAX_BUFFERS) - num_bufs = IPC_MAX_BUFFERS; - - for (i=0; iPacked; - - r->Buffers[i] = (void*) (desc->Addr | ((packed >> 28) << 32) | (((packed >> 2) & 15) << 36)); - r->BufferSizes[i] = desc->Size; - r->BufferTypes[i] = (BufferType) (packed & 3); - - if (i < num_bufs_send) - r->BufferDirections[i] = BufferDirection_Send; - else if (i < (num_bufs_send + num_bufs_recv)) - r->BufferDirections[i] = BufferDirection_Recv; - else - r->BufferDirections[i] = BufferDirection_Exch; - } - - r->NumBuffers = num_bufs; - return 0; -} - -/** - * @brief Queries the size of an IPC pointer buffer. - * @param session IPC session handle. - * @param size Output variable in which to store the size. - * @return Result code. - */ -static inline Result ipcQueryPointerBufferSize(Handle session, size_t *size) { - u32* buf = (u32*)armGetTls(); - - buf[0] = IpcCommandType_Control; - buf[1] = 8; - buf[2] = 0; - buf[3] = 0; - buf[4] = SFCI_MAGIC; - buf[5] = 0; - buf[6] = 3; - buf[7] = 0; - - Result rc = ipcDispatch(session); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct ipcQueryPointerBufferSizeResponse { - u64 magic; - u64 result; - u32 size; - } *raw = (struct ipcQueryPointerBufferSizeResponse*)r.Raw; - - rc = raw->result; - - if (R_SUCCEEDED(rc)) { - *size = raw->size & 0xffff; - } - } - - return rc; -} - -/** - * @brief Closes the IPC session with proper clean up. - * @param session IPC session handle. - * @return Result code. - */ -static inline Result ipcCloseSession(Handle session) { - u32* buf = (u32*)armGetTls(); - buf[0] = IpcCommandType_Close; - buf[1] = 0; - return ipcDispatch(session); -} -///@} - -///@name IPC domain handling -///@{ - -/** - * @brief Converts an IPC session handle into a domain. - * @param session IPC session handle. - * @param object_id_out Output variable in which to store the object ID. - * @return Result code. - */ -static inline Result ipcConvertSessionToDomain(Handle session, u32* object_id_out) { - u32* buf = (u32*)armGetTls(); - - buf[0] = IpcCommandType_Control; - buf[1] = 8; - buf[4] = SFCI_MAGIC; - buf[5] = 0; - buf[6] = 0; - buf[7] = 0; - - Result rc = ipcDispatch(session); - - if (R_SUCCEEDED(rc)) { - IpcParsedCommand r; - ipcParse(&r); - - struct ipcConvertSessionToDomainResponse { - u64 magic; - u64 result; - u32 object_id; - } *raw = (struct ipcConvertSessionToDomainResponse*)r.Raw; - - rc = raw->result; - - if (R_SUCCEEDED(rc)) { - *object_id_out = raw->object_id; - } - } - - return rc; -} - -/** - * @brief Adds an object ID to be sent through an IPC domain command structure. - * @param cmd IPC domain command structure. - * @param object_id Object ID to send. - */ -static inline void ipcSendObjectId(IpcCommand* cmd, u32 object_id) { - cmd->ObjectIds[cmd->NumObjectIds++] = object_id; -} - -/** - * @brief Prepares the header of an IPC command structure (domain version). - * @param cmd IPC command structure. - * @param sizeof_raw Size in bytes of the raw data structure to embed inside the IPC request - * @oaram object_id Domain object ID. - * @return Pointer to the raw embedded data structure in the request, ready to be filled out. - */ -static inline void* ipcPrepareHeaderForDomain(IpcCommand* cmd, size_t sizeof_raw, u32 object_id) { - void* raw = ipcPrepareHeader(cmd, sizeof_raw + sizeof(DomainMessageHeader)); - DomainMessageHeader* hdr = (DomainMessageHeader*) raw; - u32 *object_ids = (u32*)(((uintptr_t) raw) + sizeof(DomainMessageHeader) + sizeof_raw); - - hdr->Type = DomainMessageType_SendMessage; - hdr->NumObjectIds = (u8)cmd->NumObjectIds; - hdr->Length = sizeof_raw; - hdr->ThisObjectId = object_id; - hdr->Pad[0] = hdr->Pad[1] = 0; - - for(size_t i = 0; i < cmd->NumObjectIds; i++) - object_ids[i] = cmd->ObjectIds[i]; - return (void*)(((uintptr_t) raw) + sizeof(DomainMessageHeader)); -} - -/** - * @brief Parse an IPC command response into an IPC parsed command structure (domain version). - * @param IPC parsed command structure to fill in. - * @return Result code. - */ -static inline Result ipcParseForDomain(IpcParsedCommand* r) { - Result rc = ipcParse(r); - DomainMessageHeader *hdr; - u32 *object_ids; - if(R_FAILED(rc)) - return rc; - - hdr = (DomainMessageHeader*) r->Raw; - object_ids = (u32*)(((uintptr_t) hdr) + sizeof(DomainMessageHeader) + hdr->Length); - r->Raw = (void*)(((uintptr_t) r->Raw) + sizeof(DomainMessageHeader)); - - r->IsDomainMessage = true; - r->MessageType = (DomainMessageType)(hdr->Type); - switch (r->MessageType) { - case DomainMessageType_SendMessage: - case DomainMessageType_Close: - break; - default: - return MAKERESULT(Module_Libnx, LibnxError_DomainMessageUnknownType); - } - r->ThisObjectId = hdr->ThisObjectId; - r->NumObjectIds = hdr->NumObjectIds > 8 ? 8 : hdr->NumObjectIds; - if ((uintptr_t)object_ids + sizeof(u32) * r->NumObjectIds - (uintptr_t)armGetTls() >= 0x100) { - return MAKERESULT(Module_Libnx, LibnxError_DomainMessageTooManyObjectIds); - } - for(size_t i = 0; i < r->NumObjectIds; i++) - r->ObjectIds[i] = object_ids[i]; - - return rc; -} - -/** - * @brief Closes a domain object by ID. - * @param session IPC session handle. - * @param object_id ID of the object to close. - * @return Result code. - */ -static inline Result ipcCloseObjectById(Handle session, u32 object_id) { - IpcCommand c; - DomainMessageHeader* hdr; - - ipcInitialize(&c); - hdr = (DomainMessageHeader*)ipcPrepareHeader(&c, sizeof(DomainMessageHeader)); - - hdr->Type = 2; - hdr->NumObjectIds = 0; - hdr->Length = 0; - hdr->ThisObjectId = object_id; - hdr->Pad[0] = hdr->Pad[1] = 0; - - return ipcDispatch(session); // this command has no associated response -} - -///@} - diff --git a/tests/unittests/data/teststaticnewlinebraces.h b/tests/unittests/data/teststaticnewlinebraces.h deleted file mode 100644 index c72c11a..0000000 --- a/tests/unittests/data/teststaticnewlinebraces.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file condvar.h - * @brief Condition variable synchronization primitive. - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../types.h" -#include "../kernel/mutex.h" - -/// Condition variable structure. -typedef struct { - u32 tag; - Mutex* mutex; -} CondVar; - -/** - * @brief Initializes a condition variable. - * @param[in] c Condition variable object. - * @param[in] m Mutex object to use inside the condition variable. - */ -void condvarInit(CondVar* c, Mutex* m); - -/** - * @brief Waits on a condition variable with a timeout. - * @param[in] c Condition variable object. - * @param[in] timeout Timeout in nanoseconds. - * @return Result code (0xEA01 on timeout). - * @remark On function return, the underlying mutex is acquired. - */ -Result condvarWaitTimeout(CondVar* c, u64 timeout); - -/** - * @brief Waits on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - * @remark On function return, the underlying mutex is acquired. - */ -static inline Result condvarWait(CondVar* c) -{ - return condvarWaitTimeout(c, -1ull); -} - -/** - * @brief Wakes up up to the specified number of threads waiting on a condition variable. - * @param[in] c Condition variable object. - * @param[in] num Maximum number of threads to wake up (or -1 to wake them all up). - * @return Result code. - */ -Result condvarWake(CondVar* c, int num); - -/** - * @brief Wakes up a single thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeOne(CondVar* c) -{ - return condvarWake(c, 1); -} - -/** - * @brief Wakes up all thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeAll(CondVar* c) -{ - return condvarWake(c, -1); -} - diff --git a/tests/unittests/data/teststaticnewlinebracesreadded.h b/tests/unittests/data/teststaticnewlinebracesreadded.h deleted file mode 100644 index 176f4fc..0000000 --- a/tests/unittests/data/teststaticnewlinebracesreadded.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @file condvar.h - * @brief Condition variable synchronization primitive. - * @author plutoo - * @copyright libnx Authors - */ -#pragma once -#include "../types.h" -#include "../kernel/mutex.h" - -/// Condition variable structure. -typedef struct { - u32 tag; - Mutex* mutex; -} CondVar; - -/** - * @brief Initializes a condition variable. - * @param[in] c Condition variable object. - * @param[in] m Mutex object to use inside the condition variable. - */ -void condvarInit(CondVar* c, Mutex* m); - -/** - * @brief Waits on a condition variable with a timeout. - * @param[in] c Condition variable object. - * @param[in] timeout Timeout in nanoseconds. - * @return Result code (0xEA01 on timeout). - * @remark On function return, the underlying mutex is acquired. - */ -Result condvarWaitTimeout(CondVar* c, u64 timeout); - -/** - * @brief Waits on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - * @remark On function return, the underlying mutex is acquired. - */ -static inline Result condvarWait(CondVar* c) { - return condvarWaitTimeout(c, -1ull); -} - -/** - * @brief Wakes up up to the specified number of threads waiting on a condition variable. - * @param[in] c Condition variable object. - * @param[in] num Maximum number of threads to wake up (or -1 to wake them all up). - * @return Result code. - */ -Result condvarWake(CondVar* c, int num); - -/** - * @brief Wakes up a single thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeOne(CondVar* c) { - return condvarWake(c, 1); -} - -/** - * @brief Wakes up all thread waiting on a condition variable. - * @param[in] c Condition variable object. - * @return Result code. - */ -static inline Result condvarWakeAll(CondVar* c) { - return condvarWake(c, -1); -} - diff --git a/tests/unittests/nim.cfg b/tests/unittests/nim.cfg deleted file mode 100644 index e9b9a2e..0000000 --- a/tests/unittests/nim.cfg +++ /dev/null @@ -1 +0,0 @@ ---path="../../src" diff --git a/tests/unittests/testfileops.nim b/tests/unittests/testfileops.nim deleted file mode 100644 index 2d24d4e..0000000 --- a/tests/unittests/testfileops.nim +++ /dev/null @@ -1,209 +0,0 @@ -import nimgen/fileops, common, regex, os - -import unittest - -let testFileContent = """ -this is text -this is text -replace me -prepend me -end -""" - -let prependMiddleExpected = """ -this is text -this is text -replace me -prepended data -prepend me -end -""" - -let prependEndExpected = """ -this is text -this is text -replace me -prepend me -data -end -""" - -let appendEndExpected = """ -this is text -this is text -replace me -prepend me -end -data -""" - -let appendMiddleExpected = """ -this is data - text -this is text -replace me -prepend me -end -""" - -let freplaceDefaultExpected = """ - - -replace me -prepend me -end -""" - -let freplaceWithExpected = """ -this is text -this is text -foobar -prepend me -end -""" - -let freplaceRegexExpected = """ -foobar -foobar -replace me -prepend me -end -""" - -let commentExpected = """ -this is text -this is text -//replace me -//prepend me -//end -""" - -let commentMiddleExpected = """ -this //is text -//this is text -replace me -prepend me -end -""" - - -let dataDir = currentSourcePath().splitPath().head / "data" - -let testfilename = dataDir / "testing.txt" - - -suite "test file ops": - if not dataDir.dirExists(): - dataDir.createDir() - - setup: - writeFile(testfilename, testFileContent) - - ################### Prepend ####################### - - test "prepend at beginning of file": - prepend(testfilename, "data\n") - let expected = "data\n" & testFileContent - testfilename.checkFile(expected) - - test "prepend at middle of file": - prepend(testfilename, "prepended data\n", "prepend me") - testfilename.checkFile(prependMiddleExpected) - - test "prepend at end of file": - prepend(testfilename, "data\n", "end\n") - testfilename.checkFile(prependEndExpected) - - ################### Pipe ######################### - - test "pipe command into file": - when defined(windows): - pipe(testfilename, "ECHO foo") - testfilename.checkFile("foo") - else: - pipe(testfilename, "cat $file | grep 'this is text'") - testfilename.checkFile("this is text\nthis is text") - - ################# Append ######################### - - test "append file end": - append(testfilename, "data\n") - testfilename.checkFile(appendEndExpected) - - test "append file middle": - append(testfilename, " data\n", "this is") - testfilename.checkFile(appendMiddleExpected) - - ################# FReplace ######################### - - test "freplace default empty": - freplace(testfilename, "this is text") - testfilename.checkFile(freplaceDefaultExpected) - - test "freplace with content": - freplace(testfilename, "replace me", "foobar") - testfilename.checkFile(freplaceWithExpected) - - test "freplace regex": - freplace(testfilename, re"this .*", "foobar") - testfilename.checkFile(freplaceRegexExpected) - - ####################### Comment ###################### - - test "comment": - comment(testfilename, "replace me", "3") - testfilename.checkFile(commentExpected) - - test "comment over length": - comment(testfilename, "replace me", "10") - testfilename.checkFile(commentExpected) - - test "comment negative": - comment(testfilename, "replace me", "-3") - testfilename.checkFile(testFileContent) - - test "comment zero": - comment(testfilename, "replace me", "0") - testfilename.checkFile(testFileContent) - - test "comment middle": - comment(testfilename, "is text", "2") - testfilename.checkFile(commentMiddleExpected) - - ############### Static inline removal ################ - - test "replace static inline with front braces at end of line": - - let - file = dataDir / "teststaticfrontbraces.h" - resFile = dataDir / "teststaticexpectedfrontbraces.h" - - test = readFile(file) - expected = readFile(resFile) - - writeFile(testfilename, test) - - removeStatic(testfilename) - testfilename.checkFile(expected) - - reAddStatic(testfilename) - testfilename.checkFile(test) - - test "replace static inline with newline before brace": - - let - file = dataDir / "teststaticnewlinebraces.h" - resFile = dataDir / "teststaticexpectednewlinebraces.h" - reAddedFile = dataDir / "teststaticnewlinebracesreadded.h" - - test = readFile(file) - expected = readFile(resFile) - reAdded = readFile(reAddedFile) - - writeFile(testfilename, test) - - removeStatic(testfilename) - testfilename.checkFile(expected) - - reAddStatic(testfilename) - testfilename.checkFile(reAdded) diff --git a/web/CNAME b/web/CNAME deleted file mode 100644 index 2c6879b..0000000 --- a/web/CNAME +++ /dev/null @@ -1 +0,0 @@ -nimgen.genotrance.com \ No newline at end of file diff --git a/web/nimdoc.cfg b/web/nimdoc.cfg deleted file mode 100644 index 55c2827..0000000 --- a/web/nimdoc.cfg +++ /dev/null @@ -1,1401 +0,0 @@ -# This is the config file for the documentation generator. -# (c) 2016 Andreas Rumpf -# Feel free to edit the templates as you need. If you modify this file, it -# might be worth updating the hardcoded values in packages/docutils/rstgen.nim - -split.item.toc = "20" -# too long entries in the table of contents wrap around -# after this number of characters - -doc.section = """ -
-

$sectionTitle

-
-$content -
-""" - -doc.section.toc = """ -
  • - $sectionTitle -
      - $content -
    -
  • -""" - -# Chunk of HTML emitted for each entry in the HTML table of contents. -# Available variables are: -# * $desc: the actual docstring of the item. -# * $header: the full version of name, including types, pragmas, tags, etc. -# * $header_plain: like header but without HTML, for attribute embedding. -# * $itemID: numerical unique entry of the item in the HTML. -# * $itemSym: short symbolic name of the item for easier hyperlinking. -# * $itemSymEnc: quoted version for URLs or attributes. -# * $itemSymOrID: the symbolic name or the ID if that is not unique. -# * $itemSymOrIDEnc: quoted version for URLs or attributes. -# * $name: reduced name of the item. -# * $seeSrc: generated HTML from doc.item.seesrc (if some switches are used). - -doc.item = """ -
    $header
    -
    -$desc -$seeSrc -
    -""" - -# Chunk of HTML emitted for each entry in the HTML table of contents. -# See doc.item for available substitution variables. -doc.item.toc = """ -
  • $name
  • -""" - -# HTML rendered for doc.item's seeSrc variable. Note that this will render to -# the empty string if you don't pass anything through --docSeeSrcURL. Available -# substitutaion variables here are: -# * $path: relative path to the file being processed. -# * $line: line of the item in the original source file. -# * $url: whatever you did pass through the --docSeeSrcUrl switch (which also -# gets variables path/line replaced!) -doc.item.seesrc = """  Source -""" - -doc.toc = """ -
      -$content -
    -""" - -doc.body_toc = """ -
    -
    -
    - Search: -
    - $tableofcontents -
    -
    -
    -

    $moduledesc

    - $content -
    -
    -""" - -@if boot: -# This is enabled with the "boot" directive to generate -# the compiler documentation. -# As a user, tweak the block below instead. -# You can add your own global-links entries -doc.body_toc_group = """ -
    -
    - -
    - Search: -
    -
    - Group by: - -
    - $tableofcontents -
    -
    -
    -

    $moduledesc

    - $content -
    -
    -""" - -@else - -doc.body_toc_group = """ -
    -
    - -
    - Search: -
    -
    - Group by: - -
    - $tableofcontents -
    -
    -
    -

    $moduledesc

    - $content -
    -
    -""" -@end - -doc.body_no_toc = """ -$moduledesc -$content -""" - -doc.listing_start = "
    "
    -doc.listing_end = "
    " - -# * $analytics: Google analytics location, includes - - - - - -
    -
    -

    $title

    - $content -
    - -
    -
    -
    -$analytics - - -"""