Created
March 22, 2023 10:49
-
-
Save Oldes/5b186cc330eec2137708679eead3f62e to your computer and use it in GitHub Desktop.
Rebol extension source code template generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REBOL [ | |
title: "Rebol extension source code template generator" | |
] | |
system/options/quiet: false | |
system/options/log/siskin: 3 | |
;- File templates -------------------------------------------------------------- | |
rebol-extension.r3: {REBOL [ | |
title: "Rebol/#NAME# module builder" | |
type: module | |
date: #DATE# | |
home: https://github.com/Oldes/Rebol-#NAME# | |
version: 1.0.0 | |
author: @Oldes | |
] | |
;- all extension command specifications ---------------------------------------- | |
commands: [ | |
info: ["Info about #NAME# extension"] | |
] | |
;-------------------------------------- ---------------------------------------- | |
reb-code: {REBOL [Title: {Rebol #NAME# Extension} Type: module]} | |
enu-commands: "" ;; command name enumerations | |
cmd-declares: "" ;; command function declarations | |
cmd-dispatch: "" ;; command functionm dispatcher | |
;- generate C and Rebol code from the command specifications ------------------- | |
foreach [name spec] commands [ | |
append reb-code ajoin [lf name ": command "] | |
new-line/all spec false | |
append/only reb-code mold spec | |
name: form name | |
replace/all name #"-" #"_" | |
append enu-commands ajoin [LF TAB "#ENUM_PREFIX#" uppercase copy name #","] | |
append cmd-declares ajoin [LF "int cmd_" name "(RXIFRM *frm, void *ctx);"] | |
append cmd-dispatch ajoin [TAB "cmd_" name #"," LF] | |
] | |
;- additional Rebol initialization code ---------------------------------------- | |
;append reb-code {} | |
;print reb-code | |
;- convert Rebol code to C-string ---------------------------------------------- | |
init-code: copy "" | |
foreach line split reb-code lf [ | |
replace/all line #"^"" {\"} | |
append init-code ajoin [{\^/^-"} line {\n"}] | |
] | |
;-- C file templates ----------------------------------------------------------- | |
header: { | |
// | |
// auto-generated file, do not modify! | |
// | |
#include "rebol-extension.h" | |
#define MIN_REBOL_VER 3 | |
#define MIN_REBOL_REV 5 | |
#define MIN_REBOL_UPD 4 | |
#define VERSION(a, b, c) (a << 16) + (b << 8) + c | |
#define MIN_REBOL_VERSION VERSION(MIN_REBOL_VER, MIN_REBOL_REV, MIN_REBOL_UPD) | |
enum ext_commands {$enu-commands | |
}; | |
$cmd-declares | |
typedef int (*MyCommandPointer)(RXIFRM *frm, void *ctx); | |
#define #NAME#_EXT_INIT_CODE $init-code | |
#ifdef USE_TRACES | |
#include <stdio.h> | |
#define debug_print(fmt, ...) do { printf(fmt, __VA_ARGS__); } while (0) | |
#define trace(str) puts(str) | |
#else | |
#define debug_print(fmt, ...) | |
#define trace(str) | |
#endif | |
} | |
;;------------------------------------------------------------------------------ | |
ctable: { | |
// | |
// auto-generated file, do not modify! | |
// | |
#include "#FILE_PREFIX#-rebol-extension.h" | |
MyCommandPointer Command[] = { | |
$cmd-dispatch}; | |
} | |
;- output generated files ------------------------------------------------------ | |
write %#FILE_PREFIX#-rebol-extension.h reword :header self | |
write %#FILE_PREFIX#-commands-table.c reword :ctable self | |
} | |
;- | |
commands.c: { | |
// ============================================================================= | |
// Rebol/#NAME# extension commands | |
// ============================================================================= | |
#include "#FILE_PREFIX#-rebol-extension.h" | |
#define COMMAND int | |
#define ARG_Double(n) RXA_DEC64(frm,n) | |
// Command implementations follows...... | |
COMMAND cmd_info(RXIFRM *frm, void *ctx) { | |
const char text[] = "Hello from #NAME"; | |
REBINT len = strlen(text); | |
REBSER* ser = RL_MAKE_STRING(len, FALSE); | |
memcpy(ser->data, text, len); | |
SERIES_TAIL(ser) = len; | |
RXA_SERIES(frm, 1) = ser; | |
RXA_TYPE(frm, 1) = RXT_STRING; | |
RXA_INDEX(frm, 1) = 0; | |
return RXR_VALUE; | |
} | |
} | |
;- | |
rebol-extension.c: { | |
// ============================================================================= | |
// Rebol/BlurHash extension | |
// ============================================================================= | |
#include "#FILE_PREFIX#-rebol-extension.h" | |
RL_LIB *RL; // Link back to reb-lib from embedded extensions | |
//==== Globals ===============================================================// | |
extern MyCommandPointer Command[]; | |
//============================================================================// | |
static const char* init_block = #NAME#_EXT_INIT_CODE; | |
RXIEXT const char *RX_Init(int opts, RL_LIB *lib) { | |
RL = lib; | |
REBYTE ver[8]; | |
RL_VERSION(ver); | |
debug_print( | |
"RXinit #FILE_PREFIX#-extension; Rebol v%i.%i.%i\n", | |
ver[1], ver[2], ver[3]); | |
if (MIN_REBOL_VERSION > VERSION(ver[1], ver[2], ver[3])) { | |
debug_print( | |
"Needs at least Rebol v%i.%i.%i!\n", | |
MIN_REBOL_VER, MIN_REBOL_REV, MIN_REBOL_UPD); | |
return 0; | |
} | |
if (!CHECK_STRUCT_ALIGN) { | |
trace("CHECK_STRUCT_ALIGN failed!"); | |
return 0; | |
} | |
return init_block; | |
} | |
RXIEXT int RX_Call(int cmd, RXIFRM *frm, void *ctx) { | |
return Command[cmd](frm, ctx); | |
} | |
} | |
.nest: { | |
;- .-. | |
;- /'v'\ SISKIN-Builder 3.9.0 project file | |
;- (/uOu\) https://github.com/Siskin-framework/Builder/ | |
;-===="="======================================================================= | |
compiler: clang | |
version: 1.0.0 | |
optimize: 3 | |
strip: off | |
;define: USE_TRACES | |
define: ENDIAN_LITTLE | |
cflag: fpermissive | |
flag: -Wno-pointer-sign | |
flag: shared | |
;- options common for all Rebol extensions ---------------------- | |
#if Windows? [ | |
define: _CRT_SECURE_NO_WARNINGS | |
define: _USE_MATH_DEFINES | |
define: TO_WINDOWS | |
upx: on | |
compiler: gcc | |
] | |
#if Linux? [ | |
compiler: gcc | |
] | |
target-x86: [ | |
arch: x86 | |
] | |
target-x64: [ | |
arch: x64 | |
defines: [ | |
_FILE_OFFSET_BITS=64 | |
__LP64__ ; has long (integer) 64 bits | |
] | |
#if macOS? [ flag: "-arch x86_64" ] | |
] | |
target-arm64: [ | |
arch: arm64 | |
#if Linux? [ | |
flag: "-arch arm64" | |
] | |
#if macOS? [ | |
flag: "-target arm64-apple-darwin" | |
] | |
define: _FILE_OFFSET_BITS=64 | |
define: __LP64__ ; has long (integer) 64 bits | |
define: __arm64__ | |
] | |
target-armv7: [ | |
arch: armv7 | |
flag: "-march=armv7" | |
] | |
;---------------------------------------------------------------- | |
files: [ | |
%src/#FILE_PREFIX#-commands.c | |
%src/#FILE_PREFIX#-commands-table.c | |
%src/#FILE_PREFIX#-rebol-extension.c | |
] | |
#if Posix? [ | |
cflags: fPIC | |
] | |
;- generate main extension header -------------------------------- | |
do %src/#FILE_PREFIX#-rebol-extension.r3 | |
eggs: only [ | |
#if Windows? [ | |
"Rebol #NAME# extension: windows_x86" [ | |
name: %#FILE_PREFIX#-windows-x86 | |
:target-x86 | |
] | |
"Rebol #NAME# extension: windows_x64" [ | |
name: %#FILE_PREFIX#-windows-x64 | |
:target-x64 | |
] | |
] | |
#if Linux? [ | |
"Rebol #NAME# extension: linux_x86" [ | |
name: %#FILE_PREFIX#-linux-x86 | |
:target-x86 | |
] | |
"Rebol #NAME# extension: linux_x64" [ | |
name: %#FILE_PREFIX#-linux-x64 | |
:target-x64 | |
] | |
"Rebol #NAME# extension: linux_armv7" [ | |
name: %#FILE_PREFIX#-linux-armv7 | |
:target-armv7 | |
] | |
"Rebol #NAME# extension: linux_arm64" [ | |
name: %#FILE_PREFIX#-linux-arm64 | |
:target-arm64 | |
] | |
] | |
#if macOS? [ | |
"Rebol #NAME# extension: macos_x64" [ | |
name: %#FILE_PREFIX#-macos-x64 | |
:target-x64 | |
] | |
"Rebol #NAME# extension: macos_arm64" [ | |
name: %#FILE_PREFIX#-macos-arm64 | |
:target-arm64 | |
] | |
] | |
] | |
} | |
until [all [ | |
name: ask as-yellow "Extension name: " | |
trim/all name | |
parse name [some system/catalog/bitsets/alpha-numeric] | |
]] | |
values: make object! compose [ | |
DATE: now/date | |
NAME: (uppercase/part name 1) | |
FILE_PREFIX: lowercase copy name | |
ENUM_PREFIX: ajoin ["CMD_" uppercase copy name #"_"] | |
] | |
? values | |
make-dir dir: rejoin [%Rebol- values/NAME %/] | |
make-dir srcdir: rejoin [dir %src/] | |
write-rebx-file: func[file [file! word!] data][ | |
try/except [ | |
write file data | |
sys/log/more 'SISKIN ["REBX Generated:^[[33m" to-local-file file] | |
][ sys/log/error 'SISKIN system/state/last-error ] | |
file | |
] | |
data: trim/head reword/escape .nest values [#"#" #"#"] | |
file: rejoin [dir %Rebol- values/NAME %.nest] | |
write-rebx-file file data | |
foreach file [ | |
rebol-extension.r3 | |
rebol-extension.c | |
commands.c | |
][ | |
data: trim/head reword/escape get file values [#"#" #"#"] | |
file: rejoin [srcdir values/FILE_PREFIX %- file] | |
write-rebx-file file data | |
] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment