From 3346097397a1fe61f7027432b9c2c21263b05261 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 09:53:10 +0100 Subject: [PATCH 01/37] Create Foo.scala --- example/scalalib/native/1-simple/src/Foo.scala | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 example/scalalib/native/1-simple/src/Foo.scala diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala new file mode 100644 index 00000000000..f5e1e91c272 --- /dev/null +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -0,0 +1,7 @@ +package foo + +object Main { + val colored = Console.GREEN + "Hello World Ansi!" + Console.RESET + def main(args: Array[String]): Unit = + println(colored) +} From 52a38c4d0eaa9fb802bcc2e5f72910d2053a3a15 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:07:19 +0100 Subject: [PATCH 02/37] Add files via upload --- example/scalalib/native/1-simple/build.mill | 128 ++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 example/scalalib/native/1-simple/build.mill diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill new file mode 100644 index 00000000000..fd2753d59c0 --- /dev/null +++ b/example/scalalib/native/1-simple/build.mill @@ -0,0 +1,128 @@ +//// SNIPPET:BUILD +package build +import mill._, scalalib._, scalanative._ + +object `package` extends RootModule with ScalaNativeModule { + def scalaVersion = "2.13.11" + def scalaNativeVersion = "0.5.5" + def ivyDeps = Agg( + ivy"com.lihaoyi::fansi:0.5.0" + ) + + object test extends ScalaNativeTests { + def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def testFramework = "utest.runner.Framework" + } +} + +// This is a basic Mill build for a single `ScalaNativeModule`, with one +// third-party dependencies and a test suite using the uTest framework. As a +// single-module project, it `extends RootModule` to mark `object foo` as the +// top-level module in the build. This lets us directly perform operations +// `./mill compile` or `./mill run` without needing to prefix it as +// `foo.compile` or `foo.run`. +// +//// SNIPPET:END +// +// You can download this example project using the *download* link above +// if you want to try out the commands below yourself. The only requirement is +// that you have some version of the JVM installed; the `./mill` script takes +// care of any further dependencies that need to be downloaded. +// +// The source code for this module lives in the `src/` folder. +// Output for this module (compiled files, resolved dependency lists, ...) +// lives in `out/`. +// +//// SNIPPET:DEPENDENCIES +// +// This example project uses a third-party dependency - Fansi to color text in terminal. +// +// You can run `assembly` to generate a standalone executable jar, which then +// can be run from the command line or deployed to be run elsewhere. + +/** Usage + +> ./mill resolve _ # List what tasks are available to run +assembly +... +clean +... +compile +... +run +... +show +... +inspect +... + +> ./mill inspect compile # Show documentation and inputs of a task +compile(ScalaModule.scala:...) + Compiles the current module to generate compiled classfiles/bytecode. +Inputs: + scalaVersion + upstreamCompileOutput + allSourceFiles + compileClasspath + +> ./mill compile # compile sources into classfiles +... +compiling 1 Scala source to... + +> ./mill run # run the main method, if any +error: Missing argument: --text + +> ./mill run +Hello World Ansi (colored in Green) +> ./mill test +... ++ foo.FooTests...simple ...

hello

++ foo.FooTests...escaping ...

<hello>

+ +> ./mill assembly # bundle classfiles and libraries into a jar for deployment + +> ./mill show assembly # show the output of the assembly task +".../out/assembly.dest/out.jar" + +> java -jar ./out/assembly.dest/out.jar +Hello World Ansi (colored in Green) + +> ./out/assembly.dest/out.jar # mac/linux +Hello World Ansi (colored in Green) + +*/ + +//// SNIPPET:END + +// The output of every Mill task is stored in the `out/` folder under a name +// corresponding to the task that created it. e.g. The `assembly` task puts its +// metadata output in `out/assembly.json`, and its output files in +// `out/assembly.dest`. You can also use `show` to make Mill print out the +// metadata output for a particular task. +// +// Additional Mill tasks you would likely need include: +// +// [source,bash] +// ---- +// $ mill runBackground # run the main method in the background +// +// $ mill clean # delete the cached output of a task, terminate any runBackground +// +// $ mill launcher # prepares a foo/launcher.dest/run you can run later +// +// $ mill jar # bundle the classfiles into a jar suitable for publishing +// +// $ mill -i console # start a Scala console within your project +// +// $ mill -i repl # start an Ammonite Scala REPL within your project +// ---- +// +// You can run `+mill resolve __+` to see a full list of the different tasks that +// are available, `+mill resolve _+` to see the tasks within `foo`, +// `mill inspect compile` to inspect a task's doc-comment documentation or what +// it depends on, or `mill show foo.scalaVersion` to show the output of any task. +// +// The most common *tasks* that Mill can run are cached *targets*, such as +// `compile`, and un-cached *commands* such as `foo.run`. Targets do not +// re-evaluate unless one of their inputs changes, whereas commands re-run every +// time. \ No newline at end of file From 367bcb0350ecd89de133c3b437ca954694064669 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 10:23:06 +0100 Subject: [PATCH 03/37] import scala native lib properly --- example/scalalib/native/1-simple/build.mill | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index fd2753d59c0..51c6b7fe3f4 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -1,6 +1,6 @@ //// SNIPPET:BUILD package build -import mill._, scalalib._, scalanative._ +import mill._, scalalib._, scalanativelib._ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" @@ -125,4 +125,4 @@ Hello World Ansi (colored in Green) // The most common *tasks* that Mill can run are cached *targets*, such as // `compile`, and un-cached *commands* such as `foo.run`. Targets do not // re-evaluate unless one of their inputs changes, whereas commands re-run every -// time. \ No newline at end of file +// time. From a48faac220af43b07493e2972a7208f91bfc67d8 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:18:01 +0100 Subject: [PATCH 04/37] Update Foo.scala --- example/scalalib/native/1-simple/src/Foo.scala | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index f5e1e91c272..2de577a0280 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -1,7 +1,16 @@ package foo +import scalatags.Text.all._ +import mainargs.{main, ParserForMethods} -object Main { - val colored = Console.GREEN + "Hello World Ansi!" + Console.RESET - def main(args: Array[String]): Unit = - println(colored) +object Foo { + def generateHtml(text: String) = { + h1(text).toString + } + + @main + def main(text: String) = { + println(generateHtml(text)) + } + + def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) } From 7df436799ff85e84e1ef302d4cf134b2b0397393 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:20:10 +0100 Subject: [PATCH 05/37] Create FooTests.scala --- .../native/1-simple/test/src/FooTests.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 example/scalalib/native/1-simple/test/src/FooTests.scala diff --git a/example/scalalib/native/1-simple/test/src/FooTests.scala b/example/scalalib/native/1-simple/test/src/FooTests.scala new file mode 100644 index 00000000000..9dcd8bf4e04 --- /dev/null +++ b/example/scalalib/native/1-simple/test/src/FooTests.scala @@ -0,0 +1,18 @@ +package foo + +import utest._ + +object FooTests extends TestSuite { + def tests = Tests { + test("simple") { + val result = Foo.generateHtml("hello") + assert(result == "

hello

") + result + } + test("escaping") { + val result = Foo.generateHtml("") + assert(result == "

<hello>

") + result + } + } +} From cee766e4aa72654b5f09ad7ecae72e2f36f99f5c Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:21:55 +0100 Subject: [PATCH 06/37] Update build.mill --- example/scalalib/native/1-simple/build.mill | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index 51c6b7fe3f4..7b96b7c3d32 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -6,7 +6,8 @@ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" def ivyDeps = Agg( - ivy"com.lihaoyi::fansi:0.5.0" + ivy"com.lihaoyi::scalatags:0.12.0", + ivy"com.lihaoyi::mainargs:0.6.2" ) object test extends ScalaNativeTests { From ef802d33cbd58fb29c052bea0b8bb5d37066f28f Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:39:16 +0100 Subject: [PATCH 07/37] Create Hello world.c --- example/scalalib/native/2-interop/native-src/Hello world.c | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 example/scalalib/native/2-interop/native-src/Hello world.c diff --git a/example/scalalib/native/2-interop/native-src/Hello world.c b/example/scalalib/native/2-interop/native-src/Hello world.c new file mode 100644 index 00000000000..94f5b9fd77a --- /dev/null +++ b/example/scalalib/native/2-interop/native-src/Hello world.c @@ -0,0 +1,5 @@ +#include + +void printString(const char *str) { + printf("%s\n", str); +} From 11a6e75de619fd5674dffbc6bb8f87ccae48fa6f Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:48:17 +0100 Subject: [PATCH 08/37] Create HelloWorld.scala --- .../native/2-interop/src/foo/HelloWorld.scala | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 example/scalalib/native/2-interop/src/foo/HelloWorld.scala diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala new file mode 100644 index 00000000000..19e42d68340 --- /dev/null +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -0,0 +1,18 @@ +package foo + +object Main { + def main(args: Array[String]): Unit = { + print("Running HelloWorld function\n") + HelloWorld.printString(c"Hello world!!\n") + print("Done...\n") + } +} + +// Define the external module, the C library containing our function "printString" +@extern +@link("HelloWorld") +// Arbitrary object name +object HelloWorld { + // Name and signature of C function + def printString(str: CString): Unit = extern +} From 2783005d9f3a98bd28f57d9548cdf994657329ad Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:49:08 +0100 Subject: [PATCH 09/37] Rename Hello world.c to HelloWorld.c --- .../native/2-interop/native-src/{Hello world.c => HelloWorld.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename example/scalalib/native/2-interop/native-src/{Hello world.c => HelloWorld.c} (100%) diff --git a/example/scalalib/native/2-interop/native-src/Hello world.c b/example/scalalib/native/2-interop/native-src/HelloWorld.c similarity index 100% rename from example/scalalib/native/2-interop/native-src/Hello world.c rename to example/scalalib/native/2-interop/native-src/HelloWorld.c From 24b9543aa7df93ce8b8f9ede5f7a979c259560f6 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Thu, 3 Oct 2024 13:36:26 +0100 Subject: [PATCH 10/37] update interop example --- example/scalalib/native/2-interop/src/foo/HelloWorld.scala | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala index 19e42d68340..2cdf3a3b838 100644 --- a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -1,4 +1,5 @@ package foo +import scala.scalanative.unsafe._ object Main { def main(args: Array[String]): Unit = { @@ -16,3 +17,4 @@ object HelloWorld { // Name and signature of C function def printString(str: CString): Unit = extern } + From b1015e7a6956f90e593dc0d870c9d3ed940803bf Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:15:56 +0100 Subject: [PATCH 11/37] Create build.mill --- example/scalalib/native/2-interop/build.mill | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 example/scalalib/native/2-interop/build.mill diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill new file mode 100644 index 00000000000..cf151e6b556 --- /dev/null +++ b/example/scalalib/native/2-interop/build.mill @@ -0,0 +1,20 @@ +//// SNIPPET:BUILD +package build +import mill._, scalalib._, scalanativelib._ + +object `package` extends RootModule with ScalaNativeModule { + def scalaVersion = "2.13.11" + def scalaNativeVersion = "0.5.5" + def nativeLinkingOptions = "" + + object test extends ScalaNativeTests { + def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def testFramework = "utest.runner.Framework" + } +} + +//// SNIPPET:END +// +//// SNIPPET:DEPENDENCIES +// +//// SNIPPET:END From 8740b01b7843c6a8fdea63d754defa2ca2f760ed Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:23:43 +0100 Subject: [PATCH 12/37] Create Makefile --- example/scalalib/native/2-interop/Makefile | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 example/scalalib/native/2-interop/Makefile diff --git a/example/scalalib/native/2-interop/Makefile b/example/scalalib/native/2-interop/Makefile new file mode 100644 index 00000000000..b20eb32e02e --- /dev/null +++ b/example/scalalib/native/2-interop/Makefile @@ -0,0 +1,4 @@ + +all : + mkdir target + gcc -m64 -shared -c native-src/HelloWorld.c -o target/libhelloworld.so From 19ed282f92aa3668f99b2e8ab5813db770473fba Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Thu, 3 Oct 2024 17:53:19 +0100 Subject: [PATCH 13/37] Update build.mill of interop example --- example/scalalib/native/2-interop/build.mill | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill index cf151e6b556..a4a195288ff 100644 --- a/example/scalalib/native/2-interop/build.mill +++ b/example/scalalib/native/2-interop/build.mill @@ -5,7 +5,7 @@ import mill._, scalalib._, scalanativelib._ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" - def nativeLinkingOptions = "" + def nativeLinkingOptions = Seq("-L" + os.pwd(".") + "/target") object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") From 2c9d4ec5a032bf4e61c23cf65f66ca2453eed54b Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Fri, 4 Oct 2024 16:04:10 +0100 Subject: [PATCH 14/37] add some example files --- example/scalalib/native/2-interop/Makefile | 4 - example/scalalib/native/2-interop/build.mill | 25 +++- .../native/2-interop/native-src/HelloWorld.c | 14 ++- .../native/2-interop/src/foo/HelloWorld.scala | 8 +- .../2-interop/test/src/HelloWorldTests.scala | 28 +++++ .../native/3-multi-module/bar/src/Bar.scala | 12 ++ .../bar/test/src/BarTests.scala | 16 +++ .../scalalib/native/3-multi-module/build.mill | 116 ++++++++++++++++++ .../native/3-multi-module/foo/src/Foo.scala | 12 ++ 9 files changed, 225 insertions(+), 10 deletions(-) delete mode 100644 example/scalalib/native/2-interop/Makefile create mode 100644 example/scalalib/native/2-interop/test/src/HelloWorldTests.scala create mode 100644 example/scalalib/native/3-multi-module/bar/src/Bar.scala create mode 100644 example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala create mode 100644 example/scalalib/native/3-multi-module/build.mill create mode 100644 example/scalalib/native/3-multi-module/foo/src/Foo.scala diff --git a/example/scalalib/native/2-interop/Makefile b/example/scalalib/native/2-interop/Makefile deleted file mode 100644 index b20eb32e02e..00000000000 --- a/example/scalalib/native/2-interop/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -all : - mkdir target - gcc -m64 -shared -c native-src/HelloWorld.c -o target/libhelloworld.so diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill index a4a195288ff..29cfeb4b869 100644 --- a/example/scalalib/native/2-interop/build.mill +++ b/example/scalalib/native/2-interop/build.mill @@ -5,7 +5,30 @@ import mill._, scalalib._, scalanativelib._ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" - def nativeLinkingOptions = Seq("-L" + os.pwd(".") + "/target") + def nativeLinkingOptions = Seq("-L" + millSourcePath + "/output") + + // Additional source folder to put C sources + def nativeSources = T.sources(millSourcePath / "native-src") + + + + // Compile C + def nativeCompiled = T { + val cSourceFiles = nativeSources().map(_.path).flatMap(os.walk(_)).filter(_.ext == "c") + val output = "libhelloworld.so" + + os.proc( + "gcc", "-m64", "-shared", + "-c", cSourceFiles, + "-o", T.dest.toString+output + ) + .call() + + + PathRef(T.dest / output) + } + + object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") diff --git a/example/scalalib/native/2-interop/native-src/HelloWorld.c b/example/scalalib/native/2-interop/native-src/HelloWorld.c index 94f5b9fd77a..e5240b7d041 100644 --- a/example/scalalib/native/2-interop/native-src/HelloWorld.c +++ b/example/scalalib/native/2-interop/native-src/HelloWorld.c @@ -1,5 +1,15 @@ #include +#include +#include -void printString(const char *str) { - printf("%s\n", str); +char* reverseString(const char *str) { + int length = strlen(str); + char *reversed = (char*) malloc((length + 1) * sizeof(char)); + + for (int i = 0; i < length; i++) { + reversed[i] = str[length - i - 1]; + } + reversed[length] = '\0'; // Null-terminate the string + + return reversed; } diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala index 2cdf3a3b838..c47e0945ddd 100644 --- a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -1,10 +1,13 @@ package foo import scala.scalanative.unsafe._ +import scala.scalanative.libc._ object Main { def main(args: Array[String]): Unit = { print("Running HelloWorld function\n") - HelloWorld.printString(c"Hello world!!\n") + val input = c"Hello, World!!\n" + val reversed = HelloWorld.reverseString(input) + stdlib.printf(c"Reversed: %s", reversed) print("Done...\n") } } @@ -15,6 +18,5 @@ object Main { // Arbitrary object name object HelloWorld { // Name and signature of C function - def printString(str: CString): Unit = extern + def reverseString(str: CString): CString = extern } - diff --git a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala new file mode 100644 index 00000000000..e702501cadf --- /dev/null +++ b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala @@ -0,0 +1,28 @@ +package foo + +import utest._ +import scala.scalanative.unsafe._ +import scala.scalanative.libc._ + +object HelloWorldTest extends TestSuite { + val tests = Tests { + test("reverseString should reverse a C string correctly") { + Zone { implicit z => + val input = c"Hello world!" + val expected = c"!dlrow olleH" + + val reversed = HelloWorld.reverseString(input) + + // Check if the reversed string matches the expected result + assert(strcmp(reversed, expected) == 0) + } + } + } +} + +// Define the external module, the C library containing our function "reverseString" +@extern +@link("HelloWorld") +object HelloWorld { + def reverseString(str: CString): CString = extern +} diff --git a/example/scalalib/native/3-multi-module/bar/src/Bar.scala b/example/scalalib/native/3-multi-module/bar/src/Bar.scala new file mode 100644 index 00000000000..391b8d767b2 --- /dev/null +++ b/example/scalalib/native/3-multi-module/bar/src/Bar.scala @@ -0,0 +1,12 @@ +package bar +import scalatags.Text.all._ +object Bar { + def generateHtml(text: String) = { + val value = h1(text) + value.toString + } + + def main(args: Array[String]) = { + println("Bar.value: " + generateHtml(args(0))) + } +} diff --git a/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala new file mode 100644 index 00000000000..9525250b5a8 --- /dev/null +++ b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala @@ -0,0 +1,16 @@ +package bar +import utest._ +object BarTests extends TestSuite { + def tests = Tests { + test("simple") { + val result = Bar.generateHtml("hello") + assert(result == "

hello

") + result + } + test("escaping") { + val result = Bar.generateHtml("") + assert(result == "

<hello>

") + result + } + } +} diff --git a/example/scalalib/native/3-multi-module/build.mill b/example/scalalib/native/3-multi-module/build.mill new file mode 100644 index 00000000000..195306869b6 --- /dev/null +++ b/example/scalalib/native/3-multi-module/build.mill @@ -0,0 +1,116 @@ +//// SNIPPET:BUILD +package build +import mill._, scalalib._, scalanativelib._ + +trait MyModule extends ScalaNativeModule { + def scalaVersion = "2.13.11" + def scalaNativeVersion = "0.5.5" + object test extends ScalaNativeTests { + def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def testFramework = "utest.runner.Framework" + } +} + +object foo extends MyModule { + def moduleDeps = Seq(bar) + def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0") +} + +object bar extends MyModule { + def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2") +} +//// SNIPPET:END + +// This example contains a simple Mill build with two modules, `foo` and `bar`. +// We don't mark either module as top-level using `extends RootModule`, so +// running tasks needs to use the module name as the prefix e.g. `foo.run` or +// `bar.run`. You can define multiple modules the same way you define a single +// module, using `def moduleDeps` to define the relationship between them. +// +// Note that we split out the `test` submodule configuration common to both +// modules into a separate `trait MyModule`. This lets us avoid the need to +// copy-paste common settings, while still letting us define any per-module +// configuration such as `ivyDeps` specific to a particular module. +// +// The above builds expect the following project layout: +// +//// SNIPPET:TREE +// +// ---- +// build.mill +// foo/ +// src/ +// Foo.scala +// resources/ +// ... +// bar/ +// src/ +// Bar.scala +// resources/ +// ... +// out/ +// foo/ +// compile.json +// compile.dest/ +// ... +// bar/ +// compile.json +// compile.dest/ +// ... +// ---- +// +//// SNIPPET:END +// Typically, both source code and output files in Mill follow the module +// hierarchy, so e.g. input to the `foo` module lives in `foo/src/` and +// compiled output files live in `out/foo/compile.dest`. + +/** Usage + +> mill resolve __.run +foo.run +bar.run + +> mill foo.run --foo-text hello --bar-text world +Foo.value: hello +Bar.value:

world

+ +> mill bar.run world +Bar.value:

world

+ +> mill bar.test +... +...bar.BarTests...simple... +...bar.BarTests...escaping... + +*/ + +// Mill's evaluator will ensure that the modules are compiled in the right +// order, and recompiled as necessary when source code in each module changes. +// +// You can use wildcards and brace-expansion to select +// multiple targets at once or to shorten the path to deeply nested targets. If +// you provide optional target arguments and your wildcard or brace-expansion is +// resolved to multiple targets, the arguments will be applied to each of the +// targets. +// +// .Wildcards and brace-expansion +// |========================================================== +// | Wildcard | Function +// | `_` | matches a single segment of the target path +// | `__` | matches arbitrary segments of the target path +// | `{a,b}` | is equal to specifying two targets `a` and `b` +// |========================================================== +// +// +// You can use the `+` symbol to add another target with optional arguments. +// If you need to feed a `+` as argument to your target, you can mask it by +// preceding it with a backslash (`\`). +// +// === Examples +// +// `+mill foo._.compile+`:: Runs `compile` for all direct sub-modules of `foo` +// `+mill foo.__.test+` :: Runs `test` for all sub-modules of `foo` +// `+mill {foo,bar}.__.testCached+` :: Runs `testCached` for all sub-modules of `foo` and `bar` +// `+mill __.compile + foo.__.test+` :: Runs all `compile` targets and all tests under `foo`. +// +// diff --git a/example/scalalib/native/3-multi-module/foo/src/Foo.scala b/example/scalalib/native/3-multi-module/foo/src/Foo.scala new file mode 100644 index 00000000000..952d4d41dbc --- /dev/null +++ b/example/scalalib/native/3-multi-module/foo/src/Foo.scala @@ -0,0 +1,12 @@ +package foo +import mainargs.{main, ParserForMethods, arg} +object Foo { + @main + def main(@arg(name = "foo-text") fooText: String, + @arg(name = "bar-text") barText: String): Unit = { + println("Foo.value: " + fooText) + println("Bar.value: " + bar.Bar.generateHtml(barText)) + } + + def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) +} From 61f53b7e0d9052bff6a2bbbcebc31a4a3c2784bd Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 5 Oct 2024 02:09:13 +0100 Subject: [PATCH 15/37] add changes to 2-interop example --- example/scalalib/native/2-interop/build.mill | 2 +- .../native/2-interop/src/foo/HelloWorld.scala | 3 +-- .../2-interop/test/src/HelloWorldTests.scala | 20 +++++-------------- 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill index 29cfeb4b869..b0a43a1f729 100644 --- a/example/scalalib/native/2-interop/build.mill +++ b/example/scalalib/native/2-interop/build.mill @@ -20,7 +20,7 @@ object `package` extends RootModule with ScalaNativeModule { os.proc( "gcc", "-m64", "-shared", "-c", cSourceFiles, - "-o", T.dest.toString+output + "-o", T.dest.toString + "/output" ) .call() diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala index c47e0945ddd..27b7ae859d9 100644 --- a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -1,13 +1,12 @@ package foo import scala.scalanative.unsafe._ -import scala.scalanative.libc._ object Main { def main(args: Array[String]): Unit = { print("Running HelloWorld function\n") val input = c"Hello, World!!\n" val reversed = HelloWorld.reverseString(input) - stdlib.printf(c"Reversed: %s", reversed) + print(c"Reversed: %s", reversed) print("Done...\n") } } diff --git a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala index e702501cadf..75f63d0c1b7 100644 --- a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala +++ b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala @@ -2,27 +2,17 @@ package foo import utest._ import scala.scalanative.unsafe._ -import scala.scalanative.libc._ object HelloWorldTest extends TestSuite { val tests = Tests { test("reverseString should reverse a C string correctly") { - Zone { implicit z => - val input = c"Hello world!" - val expected = c"!dlrow olleH" + val input = c"Hello world!" + val expected = c"!dlrow olleH" - val reversed = HelloWorld.reverseString(input) + val reversed = HelloWorld.reverseString(input) - // Check if the reversed string matches the expected result - assert(strcmp(reversed, expected) == 0) - } + // Check if the reversed string matches the expected result + assert(strcmp(reversed, expected) == 0) } } } - -// Define the external module, the C library containing our function "reverseString" -@extern -@link("HelloWorld") -object HelloWorld { - def reverseString(str: CString): CString = extern -} From 9dc905309b88b7a0bb702f33c60afc54b13a9ffb Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 5 Oct 2024 13:50:49 +0100 Subject: [PATCH 16/37] update scala-native examples code --- .../native/2-interop/src/foo/HelloWorld.scala | 6 +- .../2-interop/test/src/HelloWorldTests.scala | 6 +- .../bar/native-src/HelloWorldBar.c | 7 + .../3-multi-module/bar/native-src/htm.c | 547 ++++++++++++++++ .../3-multi-module/bar/native-src/htmc.h | 586 ++++++++++++++++++ .../native/3-multi-module/bar/src/Bar.scala | 21 +- .../bar/test/src/BarTests.scala | 6 +- .../scalalib/native/3-multi-module/build.mill | 116 ---- .../foo/native-src/HelloWorldFoo.c | 7 + .../3-multi-module/foo/native-src/htm.c | 547 ++++++++++++++++ .../3-multi-module/foo/native-src/htmc.h | 586 ++++++++++++++++++ .../native/3-multi-module/foo/src/Foo.scala | 16 +- 12 files changed, 2318 insertions(+), 133 deletions(-) create mode 100644 example/scalalib/native/3-multi-module/bar/native-src/HelloWorldBar.c create mode 100644 example/scalalib/native/3-multi-module/bar/native-src/htm.c create mode 100644 example/scalalib/native/3-multi-module/bar/native-src/htmc.h delete mode 100644 example/scalalib/native/3-multi-module/build.mill create mode 100644 example/scalalib/native/3-multi-module/foo/native-src/HelloWorldFoo.c create mode 100644 example/scalalib/native/3-multi-module/foo/native-src/htm.c create mode 100644 example/scalalib/native/3-multi-module/foo/native-src/htmc.h diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala index 27b7ae859d9..39732d095c7 100644 --- a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -6,12 +6,12 @@ object Main { print("Running HelloWorld function\n") val input = c"Hello, World!!\n" val reversed = HelloWorld.reverseString(input) - print(c"Reversed: %s", reversed) - print("Done...\n") + println(c"Reversed: %s", reversed) + println("Done...") } } -// Define the external module, the C library containing our function "printString" +// Define the external module, the C library containing our function "reverseString" @extern @link("HelloWorld") // Arbitrary object name diff --git a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala index 75f63d0c1b7..049363003ae 100644 --- a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala +++ b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala @@ -6,13 +6,13 @@ import scala.scalanative.unsafe._ object HelloWorldTest extends TestSuite { val tests = Tests { test("reverseString should reverse a C string correctly") { - val input = c"Hello world!" val expected = c"!dlrow olleH" - val reversed = HelloWorld.reverseString(input) + val reversed = HelloWorld.reverseString(c"Hello World!") // Check if the reversed string matches the expected result - assert(strcmp(reversed, expected) == 0) + assert(reversed == expected) + result } } } diff --git a/example/scalalib/native/3-multi-module/bar/native-src/HelloWorldBar.c b/example/scalalib/native/3-multi-module/bar/native-src/HelloWorldBar.c new file mode 100644 index 00000000000..3fd48576930 --- /dev/null +++ b/example/scalalib/native/3-multi-module/bar/native-src/HelloWorldBar.c @@ -0,0 +1,7 @@ +#include "htmc.h" +#include + + +char* generateHtml(const char* text) { + return htmc(h1(text)); +} diff --git a/example/scalalib/native/3-multi-module/bar/native-src/htm.c b/example/scalalib/native/3-multi-module/bar/native-src/htm.c new file mode 100644 index 00000000000..298492900d9 --- /dev/null +++ b/example/scalalib/native/3-multi-module/bar/native-src/htm.c @@ -0,0 +1,547 @@ +#include "htmc.h" + +#ifndef HTMC_C +#define HTMC_C + +#include + +const char *htmc_tags[] = { +"a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "math", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr" +}; + +const uint32_t htmc_tag_lengths[] = { +sizeof("a") - 1, sizeof("abbr") - 1, sizeof("address") - 1, sizeof("area") - 1, sizeof("article") - 1, sizeof("aside") - 1, sizeof("audio") - 1, sizeof("b") - 1, sizeof("base") - 1, sizeof("bdi") - 1, sizeof("bdo") - 1, sizeof("blockquote") - 1, sizeof("body") - 1, sizeof("br") - 1, sizeof("button") - 1, sizeof("canvas") - 1, sizeof("caption") - 1, sizeof("cite") - 1, sizeof("code") - 1, sizeof("col") - 1, sizeof("colgroup") - 1, sizeof("data") - 1, sizeof("datalist") - 1, sizeof("dd") - 1, sizeof("del") - 1, sizeof("details") - 1, sizeof("dfn") - 1, sizeof("dialog") - 1, sizeof("div") - 1, sizeof("dl") - 1, sizeof("dt") - 1, sizeof("em") - 1, sizeof("embed") - 1, sizeof("fieldset") - 1, sizeof("figcaption") - 1, sizeof("figure") - 1, sizeof("footer") - 1, sizeof("form") - 1, sizeof("h1") - 1, sizeof("h2") - 1, sizeof("h3") - 1, sizeof("h4") - 1, sizeof("h5") - 1, sizeof("h6") - 1, sizeof("head") - 1, sizeof("header") - 1, sizeof("hgroup") - 1, sizeof("hr") - 1, sizeof("html") - 1, sizeof("i") - 1, sizeof("iframe") - 1, sizeof("img") - 1, sizeof("input") - 1, sizeof("ins") - 1, sizeof("kbd") - 1, sizeof("label") - 1, sizeof("legend") - 1, sizeof("li") - 1, sizeof("link") - 1, sizeof("main") - 1, sizeof("map") - 1, sizeof("mark") - 1, sizeof("math") - 1, sizeof("menu") - 1, sizeof("meta") - 1, sizeof("meter") - 1, sizeof("nav") - 1, sizeof("noscript") - 1, sizeof("object") - 1, sizeof("ol") - 1, sizeof("optgroup") - 1, sizeof("option") - 1, sizeof("output") - 1, sizeof("p") - 1, sizeof("param") - 1, sizeof("picture") - 1, sizeof("pre") - 1, sizeof("progress") - 1, sizeof("q") - 1, sizeof("rp") - 1, sizeof("rt") - 1, sizeof("ruby") - 1, sizeof("s") - 1, sizeof("samp") - 1, sizeof("script") - 1, sizeof("section") - 1, sizeof("select") - 1, sizeof("slot") - 1, sizeof("small") - 1, sizeof("source") - 1, sizeof("span") - 1, sizeof("strong") - 1, sizeof("style") - 1, sizeof("sub") - 1, sizeof("summary") - 1, sizeof("sup") - 1, sizeof("svg") - 1, sizeof("table") - 1, sizeof("tbody") - 1, sizeof("td") - 1, sizeof("template") - 1, sizeof("textarea") - 1, sizeof("tfoot") - 1, sizeof("th") - 1, sizeof("thead") - 1, sizeof("time") - 1, sizeof("title") - 1, sizeof("tr") - 1, sizeof("track") - 1, sizeof("u") - 1, sizeof("ul") - 1, sizeof("var") - 1, sizeof("video") - 1, sizeof("wbr") - 1 +}; + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx) +{ + size_t i = 0; + for( ; i != used_idx ; i++) + { + free(ha->buffers[i]); + } + for(i += 1; i < ha->nb ; i++) + { + free(ha->buffers[i]); + } + + free(ha->caps); + free(ha->sizes); + free(ha->unused); + free(ha->buffers); +} + +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer) +{ + size_t i; + for(i = 0; i < ha->nb ; i++) + { + if(buffer == ha->buffers[i]) + break; + } + return i; +} + +void htmc_grow_buffers(HtmcAllocations *ha) +{ + ha->buffers = realloc(ha->buffers, ha->nb * 2 * sizeof(char*)); + memset(ha->buffers + ha->nb, 0, ha->nb * sizeof(char*)); + + ha->caps = realloc(ha->caps, ha->nb * 2 * sizeof(size_t)); + memset(ha->caps + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->sizes = realloc(ha->sizes, ha->nb * 2 * sizeof(size_t)); + memset(ha->sizes + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->unused = realloc(ha->unused, ha->nb * 2 * sizeof(bool)); + memset(ha->unused + ha->nb, 1, ha->nb * sizeof(bool)); + + ha->nb *= 2; +} + +void htmc_set_unused(HtmcAllocations *ha, const char *str) +{ + size_t idx = htmc_find_buffer(ha, str); + ha->unused[idx] = true; +} + +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str) +{ + size_t found = htmc_find_buffer(ha, str); + if(found != ha->nb) + { + ha->unused[found] = true; + } +} + +size_t htmc_find_unused(const HtmcAllocations *ha) +{ + size_t first_unused; + + for(first_unused = 0 ; first_unused < ha->nb ; first_unused++) + { + if(ha->unused[first_unused]) + { + goto find_unused_and_alloced; + } + } + + // no unused buffers were found + return first_unused; + + find_unused_and_alloced: + for(size_t i = first_unused ; i < ha->nb ; i++) + { + if(ha->unused[i] && ha->caps[i] != 0) + { + return i; + } + } + + return first_unused; +} + +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_cap) +{ + size_t unused_buffer_idx = htmc_find_unused(ha); + if(unused_buffer_idx == ha->nb) + { + unused_buffer_idx = ha->nb; + htmc_grow_buffers(ha); + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = calloc(with_cap, sizeof(char)); + ha->caps[ unused_buffer_idx ] = with_cap; + } + else if(with_cap > ha->caps[ unused_buffer_idx ]) + { + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = realloc(*unused_buffer, with_cap); + ha->caps[ unused_buffer_idx ] = with_cap; + } + + ha->unused[ unused_buffer_idx ] = false; + + return unused_buffer_idx; +} + +size_t htmc_concat_strings_into(HtmcAllocations *ha, HtmcStrsArr strs, size_t unused_buffer_idx) +{ + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + + // if no strings were provided, return an empty string + if(strs.nb == 0) + { + if(*cap == 0) + { + *unused_buffer = calloc(1, sizeof(char)); + } + **unused_buffer = '\0'; + return unused_buffer_idx; + } + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(next_str); + if(*size + next_len >= *cap) + { + *cap = (next_len + *cap) * 2; + *unused_buffer = realloc(*unused_buffer, *cap); + } + memcpy(*unused_buffer + *size, next_str, next_len); + + htmc_set_unused_if_alloced(ha, next_str); + + *size = *size + next_len; + } + + (*unused_buffer)[*size] = '\0'; + return unused_buffer_idx; +} + +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs) +{ + size_t unused_buffer_idx = htmc_get_unused(ha, 16); + return htmc_concat_strings_into(ha, strs, unused_buffer_idx); +} + +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t append_to, HtmcStrsArr strs) +{ + char **append_to_str = &ha->buffers[ append_to ]; + size_t *len = &ha->sizes[ append_to ]; + size_t *cap = &ha->caps [ append_to ]; + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(strs.arr[i]); + bool is_copy = (next_str == *append_to_str); + + if(*len + next_len >= *cap) + { + htmc_gurantee_cap(append_to_str, cap, (next_len + *cap) * 2); + } + + // if it's a copy of *append_to_str that means it might have been invalidate with the htmc_gurantee_cap + if(is_copy) + { + memmove(*append_to_str + *len, *append_to_str, next_len); + *len += next_len; + } + else + { + memmove(*append_to_str + *len, next_str, next_len); + *len += next_len; + + htmc_set_unused_if_alloced(ha, next_str); + } + } + + (*append_to_str)[*len] = '\0'; +} + +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **between_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + htmc_gurantee_cap(between_ptr, cap, needed_cap); + + memmove(*between_ptr + 1 + tag_len + 1, *between_ptr, between_len); + + memcpy(*between_ptr, "<", 1); + memcpy(*between_ptr + 1, tag, tag_len); + memcpy(*between_ptr + 1 + tag_len, ">", 1); + memcpy(*between_ptr + 1 + tag_len + 1 + between_len, "", 1); + (*between_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *between_ptr; +} + +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, needed_cap); + const char *between = ha->buffers[ str_idx ]; + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t size = 0; + + memcpy(*unused_buffer, "<", 1); + size += 1; + + memcpy(*unused_buffer + size, tag, tag_len); + size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*cap <= size + attr_len + 1) // 1 for the spaces between each attribute + { + *unused_buffer = realloc(*unused_buffer, size + (attr_len * 2)); + *cap = size + (attr_len * 2); + } + memcpy(*unused_buffer + size, " ", 1); + size += 1; + memcpy(*unused_buffer + size, attrs.arr[i], attr_len); + size += attr_len; + } + + if(*cap <= size + 1 + between_len + 2 + tag_len + 1) + { + *unused_buffer = realloc(*unused_buffer, size + 1 + between_len + 2 + tag_len + 1 + 1); + *cap = size + 1 + between_len + 2 + tag_len + 1 + 1; + } + + memcpy(*unused_buffer + size, ">", 1); + size += 1; + + memcpy(*unused_buffer + size, between, between_len); + size += between_len; + + memcpy(*unused_buffer + size, "", 1); + size += 1; + + (*unused_buffer)[size] = '\0'; + + ha->sizes[ unused_buffer_idx ] = size; + ha->unused[ str_idx ] = true; + + return *unused_buffer; +} + +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id) +{ + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + memcpy(*unused_buffer + 1, tag, tag_len); + memcpy(*unused_buffer + 1 + tag_len, ">", 1); + (*unused_buffer)[ 1 + tag_len + 1 ] = '\0'; + + ha->sizes[ unused_buffer_idx ] = tag_len + 2; + + return *unused_buffer; +} + +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy) +{ + (void)dummy; + + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + size_t *cap = &ha->caps[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + *size += 1; + + memcpy(*unused_buffer + 1, tag, tag_len); + *size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*size + attr_len + 1 >= *cap) + { + *unused_buffer = realloc(*unused_buffer, (*size + attr_len) * 2); + *cap = (*size + attr_len) * 2; + } + + memcpy(*unused_buffer + *size, " ", 1); + *size += 1; + + memcpy(*unused_buffer + *size, attrs.arr[i], attr_len); + *size += attr_len; + } + + memcpy(*unused_buffer + *size, ">", 2); // 2 for the '\0' + *size += 1; + + return *unused_buffer; +} + +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + const size_t combined_strlen = ha->sizes[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + if(combined_strlen * nb >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, combined_strlen * nb + 1); + *cap = combined_strlen * nb + 1; + } + + for(uint32_t i = 1 ; i < nb ; i++) + { + memcpy(*combined_str_ptr + *size, *combined_str_ptr, combined_strlen); + *size += combined_strlen; + } + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +// should mod take idx? maybe leave that as the re-entrant version with void*, and let user handle idx +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i, arg); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t len = ha->sizes[ str_idx ]; + size_t unused_buffer_idx = htmc_get_unused(ha, len + 1); + char **dup = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*dup, ha->buffers[ str_idx ], len + 1); + + ha->sizes[ unused_buffer_idx ] = len; + + return unused_buffer_idx; +} + +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t idx = htmc_strdup(ha, str_idx); + return ha->buffers[ idx ]; +} + +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + va_list args_copy1; + va_copy(args_copy1, args); + + int str_len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + + size_t unused_buffer_idx = htmc_get_unused(ha, str_len + 1); + char **unused = &ha->buffers[ unused_buffer_idx ]; + ha->sizes[ unused_buffer_idx ] = str_len; + + vsnprintf(*unused, str_len + 1, fmt, args_copy1); + va_end(args_copy1); + + htmc_set_unused_if_alloced(ha, fmt); + + return *unused; +} + +// TODO check in the string for '--' and report error +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **buffer_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t comment_start_len = 4; + const size_t comment_end_len = 3; + const size_t needed_cap = comment_start_len + between_len + comment_end_len + 1; + + htmc_gurantee_cap(buffer_ptr, cap, needed_cap); + + memmove(*buffer_ptr + comment_start_len, *buffer_ptr, between_len); + + memcpy(*buffer_ptr, "", 3); + (*buffer_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *buffer_ptr; +} + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap) +{ + if(*cap < new_cap) + { + *buffer = realloc(*buffer, new_cap); + *cap = new_cap; + } +} + +#endif /* HTMC_C */ diff --git a/example/scalalib/native/3-multi-module/bar/native-src/htmc.h b/example/scalalib/native/3-multi-module/bar/native-src/htmc.h new file mode 100644 index 00000000000..c7be0829643 --- /dev/null +++ b/example/scalalib/native/3-multi-module/bar/native-src/htmc.h @@ -0,0 +1,586 @@ +#ifndef HTMC_H +#define HTMC_H + +#include +#include +#include +#include +#include +#include + +typedef struct +{ + size_t nb; + bool *unused; + size_t *caps; + size_t *sizes; + char **buffers; +} HtmcAllocations; + +typedef struct +{ + char **arr; + size_t nb; +} HtmcStrsArr; + +#define htmc(...) \ +({ \ + const size_t init_cap = 4; \ + HtmcAllocations htmc_ha = { \ + .nb = init_cap, \ + .buffers = calloc(init_cap, sizeof(char*)), \ + .caps = calloc(init_cap, sizeof(size_t)), \ + .sizes = calloc(init_cap, sizeof(size_t)), \ + .unused = malloc(init_cap * sizeof(bool)), \ + }; \ + memset(htmc_ha.unused, 1, init_cap * sizeof(bool)); \ + size_t ret_idx = htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__)); \ + char *ret = htmc_ha.buffers[ ret_idx ]; \ + htmc_cleanup_unused_buffers(&htmc_ha, ret_idx); \ + ret; \ +}) + +#define htmc_strsarr(...) (HtmcStrsArr){.arr=(char*[]){__VA_ARGS__}, .nb=sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)} + +#define htmc_repeat(nb, ...) htmc_repeat_(&htmc_ha, nb, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify(nb, mod, ...) htmc_repeat_modify_(&htmc_ha, nb, mod, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify_r(nb, mod, ctx, ...) htmc_repeat_modify_r_(&htmc_ha, nb, mod, ctx, htmc_strsarr(__VA_ARGS__)) + +#define htmc_fmt(fmt, ...) htmc_fmt_(&htmc_ha, fmt, ##__VA_ARGS__) + +#define htmc_ccode(...) \ +({ \ + size_t htmc_ccode_yielded_idx = htmc_get_unused(&htmc_ha, 16); \ + htmc_ha.sizes[ htmc_ccode_yielded_idx ] = 0; \ + htmc_ha.buffers[ htmc_ccode_yielded_idx ][0] = '\0'; \ + __VA_ARGS__ \ + char *htmc_ccode_yielded = htmc_ha.buffers[ htmc_ccode_yielded_idx ]; \ + htmc_ccode_yielded; \ +}) +#define htmc_yield(...) htmc_append_to_buffer_idx(&htmc_ha, htmc_ccode_yielded_idx, htmc_strsarr(__VA_ARGS__)) +#define htmc_yielded htmc_ha.buffers[ htmc_ccode_yielded_idx ] +#define htmc_yielded_len htmc_ha.sizes[ htmc_ccode_yielded_idx ] + +#define htmc_attr_(...) \ +htmc_strsarr(__VA_ARGS__))) + +#define htmc_attr(tag, ...) \ +_Generic(&(char[htmc_is_single_tag(htmc_id_##tag) + 1]){ 0 } , \ + char(*)[1]: htmc_surround_by_tag_with_attrs, \ + char(*)[2]: htmc_make_tag_with_attrs \ +)(&htmc_ha, htmc_id_##tag, htmc_strsarr(__VA_ARGS__), htmc_concat_strings(&htmc_ha, htmc_attr_ + +#define htmc_strlit(...) #__VA_ARGS__ + +#define htmc_is_single_tag(id) \ +(id == (htmc_id_area || htmc_id_base || htmc_id_br || htmc_id_col || htmc_id_embed || htmc_id_hr || htmc_id_img || htmc_id_input || htmc_id_link || htmc_id_meta || htmc_id_param || htmc_id_source || htmc_id_track || htmc_id_wbr)) + +#define htmc_doctypehtml ("") + +#define htmc_comment(...) htmc_comment_(&htmc_ha, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that need a closing tag: +#define htmc_a(...) htmc_surround_by_tag(&htmc_ha, 0, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_abbr(...) htmc_surround_by_tag(&htmc_ha, 1, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_address(...) htmc_surround_by_tag(&htmc_ha, 2, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_article(...) htmc_surround_by_tag(&htmc_ha, 4, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_aside(...) htmc_surround_by_tag(&htmc_ha, 5, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_audio(...) htmc_surround_by_tag(&htmc_ha, 6, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_b(...) htmc_surround_by_tag(&htmc_ha, 7, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdi(...) htmc_surround_by_tag(&htmc_ha, 9, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdo(...) htmc_surround_by_tag(&htmc_ha, 10, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_blockquote(...) htmc_surround_by_tag(&htmc_ha, 11, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_body(...) htmc_surround_by_tag(&htmc_ha, 12, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_button(...) htmc_surround_by_tag(&htmc_ha, 14, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_canvas(...) htmc_surround_by_tag(&htmc_ha, 15, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_caption(...) htmc_surround_by_tag(&htmc_ha, 16, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_cite(...) htmc_surround_by_tag(&htmc_ha, 17, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_code(...) htmc_surround_by_tag(&htmc_ha, 18, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_colgroup(...) htmc_surround_by_tag(&htmc_ha, 20, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_data(...) htmc_surround_by_tag(&htmc_ha, 21, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_datalist(...) htmc_surround_by_tag(&htmc_ha, 22, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dd(...) htmc_surround_by_tag(&htmc_ha, 23, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_del(...) htmc_surround_by_tag(&htmc_ha, 24, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_details(...) htmc_surround_by_tag(&htmc_ha, 25, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dfn(...) htmc_surround_by_tag(&htmc_ha, 26, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dialog(...) htmc_surround_by_tag(&htmc_ha, 27, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_div(...) htmc_surround_by_tag(&htmc_ha, 28, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dl(...) htmc_surround_by_tag(&htmc_ha, 29, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dt(...) htmc_surround_by_tag(&htmc_ha, 30, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_em(...) htmc_surround_by_tag(&htmc_ha, 31, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_fieldset(...) htmc_surround_by_tag(&htmc_ha, 33, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figcaption(...) htmc_surround_by_tag(&htmc_ha, 34, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figure(...) htmc_surround_by_tag(&htmc_ha, 35, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_footer(...) htmc_surround_by_tag(&htmc_ha, 36, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_form(...) htmc_surround_by_tag(&htmc_ha, 37, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h1(...) htmc_surround_by_tag(&htmc_ha, 38, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h2(...) htmc_surround_by_tag(&htmc_ha, 39, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h3(...) htmc_surround_by_tag(&htmc_ha, 40, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h4(...) htmc_surround_by_tag(&htmc_ha, 41, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h5(...) htmc_surround_by_tag(&htmc_ha, 42, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h6(...) htmc_surround_by_tag(&htmc_ha, 43, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_head(...) htmc_surround_by_tag(&htmc_ha, 44, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_header(...) htmc_surround_by_tag(&htmc_ha, 45, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_hgroup(...) htmc_surround_by_tag(&htmc_ha, 46, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_html(...) htmc_surround_by_tag(&htmc_ha, 48, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_i(...) htmc_surround_by_tag(&htmc_ha, 49, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_iframe(...) htmc_surround_by_tag(&htmc_ha, 50, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ins(...) htmc_surround_by_tag(&htmc_ha, 53, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_kbd(...) htmc_surround_by_tag(&htmc_ha, 54, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_label(...) htmc_surround_by_tag(&htmc_ha, 55, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_legend(...) htmc_surround_by_tag(&htmc_ha, 56, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_li(...) htmc_surround_by_tag(&htmc_ha, 57, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_main(...) htmc_surround_by_tag(&htmc_ha, 59, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_map(...) htmc_surround_by_tag(&htmc_ha, 60, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_mark(...) htmc_surround_by_tag(&htmc_ha, 61, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_math(...) htmc_surround_by_tag(&htmc_ha, 62, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_menu(...) htmc_surround_by_tag(&htmc_ha, 63, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_meter(...) htmc_surround_by_tag(&htmc_ha, 65, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_nav(...) htmc_surround_by_tag(&htmc_ha, 66, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_noscript(...) htmc_surround_by_tag(&htmc_ha, 67, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_object(...) htmc_surround_by_tag(&htmc_ha, 68, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ol(...) htmc_surround_by_tag(&htmc_ha, 69, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_optgroup(...) htmc_surround_by_tag(&htmc_ha, 70, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_option(...) htmc_surround_by_tag(&htmc_ha, 71, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_output(...) htmc_surround_by_tag(&htmc_ha, 72, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_p(...) htmc_surround_by_tag(&htmc_ha, 73, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_picture(...) htmc_surround_by_tag(&htmc_ha, 75, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_pre(...) htmc_surround_by_tag(&htmc_ha, 76, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_progress(...) htmc_surround_by_tag(&htmc_ha, 77, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_q(...) htmc_surround_by_tag(&htmc_ha, 78, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rp(...) htmc_surround_by_tag(&htmc_ha, 79, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rt(...) htmc_surround_by_tag(&htmc_ha, 80, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ruby(...) htmc_surround_by_tag(&htmc_ha, 81, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_s(...) htmc_surround_by_tag(&htmc_ha, 82, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_samp(...) htmc_surround_by_tag(&htmc_ha, 83, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_script(...) htmc_surround_by_tag(&htmc_ha, 84, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_section(...) htmc_surround_by_tag(&htmc_ha, 85, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_select(...) htmc_surround_by_tag(&htmc_ha, 86, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_slot(...) htmc_surround_by_tag(&htmc_ha, 87, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_small(...) htmc_surround_by_tag(&htmc_ha, 88, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_span(...) htmc_surround_by_tag(&htmc_ha, 90, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_strong(...) htmc_surround_by_tag(&htmc_ha, 91, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_style(...) htmc_surround_by_tag(&htmc_ha, 92, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sub(...) htmc_surround_by_tag(&htmc_ha, 93, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_summary(...) htmc_surround_by_tag(&htmc_ha, 94, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sup(...) htmc_surround_by_tag(&htmc_ha, 95, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_svg(...) htmc_surround_by_tag(&htmc_ha, 96, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_table(...) htmc_surround_by_tag(&htmc_ha, 97, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tbody(...) htmc_surround_by_tag(&htmc_ha, 98, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_td(...) htmc_surround_by_tag(&htmc_ha, 99, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_template(...) htmc_surround_by_tag(&htmc_ha, 100, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_textarea(...) htmc_surround_by_tag(&htmc_ha, 101, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tfoot(...) htmc_surround_by_tag(&htmc_ha, 102, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_th(...) htmc_surround_by_tag(&htmc_ha, 103, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_thead(...) htmc_surround_by_tag(&htmc_ha, 104, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_time(...) htmc_surround_by_tag(&htmc_ha, 105, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_title(...) htmc_surround_by_tag(&htmc_ha, 106, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tr(...) htmc_surround_by_tag(&htmc_ha, 107, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_u(...) htmc_surround_by_tag(&htmc_ha, 109, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ul(...) htmc_surround_by_tag(&htmc_ha, 110, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_var(...) htmc_surround_by_tag(&htmc_ha, 111, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_video(...) htmc_surround_by_tag(&htmc_ha, 112, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that don't terminate +#define htmc_area(...) htmc_make_tag_with_attrs(&htmc_ha, 3, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_base(...) htmc_make_tag_with_attrs(&htmc_ha, 8, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_br(...) htmc_make_tag_with_attrs(&htmc_ha, 13, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_col(...) htmc_make_tag_with_attrs(&htmc_ha, 19, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_embed(...) htmc_make_tag_with_attrs(&htmc_ha, 32, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_hr(...) htmc_make_tag_with_attrs(&htmc_ha, 47, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_img(...) htmc_make_tag_with_attrs(&htmc_ha, 51, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_input(...) htmc_make_tag_with_attrs(&htmc_ha, 52, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_link(...) htmc_make_tag_with_attrs(&htmc_ha, 58, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_meta(...) htmc_make_tag_with_attrs(&htmc_ha, 64, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_param(...) htmc_make_tag_with_attrs(&htmc_ha, 74, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_source(...) htmc_make_tag_with_attrs(&htmc_ha, 89, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_track(...) htmc_make_tag_with_attrs(&htmc_ha, 108, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_wbr(...) htmc_make_tag_with_attrs(&htmc_ha, 113, htmc_strsarr(__VA_ARGS__), NULL) + +#define htmc_id_a 0 +#define htmc_id_abbr 1 +#define htmc_id_address 2 +#define htmc_id_area 3 +#define htmc_id_article 4 +#define htmc_id_aside 5 +#define htmc_id_audio 6 +#define htmc_id_b 7 +#define htmc_id_base 8 +#define htmc_id_bdi 9 +#define htmc_id_bdo 10 +#define htmc_id_blockquote 11 +#define htmc_id_body 12 +#define htmc_id_br 13 +#define htmc_id_button 14 +#define htmc_id_canvas 15 +#define htmc_id_caption 16 +#define htmc_id_cite 17 +#define htmc_id_code 18 +#define htmc_id_col 19 +#define htmc_id_colgroup 20 +#define htmc_id_data 21 +#define htmc_id_datalist 22 +#define htmc_id_dd 23 +#define htmc_id_del 24 +#define htmc_id_details 25 +#define htmc_id_dfn 26 +#define htmc_id_dialog 27 +#define htmc_id_div 28 +#define htmc_id_dl 29 +#define htmc_id_dt 30 +#define htmc_id_em 31 +#define htmc_id_embed 32 +#define htmc_id_fieldset 33 +#define htmc_id_figcaption 34 +#define htmc_id_figure 35 +#define htmc_id_footer 36 +#define htmc_id_form 37 +#define htmc_id_h1 38 +#define htmc_id_h2 39 +#define htmc_id_h3 40 +#define htmc_id_h4 41 +#define htmc_id_h5 42 +#define htmc_id_h6 43 +#define htmc_id_head 44 +#define htmc_id_header 45 +#define htmc_id_hgroup 46 +#define htmc_id_hr 47 +#define htmc_id_html 48 +#define htmc_id_i 49 +#define htmc_id_iframe 50 +#define htmc_id_img 51 +#define htmc_id_input 52 +#define htmc_id_ins 53 +#define htmc_id_kbd 54 +#define htmc_id_label 55 +#define htmc_id_legend 56 +#define htmc_id_li 57 +#define htmc_id_link 58 +#define htmc_id_main 59 +#define htmc_id_map 60 +#define htmc_id_mark 61 +#define htmc_id_math 62 +#define htmc_id_menu 63 +#define htmc_id_meta 64 +#define htmc_id_meter 65 +#define htmc_id_nav 66 +#define htmc_id_noscript 67 +#define htmc_id_object 68 +#define htmc_id_ol 69 +#define htmc_id_optgroup 70 +#define htmc_id_option 71 +#define htmc_id_output 72 +#define htmc_id_p 73 +#define htmc_id_param 74 +#define htmc_id_picture 75 +#define htmc_id_pre 76 +#define htmc_id_progress 77 +#define htmc_id_q 78 +#define htmc_id_rp 79 +#define htmc_id_rt 80 +#define htmc_id_ruby 81 +#define htmc_id_s 82 +#define htmc_id_samp 83 +#define htmc_id_script 84 +#define htmc_id_section 85 +#define htmc_id_select 86 +#define htmc_id_slot 87 +#define htmc_id_small 88 +#define htmc_id_source 89 +#define htmc_id_span 90 +#define htmc_id_strong 91 +#define htmc_id_style 92 +#define htmc_id_sub 93 +#define htmc_id_summary 94 +#define htmc_id_sup 95 +#define htmc_id_svg 96 +#define htmc_id_table 97 +#define htmc_id_tbody 98 +#define htmc_id_td 99 +#define htmc_id_template 100 +#define htmc_id_textarea 101 +#define htmc_id_tfoot 102 +#define htmc_id_th 103 +#define htmc_id_thead 104 +#define htmc_id_time 105 +#define htmc_id_title 106 +#define htmc_id_tr 107 +#define htmc_id_track 108 +#define htmc_id_u 109 +#define htmc_id_ul 110 +#define htmc_id_var 111 +#define htmc_id_video 112 +#define htmc_id_wbr 113 + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx); +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer); +void htmc_grow_buffers(HtmcAllocations *ha); +void htmc_set_unused(HtmcAllocations *ha, const char *str); +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str); +size_t htmc_find_unused(const HtmcAllocations *ha); +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_size); +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs); +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx); +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx); +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id); +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy); +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs); +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs); +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs); +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...); +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t buffer_idx, HtmcStrsArr strs); +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx); + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap); + +#endif + +#ifdef HTMC_PREFIX + +#undef HTMC_PREFIX + +#undef doctypehtml + +#undef comment + +#undef a +#undef abbr +#undef address +#undef area +#undef article +#undef aside +#undef audio +#undef b +#undef base +#undef bdi +#undef bdo +#undef blockquote +#undef body +#undef br +#undef button +#undef canvas +#undef caption +#undef cite +#undef code +#undef col +#undef colgroup +#undef data +#undef datalist +#undef dd +#undef del +#undef details +#undef dfn +#undef dialog +#undef div +#undef dl +#undef dt +#undef em +#undef embed +#undef fieldset +#undef figcaption +#undef figure +#undef footer +#undef form +#undef h1 +#undef h2 +#undef h3 +#undef h4 +#undef h5 +#undef h6 +#undef head +#undef header +#undef hgroup +#undef hr +#undef html +#undef i +#undef iframe +#undef img +#undef input +#undef ins +#undef kbd +#undef label +#undef legend +#undef li +#undef link +#undef map +#undef mark +#undef math +#undef menu +#undef meta +#undef meter +#undef nav +#undef noscript +#undef object +#undef ol +#undef optgroup +#undef option +#undef output +#undef p +#undef param +#undef picture +#undef pre +#undef progress +#undef q +#undef rp +#undef rt +#undef ruby +#undef s +#undef samp +#undef script +#undef section +#undef select +#undef slot +#undef small +#undef source +#undef span +#undef strong +#undef style +#undef sub +#undef summary +#undef sup +#undef svg +#undef table +#undef tbody +#undef td +#undef template +#undef textarea +#undef tfoot +#undef th +#undef thead +#undef time +#undef title +#undef tr +#undef track +#undef u +#undef ul +#undef var +#undef video +#undef wbr + +#undef attr + +#else + +#define doctypehtml htmc_doctypehtml + +#define comment htmc_comment + +#define a(...) htmc_a(__VA_ARGS__) +#define abbr(...) htmc_abbr(__VA_ARGS__) +#define address(...) htmc_address(__VA_ARGS__) +#define area(...) htmc_area(__VA_ARGS__) +#define article(...) htmc_article(__VA_ARGS__) +#define aside(...) htmc_aside(__VA_ARGS__) +#define audio(...) htmc_audio(__VA_ARGS__) +#define b(...) htmc_b(__VA_ARGS__) +#define base(...) htmc_base(__VA_ARGS__) +#define bdi(...) htmc_bdi(__VA_ARGS__) +#define bdo(...) htmc_bdo(__VA_ARGS__) +#define blockquote(...) htmc_blockquote(__VA_ARGS__) +#define body(...) htmc_body(__VA_ARGS__) +#define br(...) htmc_br(__VA_ARGS__) +#define button(...) htmc_button(__VA_ARGS__) +#define canvas(...) htmc_canvas(__VA_ARGS__) +#define caption(...) htmc_caption(__VA_ARGS__) +#define cite(...) htmc_cite(__VA_ARGS__) +#define code(...) htmc_code(__VA_ARGS__) +#define col(...) htmc_col(__VA_ARGS__) +#define colgroup(...) htmc_colgroup(__VA_ARGS__) +#define data(...) htmc_data(__VA_ARGS__) +#define datalist(...) htmc_datalist(__VA_ARGS__) +#define dd(...) htmc_dd(__VA_ARGS__) +#define del(...) htmc_del(__VA_ARGS__) +#define details(...) htmc_details(__VA_ARGS__) +#define dfn(...) htmc_dfn(__VA_ARGS__) +#define dialog(...) htmc_dialog(__VA_ARGS__) +#define div(...) htmc_div(__VA_ARGS__) +#define dl(...) htmc_dl(__VA_ARGS__) +#define dt(...) htmc_dt(__VA_ARGS__) +#define em(...) htmc_em(__VA_ARGS__) +#define embed(...) htmc_embed(__VA_ARGS__) +#define fieldset(...) htmc_fieldset(__VA_ARGS__) +#define figcaption(...) htmc_figcaption(__VA_ARGS__) +#define figure(...) htmc_figure(__VA_ARGS__) +#define footer(...) htmc_footer(__VA_ARGS__) +#define form(...) htmc_form(__VA_ARGS__) +#define h1(...) htmc_h1(__VA_ARGS__) +#define h2(...) htmc_h2(__VA_ARGS__) +#define h3(...) htmc_h3(__VA_ARGS__) +#define h4(...) htmc_h4(__VA_ARGS__) +#define h5(...) htmc_h5(__VA_ARGS__) +#define h6(...) htmc_h6(__VA_ARGS__) +#define head(...) htmc_head(__VA_ARGS__) +#define header(...) htmc_header(__VA_ARGS__) +#define hgroup(...) htmc_hgroup(__VA_ARGS__) +#define hr(...) htmc_hr(__VA_ARGS__) +#define html(...) htmc_html(__VA_ARGS__) +#define i(...) htmc_i(__VA_ARGS__) +#define iframe(...) htmc_iframe(__VA_ARGS__) +#define img(...) htmc_img(__VA_ARGS__) +#define input(...) htmc_input(__VA_ARGS__) +#define ins(...) htmc_ins(__VA_ARGS__) +#define kbd(...) htmc_kbd(__VA_ARGS__) +#define label(...) htmc_label(__VA_ARGS__) +#define legend(...) htmc_legend(__VA_ARGS__) +#define li(...) htmc_li(__VA_ARGS__) +#define link(...) htmc_link(__VA_ARGS__) +#define map(...) htmc_map(__VA_ARGS__) +#define mark(...) htmc_mark(__VA_ARGS__) +#define math(...) htmc_math(__VA_ARGS__) +#define menu(...) htmc_menu(__VA_ARGS__) +#define meta(...) htmc_meta(__VA_ARGS__) +#define meter(...) htmc_meter(__VA_ARGS__) +#define nav(...) htmc_nav(__VA_ARGS__) +#define noscript(...) htmc_noscript(__VA_ARGS__) +#define object(...) htmc_object(__VA_ARGS__) +#define ol(...) htmc_ol(__VA_ARGS__) +#define optgroup(...) htmc_optgroup(__VA_ARGS__) +#define option(...) htmc_option(__VA_ARGS__) +#define output(...) htmc_output(__VA_ARGS__) +#define p(...) htmc_p(__VA_ARGS__) +#define param(...) htmc_param(__VA_ARGS__) +#define picture(...) htmc_picture(__VA_ARGS__) +#define pre(...) htmc_pre(__VA_ARGS__) +#define progress(...) htmc_progress(__VA_ARGS__) +#define q(...) htmc_q(__VA_ARGS__) +#define rp(...) htmc_rp(__VA_ARGS__) +#define rt(...) htmc_rt(__VA_ARGS__) +#define ruby(...) htmc_ruby(__VA_ARGS__) +#define s(...) htmc_s(__VA_ARGS__) +#define samp(...) htmc_samp(__VA_ARGS__) +#define script(...) htmc_script(__VA_ARGS__) +#define section(...) htmc_section(__VA_ARGS__) +#define select(...) htmc_select(__VA_ARGS__) +#define slot(...) htmc_slot(__VA_ARGS__) +#define small(...) htmc_small(__VA_ARGS__) +#define source(...) htmc_source(__VA_ARGS__) +#define span(...) htmc_span(__VA_ARGS__) +#define strong(...) htmc_strong(__VA_ARGS__) +#define style(...) htmc_style(__VA_ARGS__) +#define sub(...) htmc_sub(__VA_ARGS__) +#define summary(...) htmc_summary(__VA_ARGS__) +#define sup(...) htmc_sup(__VA_ARGS__) +#define svg(...) htmc_svg(__VA_ARGS__) +#define table(...) htmc_table(__VA_ARGS__) +#define tbody(...) htmc_tbody(__VA_ARGS__) +#define td(...) htmc_td(__VA_ARGS__) +#define template(...) htmc_template(__VA_ARGS__) +#define textarea(...) htmc_textarea(__VA_ARGS__) +#define tfoot(...) htmc_tfoot(__VA_ARGS__) +#define th(...) htmc_th(__VA_ARGS__) +#define thead(...) htmc_thead(__VA_ARGS__) +#define time(...) htmc_time(__VA_ARGS__) +#define title(...) htmc_title(__VA_ARGS__) +#define tr(...) htmc_tr(__VA_ARGS__) +#define track(...) htmc_track(__VA_ARGS__) +#define u(...) htmc_u(__VA_ARGS__) +#define ul(...) htmc_ul(__VA_ARGS__) +#define var(...) htmc_var(__VA_ARGS__) +#define video(...) htmc_video(__VA_ARGS__) +#define wbr(...) htmc_wbr(__VA_ARGS__) + +#define attr(...) htmc_attr(__VA_ARGS__) + +#endif diff --git a/example/scalalib/native/3-multi-module/bar/src/Bar.scala b/example/scalalib/native/3-multi-module/bar/src/Bar.scala index 391b8d767b2..c066d709757 100644 --- a/example/scalalib/native/3-multi-module/bar/src/Bar.scala +++ b/example/scalalib/native/3-multi-module/bar/src/Bar.scala @@ -1,12 +1,21 @@ package bar import scalatags.Text.all._ +import scala.scalanative.unsafe._ + object Bar { - def generateHtml(text: String) = { - val value = h1(text) - value.toString + def main(args: Array[String]): Unit = { + println("Running HelloWorld function") + val result = HelloWorldBar.generateHtml(args(0)) + println(("Bar value:" + result) + println("Done...) } +} - def main(args: Array[String]) = { - println("Bar.value: " + generateHtml(args(0))) - } +// Define the external module, the C library containing our function "generateHtml" +@extern +@link("HelloWorldBar") +// Arbitrary object name +object HelloWorldBar { + // Name and signature of C function + def generateHtml(str: CString): CString = extern } diff --git a/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala index 9525250b5a8..4033fdd973b 100644 --- a/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala +++ b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala @@ -1,14 +1,16 @@ package bar import utest._ +import scala.scalanative.unsafe._ + object BarTests extends TestSuite { def tests = Tests { test("simple") { - val result = Bar.generateHtml("hello") + val result = Bar.generateHtml(c"hello") assert(result == "

hello

") result } test("escaping") { - val result = Bar.generateHtml("") + val result = Bar.generateHtml(c"") assert(result == "

<hello>

") result } diff --git a/example/scalalib/native/3-multi-module/build.mill b/example/scalalib/native/3-multi-module/build.mill deleted file mode 100644 index 195306869b6..00000000000 --- a/example/scalalib/native/3-multi-module/build.mill +++ /dev/null @@ -1,116 +0,0 @@ -//// SNIPPET:BUILD -package build -import mill._, scalalib._, scalanativelib._ - -trait MyModule extends ScalaNativeModule { - def scalaVersion = "2.13.11" - def scalaNativeVersion = "0.5.5" - object test extends ScalaNativeTests { - def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") - def testFramework = "utest.runner.Framework" - } -} - -object foo extends MyModule { - def moduleDeps = Seq(bar) - def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0") -} - -object bar extends MyModule { - def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2") -} -//// SNIPPET:END - -// This example contains a simple Mill build with two modules, `foo` and `bar`. -// We don't mark either module as top-level using `extends RootModule`, so -// running tasks needs to use the module name as the prefix e.g. `foo.run` or -// `bar.run`. You can define multiple modules the same way you define a single -// module, using `def moduleDeps` to define the relationship between them. -// -// Note that we split out the `test` submodule configuration common to both -// modules into a separate `trait MyModule`. This lets us avoid the need to -// copy-paste common settings, while still letting us define any per-module -// configuration such as `ivyDeps` specific to a particular module. -// -// The above builds expect the following project layout: -// -//// SNIPPET:TREE -// -// ---- -// build.mill -// foo/ -// src/ -// Foo.scala -// resources/ -// ... -// bar/ -// src/ -// Bar.scala -// resources/ -// ... -// out/ -// foo/ -// compile.json -// compile.dest/ -// ... -// bar/ -// compile.json -// compile.dest/ -// ... -// ---- -// -//// SNIPPET:END -// Typically, both source code and output files in Mill follow the module -// hierarchy, so e.g. input to the `foo` module lives in `foo/src/` and -// compiled output files live in `out/foo/compile.dest`. - -/** Usage - -> mill resolve __.run -foo.run -bar.run - -> mill foo.run --foo-text hello --bar-text world -Foo.value: hello -Bar.value:

world

- -> mill bar.run world -Bar.value:

world

- -> mill bar.test -... -...bar.BarTests...simple... -...bar.BarTests...escaping... - -*/ - -// Mill's evaluator will ensure that the modules are compiled in the right -// order, and recompiled as necessary when source code in each module changes. -// -// You can use wildcards and brace-expansion to select -// multiple targets at once or to shorten the path to deeply nested targets. If -// you provide optional target arguments and your wildcard or brace-expansion is -// resolved to multiple targets, the arguments will be applied to each of the -// targets. -// -// .Wildcards and brace-expansion -// |========================================================== -// | Wildcard | Function -// | `_` | matches a single segment of the target path -// | `__` | matches arbitrary segments of the target path -// | `{a,b}` | is equal to specifying two targets `a` and `b` -// |========================================================== -// -// -// You can use the `+` symbol to add another target with optional arguments. -// If you need to feed a `+` as argument to your target, you can mask it by -// preceding it with a backslash (`\`). -// -// === Examples -// -// `+mill foo._.compile+`:: Runs `compile` for all direct sub-modules of `foo` -// `+mill foo.__.test+` :: Runs `test` for all sub-modules of `foo` -// `+mill {foo,bar}.__.testCached+` :: Runs `testCached` for all sub-modules of `foo` and `bar` -// `+mill __.compile + foo.__.test+` :: Runs all `compile` targets and all tests under `foo`. -// -// diff --git a/example/scalalib/native/3-multi-module/foo/native-src/HelloWorldFoo.c b/example/scalalib/native/3-multi-module/foo/native-src/HelloWorldFoo.c new file mode 100644 index 00000000000..e8b9fb3d384 --- /dev/null +++ b/example/scalalib/native/3-multi-module/foo/native-src/HelloWorldFoo.c @@ -0,0 +1,7 @@ +#include "htmc.h" +#include + + +char* generateHtml(const char* text) { + return htmc(p(text)); +} diff --git a/example/scalalib/native/3-multi-module/foo/native-src/htm.c b/example/scalalib/native/3-multi-module/foo/native-src/htm.c new file mode 100644 index 00000000000..298492900d9 --- /dev/null +++ b/example/scalalib/native/3-multi-module/foo/native-src/htm.c @@ -0,0 +1,547 @@ +#include "htmc.h" + +#ifndef HTMC_C +#define HTMC_C + +#include + +const char *htmc_tags[] = { +"a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "math", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr" +}; + +const uint32_t htmc_tag_lengths[] = { +sizeof("a") - 1, sizeof("abbr") - 1, sizeof("address") - 1, sizeof("area") - 1, sizeof("article") - 1, sizeof("aside") - 1, sizeof("audio") - 1, sizeof("b") - 1, sizeof("base") - 1, sizeof("bdi") - 1, sizeof("bdo") - 1, sizeof("blockquote") - 1, sizeof("body") - 1, sizeof("br") - 1, sizeof("button") - 1, sizeof("canvas") - 1, sizeof("caption") - 1, sizeof("cite") - 1, sizeof("code") - 1, sizeof("col") - 1, sizeof("colgroup") - 1, sizeof("data") - 1, sizeof("datalist") - 1, sizeof("dd") - 1, sizeof("del") - 1, sizeof("details") - 1, sizeof("dfn") - 1, sizeof("dialog") - 1, sizeof("div") - 1, sizeof("dl") - 1, sizeof("dt") - 1, sizeof("em") - 1, sizeof("embed") - 1, sizeof("fieldset") - 1, sizeof("figcaption") - 1, sizeof("figure") - 1, sizeof("footer") - 1, sizeof("form") - 1, sizeof("h1") - 1, sizeof("h2") - 1, sizeof("h3") - 1, sizeof("h4") - 1, sizeof("h5") - 1, sizeof("h6") - 1, sizeof("head") - 1, sizeof("header") - 1, sizeof("hgroup") - 1, sizeof("hr") - 1, sizeof("html") - 1, sizeof("i") - 1, sizeof("iframe") - 1, sizeof("img") - 1, sizeof("input") - 1, sizeof("ins") - 1, sizeof("kbd") - 1, sizeof("label") - 1, sizeof("legend") - 1, sizeof("li") - 1, sizeof("link") - 1, sizeof("main") - 1, sizeof("map") - 1, sizeof("mark") - 1, sizeof("math") - 1, sizeof("menu") - 1, sizeof("meta") - 1, sizeof("meter") - 1, sizeof("nav") - 1, sizeof("noscript") - 1, sizeof("object") - 1, sizeof("ol") - 1, sizeof("optgroup") - 1, sizeof("option") - 1, sizeof("output") - 1, sizeof("p") - 1, sizeof("param") - 1, sizeof("picture") - 1, sizeof("pre") - 1, sizeof("progress") - 1, sizeof("q") - 1, sizeof("rp") - 1, sizeof("rt") - 1, sizeof("ruby") - 1, sizeof("s") - 1, sizeof("samp") - 1, sizeof("script") - 1, sizeof("section") - 1, sizeof("select") - 1, sizeof("slot") - 1, sizeof("small") - 1, sizeof("source") - 1, sizeof("span") - 1, sizeof("strong") - 1, sizeof("style") - 1, sizeof("sub") - 1, sizeof("summary") - 1, sizeof("sup") - 1, sizeof("svg") - 1, sizeof("table") - 1, sizeof("tbody") - 1, sizeof("td") - 1, sizeof("template") - 1, sizeof("textarea") - 1, sizeof("tfoot") - 1, sizeof("th") - 1, sizeof("thead") - 1, sizeof("time") - 1, sizeof("title") - 1, sizeof("tr") - 1, sizeof("track") - 1, sizeof("u") - 1, sizeof("ul") - 1, sizeof("var") - 1, sizeof("video") - 1, sizeof("wbr") - 1 +}; + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx) +{ + size_t i = 0; + for( ; i != used_idx ; i++) + { + free(ha->buffers[i]); + } + for(i += 1; i < ha->nb ; i++) + { + free(ha->buffers[i]); + } + + free(ha->caps); + free(ha->sizes); + free(ha->unused); + free(ha->buffers); +} + +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer) +{ + size_t i; + for(i = 0; i < ha->nb ; i++) + { + if(buffer == ha->buffers[i]) + break; + } + return i; +} + +void htmc_grow_buffers(HtmcAllocations *ha) +{ + ha->buffers = realloc(ha->buffers, ha->nb * 2 * sizeof(char*)); + memset(ha->buffers + ha->nb, 0, ha->nb * sizeof(char*)); + + ha->caps = realloc(ha->caps, ha->nb * 2 * sizeof(size_t)); + memset(ha->caps + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->sizes = realloc(ha->sizes, ha->nb * 2 * sizeof(size_t)); + memset(ha->sizes + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->unused = realloc(ha->unused, ha->nb * 2 * sizeof(bool)); + memset(ha->unused + ha->nb, 1, ha->nb * sizeof(bool)); + + ha->nb *= 2; +} + +void htmc_set_unused(HtmcAllocations *ha, const char *str) +{ + size_t idx = htmc_find_buffer(ha, str); + ha->unused[idx] = true; +} + +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str) +{ + size_t found = htmc_find_buffer(ha, str); + if(found != ha->nb) + { + ha->unused[found] = true; + } +} + +size_t htmc_find_unused(const HtmcAllocations *ha) +{ + size_t first_unused; + + for(first_unused = 0 ; first_unused < ha->nb ; first_unused++) + { + if(ha->unused[first_unused]) + { + goto find_unused_and_alloced; + } + } + + // no unused buffers were found + return first_unused; + + find_unused_and_alloced: + for(size_t i = first_unused ; i < ha->nb ; i++) + { + if(ha->unused[i] && ha->caps[i] != 0) + { + return i; + } + } + + return first_unused; +} + +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_cap) +{ + size_t unused_buffer_idx = htmc_find_unused(ha); + if(unused_buffer_idx == ha->nb) + { + unused_buffer_idx = ha->nb; + htmc_grow_buffers(ha); + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = calloc(with_cap, sizeof(char)); + ha->caps[ unused_buffer_idx ] = with_cap; + } + else if(with_cap > ha->caps[ unused_buffer_idx ]) + { + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = realloc(*unused_buffer, with_cap); + ha->caps[ unused_buffer_idx ] = with_cap; + } + + ha->unused[ unused_buffer_idx ] = false; + + return unused_buffer_idx; +} + +size_t htmc_concat_strings_into(HtmcAllocations *ha, HtmcStrsArr strs, size_t unused_buffer_idx) +{ + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + + // if no strings were provided, return an empty string + if(strs.nb == 0) + { + if(*cap == 0) + { + *unused_buffer = calloc(1, sizeof(char)); + } + **unused_buffer = '\0'; + return unused_buffer_idx; + } + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(next_str); + if(*size + next_len >= *cap) + { + *cap = (next_len + *cap) * 2; + *unused_buffer = realloc(*unused_buffer, *cap); + } + memcpy(*unused_buffer + *size, next_str, next_len); + + htmc_set_unused_if_alloced(ha, next_str); + + *size = *size + next_len; + } + + (*unused_buffer)[*size] = '\0'; + return unused_buffer_idx; +} + +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs) +{ + size_t unused_buffer_idx = htmc_get_unused(ha, 16); + return htmc_concat_strings_into(ha, strs, unused_buffer_idx); +} + +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t append_to, HtmcStrsArr strs) +{ + char **append_to_str = &ha->buffers[ append_to ]; + size_t *len = &ha->sizes[ append_to ]; + size_t *cap = &ha->caps [ append_to ]; + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(strs.arr[i]); + bool is_copy = (next_str == *append_to_str); + + if(*len + next_len >= *cap) + { + htmc_gurantee_cap(append_to_str, cap, (next_len + *cap) * 2); + } + + // if it's a copy of *append_to_str that means it might have been invalidate with the htmc_gurantee_cap + if(is_copy) + { + memmove(*append_to_str + *len, *append_to_str, next_len); + *len += next_len; + } + else + { + memmove(*append_to_str + *len, next_str, next_len); + *len += next_len; + + htmc_set_unused_if_alloced(ha, next_str); + } + } + + (*append_to_str)[*len] = '\0'; +} + +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **between_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + htmc_gurantee_cap(between_ptr, cap, needed_cap); + + memmove(*between_ptr + 1 + tag_len + 1, *between_ptr, between_len); + + memcpy(*between_ptr, "<", 1); + memcpy(*between_ptr + 1, tag, tag_len); + memcpy(*between_ptr + 1 + tag_len, ">", 1); + memcpy(*between_ptr + 1 + tag_len + 1 + between_len, "", 1); + (*between_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *between_ptr; +} + +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, needed_cap); + const char *between = ha->buffers[ str_idx ]; + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t size = 0; + + memcpy(*unused_buffer, "<", 1); + size += 1; + + memcpy(*unused_buffer + size, tag, tag_len); + size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*cap <= size + attr_len + 1) // 1 for the spaces between each attribute + { + *unused_buffer = realloc(*unused_buffer, size + (attr_len * 2)); + *cap = size + (attr_len * 2); + } + memcpy(*unused_buffer + size, " ", 1); + size += 1; + memcpy(*unused_buffer + size, attrs.arr[i], attr_len); + size += attr_len; + } + + if(*cap <= size + 1 + between_len + 2 + tag_len + 1) + { + *unused_buffer = realloc(*unused_buffer, size + 1 + between_len + 2 + tag_len + 1 + 1); + *cap = size + 1 + between_len + 2 + tag_len + 1 + 1; + } + + memcpy(*unused_buffer + size, ">", 1); + size += 1; + + memcpy(*unused_buffer + size, between, between_len); + size += between_len; + + memcpy(*unused_buffer + size, "", 1); + size += 1; + + (*unused_buffer)[size] = '\0'; + + ha->sizes[ unused_buffer_idx ] = size; + ha->unused[ str_idx ] = true; + + return *unused_buffer; +} + +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id) +{ + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + memcpy(*unused_buffer + 1, tag, tag_len); + memcpy(*unused_buffer + 1 + tag_len, ">", 1); + (*unused_buffer)[ 1 + tag_len + 1 ] = '\0'; + + ha->sizes[ unused_buffer_idx ] = tag_len + 2; + + return *unused_buffer; +} + +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy) +{ + (void)dummy; + + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + size_t *cap = &ha->caps[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + *size += 1; + + memcpy(*unused_buffer + 1, tag, tag_len); + *size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*size + attr_len + 1 >= *cap) + { + *unused_buffer = realloc(*unused_buffer, (*size + attr_len) * 2); + *cap = (*size + attr_len) * 2; + } + + memcpy(*unused_buffer + *size, " ", 1); + *size += 1; + + memcpy(*unused_buffer + *size, attrs.arr[i], attr_len); + *size += attr_len; + } + + memcpy(*unused_buffer + *size, ">", 2); // 2 for the '\0' + *size += 1; + + return *unused_buffer; +} + +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + const size_t combined_strlen = ha->sizes[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + if(combined_strlen * nb >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, combined_strlen * nb + 1); + *cap = combined_strlen * nb + 1; + } + + for(uint32_t i = 1 ; i < nb ; i++) + { + memcpy(*combined_str_ptr + *size, *combined_str_ptr, combined_strlen); + *size += combined_strlen; + } + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +// should mod take idx? maybe leave that as the re-entrant version with void*, and let user handle idx +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i, arg); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t len = ha->sizes[ str_idx ]; + size_t unused_buffer_idx = htmc_get_unused(ha, len + 1); + char **dup = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*dup, ha->buffers[ str_idx ], len + 1); + + ha->sizes[ unused_buffer_idx ] = len; + + return unused_buffer_idx; +} + +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t idx = htmc_strdup(ha, str_idx); + return ha->buffers[ idx ]; +} + +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + va_list args_copy1; + va_copy(args_copy1, args); + + int str_len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + + size_t unused_buffer_idx = htmc_get_unused(ha, str_len + 1); + char **unused = &ha->buffers[ unused_buffer_idx ]; + ha->sizes[ unused_buffer_idx ] = str_len; + + vsnprintf(*unused, str_len + 1, fmt, args_copy1); + va_end(args_copy1); + + htmc_set_unused_if_alloced(ha, fmt); + + return *unused; +} + +// TODO check in the string for '--' and report error +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **buffer_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t comment_start_len = 4; + const size_t comment_end_len = 3; + const size_t needed_cap = comment_start_len + between_len + comment_end_len + 1; + + htmc_gurantee_cap(buffer_ptr, cap, needed_cap); + + memmove(*buffer_ptr + comment_start_len, *buffer_ptr, between_len); + + memcpy(*buffer_ptr, "", 3); + (*buffer_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *buffer_ptr; +} + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap) +{ + if(*cap < new_cap) + { + *buffer = realloc(*buffer, new_cap); + *cap = new_cap; + } +} + +#endif /* HTMC_C */ diff --git a/example/scalalib/native/3-multi-module/foo/native-src/htmc.h b/example/scalalib/native/3-multi-module/foo/native-src/htmc.h new file mode 100644 index 00000000000..c7be0829643 --- /dev/null +++ b/example/scalalib/native/3-multi-module/foo/native-src/htmc.h @@ -0,0 +1,586 @@ +#ifndef HTMC_H +#define HTMC_H + +#include +#include +#include +#include +#include +#include + +typedef struct +{ + size_t nb; + bool *unused; + size_t *caps; + size_t *sizes; + char **buffers; +} HtmcAllocations; + +typedef struct +{ + char **arr; + size_t nb; +} HtmcStrsArr; + +#define htmc(...) \ +({ \ + const size_t init_cap = 4; \ + HtmcAllocations htmc_ha = { \ + .nb = init_cap, \ + .buffers = calloc(init_cap, sizeof(char*)), \ + .caps = calloc(init_cap, sizeof(size_t)), \ + .sizes = calloc(init_cap, sizeof(size_t)), \ + .unused = malloc(init_cap * sizeof(bool)), \ + }; \ + memset(htmc_ha.unused, 1, init_cap * sizeof(bool)); \ + size_t ret_idx = htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__)); \ + char *ret = htmc_ha.buffers[ ret_idx ]; \ + htmc_cleanup_unused_buffers(&htmc_ha, ret_idx); \ + ret; \ +}) + +#define htmc_strsarr(...) (HtmcStrsArr){.arr=(char*[]){__VA_ARGS__}, .nb=sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)} + +#define htmc_repeat(nb, ...) htmc_repeat_(&htmc_ha, nb, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify(nb, mod, ...) htmc_repeat_modify_(&htmc_ha, nb, mod, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify_r(nb, mod, ctx, ...) htmc_repeat_modify_r_(&htmc_ha, nb, mod, ctx, htmc_strsarr(__VA_ARGS__)) + +#define htmc_fmt(fmt, ...) htmc_fmt_(&htmc_ha, fmt, ##__VA_ARGS__) + +#define htmc_ccode(...) \ +({ \ + size_t htmc_ccode_yielded_idx = htmc_get_unused(&htmc_ha, 16); \ + htmc_ha.sizes[ htmc_ccode_yielded_idx ] = 0; \ + htmc_ha.buffers[ htmc_ccode_yielded_idx ][0] = '\0'; \ + __VA_ARGS__ \ + char *htmc_ccode_yielded = htmc_ha.buffers[ htmc_ccode_yielded_idx ]; \ + htmc_ccode_yielded; \ +}) +#define htmc_yield(...) htmc_append_to_buffer_idx(&htmc_ha, htmc_ccode_yielded_idx, htmc_strsarr(__VA_ARGS__)) +#define htmc_yielded htmc_ha.buffers[ htmc_ccode_yielded_idx ] +#define htmc_yielded_len htmc_ha.sizes[ htmc_ccode_yielded_idx ] + +#define htmc_attr_(...) \ +htmc_strsarr(__VA_ARGS__))) + +#define htmc_attr(tag, ...) \ +_Generic(&(char[htmc_is_single_tag(htmc_id_##tag) + 1]){ 0 } , \ + char(*)[1]: htmc_surround_by_tag_with_attrs, \ + char(*)[2]: htmc_make_tag_with_attrs \ +)(&htmc_ha, htmc_id_##tag, htmc_strsarr(__VA_ARGS__), htmc_concat_strings(&htmc_ha, htmc_attr_ + +#define htmc_strlit(...) #__VA_ARGS__ + +#define htmc_is_single_tag(id) \ +(id == (htmc_id_area || htmc_id_base || htmc_id_br || htmc_id_col || htmc_id_embed || htmc_id_hr || htmc_id_img || htmc_id_input || htmc_id_link || htmc_id_meta || htmc_id_param || htmc_id_source || htmc_id_track || htmc_id_wbr)) + +#define htmc_doctypehtml ("") + +#define htmc_comment(...) htmc_comment_(&htmc_ha, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that need a closing tag: +#define htmc_a(...) htmc_surround_by_tag(&htmc_ha, 0, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_abbr(...) htmc_surround_by_tag(&htmc_ha, 1, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_address(...) htmc_surround_by_tag(&htmc_ha, 2, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_article(...) htmc_surround_by_tag(&htmc_ha, 4, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_aside(...) htmc_surround_by_tag(&htmc_ha, 5, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_audio(...) htmc_surround_by_tag(&htmc_ha, 6, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_b(...) htmc_surround_by_tag(&htmc_ha, 7, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdi(...) htmc_surround_by_tag(&htmc_ha, 9, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdo(...) htmc_surround_by_tag(&htmc_ha, 10, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_blockquote(...) htmc_surround_by_tag(&htmc_ha, 11, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_body(...) htmc_surround_by_tag(&htmc_ha, 12, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_button(...) htmc_surround_by_tag(&htmc_ha, 14, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_canvas(...) htmc_surround_by_tag(&htmc_ha, 15, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_caption(...) htmc_surround_by_tag(&htmc_ha, 16, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_cite(...) htmc_surround_by_tag(&htmc_ha, 17, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_code(...) htmc_surround_by_tag(&htmc_ha, 18, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_colgroup(...) htmc_surround_by_tag(&htmc_ha, 20, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_data(...) htmc_surround_by_tag(&htmc_ha, 21, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_datalist(...) htmc_surround_by_tag(&htmc_ha, 22, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dd(...) htmc_surround_by_tag(&htmc_ha, 23, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_del(...) htmc_surround_by_tag(&htmc_ha, 24, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_details(...) htmc_surround_by_tag(&htmc_ha, 25, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dfn(...) htmc_surround_by_tag(&htmc_ha, 26, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dialog(...) htmc_surround_by_tag(&htmc_ha, 27, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_div(...) htmc_surround_by_tag(&htmc_ha, 28, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dl(...) htmc_surround_by_tag(&htmc_ha, 29, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dt(...) htmc_surround_by_tag(&htmc_ha, 30, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_em(...) htmc_surround_by_tag(&htmc_ha, 31, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_fieldset(...) htmc_surround_by_tag(&htmc_ha, 33, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figcaption(...) htmc_surround_by_tag(&htmc_ha, 34, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figure(...) htmc_surround_by_tag(&htmc_ha, 35, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_footer(...) htmc_surround_by_tag(&htmc_ha, 36, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_form(...) htmc_surround_by_tag(&htmc_ha, 37, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h1(...) htmc_surround_by_tag(&htmc_ha, 38, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h2(...) htmc_surround_by_tag(&htmc_ha, 39, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h3(...) htmc_surround_by_tag(&htmc_ha, 40, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h4(...) htmc_surround_by_tag(&htmc_ha, 41, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h5(...) htmc_surround_by_tag(&htmc_ha, 42, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h6(...) htmc_surround_by_tag(&htmc_ha, 43, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_head(...) htmc_surround_by_tag(&htmc_ha, 44, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_header(...) htmc_surround_by_tag(&htmc_ha, 45, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_hgroup(...) htmc_surround_by_tag(&htmc_ha, 46, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_html(...) htmc_surround_by_tag(&htmc_ha, 48, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_i(...) htmc_surround_by_tag(&htmc_ha, 49, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_iframe(...) htmc_surround_by_tag(&htmc_ha, 50, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ins(...) htmc_surround_by_tag(&htmc_ha, 53, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_kbd(...) htmc_surround_by_tag(&htmc_ha, 54, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_label(...) htmc_surround_by_tag(&htmc_ha, 55, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_legend(...) htmc_surround_by_tag(&htmc_ha, 56, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_li(...) htmc_surround_by_tag(&htmc_ha, 57, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_main(...) htmc_surround_by_tag(&htmc_ha, 59, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_map(...) htmc_surround_by_tag(&htmc_ha, 60, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_mark(...) htmc_surround_by_tag(&htmc_ha, 61, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_math(...) htmc_surround_by_tag(&htmc_ha, 62, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_menu(...) htmc_surround_by_tag(&htmc_ha, 63, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_meter(...) htmc_surround_by_tag(&htmc_ha, 65, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_nav(...) htmc_surround_by_tag(&htmc_ha, 66, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_noscript(...) htmc_surround_by_tag(&htmc_ha, 67, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_object(...) htmc_surround_by_tag(&htmc_ha, 68, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ol(...) htmc_surround_by_tag(&htmc_ha, 69, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_optgroup(...) htmc_surround_by_tag(&htmc_ha, 70, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_option(...) htmc_surround_by_tag(&htmc_ha, 71, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_output(...) htmc_surround_by_tag(&htmc_ha, 72, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_p(...) htmc_surround_by_tag(&htmc_ha, 73, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_picture(...) htmc_surround_by_tag(&htmc_ha, 75, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_pre(...) htmc_surround_by_tag(&htmc_ha, 76, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_progress(...) htmc_surround_by_tag(&htmc_ha, 77, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_q(...) htmc_surround_by_tag(&htmc_ha, 78, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rp(...) htmc_surround_by_tag(&htmc_ha, 79, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rt(...) htmc_surround_by_tag(&htmc_ha, 80, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ruby(...) htmc_surround_by_tag(&htmc_ha, 81, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_s(...) htmc_surround_by_tag(&htmc_ha, 82, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_samp(...) htmc_surround_by_tag(&htmc_ha, 83, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_script(...) htmc_surround_by_tag(&htmc_ha, 84, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_section(...) htmc_surround_by_tag(&htmc_ha, 85, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_select(...) htmc_surround_by_tag(&htmc_ha, 86, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_slot(...) htmc_surround_by_tag(&htmc_ha, 87, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_small(...) htmc_surround_by_tag(&htmc_ha, 88, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_span(...) htmc_surround_by_tag(&htmc_ha, 90, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_strong(...) htmc_surround_by_tag(&htmc_ha, 91, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_style(...) htmc_surround_by_tag(&htmc_ha, 92, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sub(...) htmc_surround_by_tag(&htmc_ha, 93, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_summary(...) htmc_surround_by_tag(&htmc_ha, 94, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sup(...) htmc_surround_by_tag(&htmc_ha, 95, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_svg(...) htmc_surround_by_tag(&htmc_ha, 96, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_table(...) htmc_surround_by_tag(&htmc_ha, 97, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tbody(...) htmc_surround_by_tag(&htmc_ha, 98, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_td(...) htmc_surround_by_tag(&htmc_ha, 99, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_template(...) htmc_surround_by_tag(&htmc_ha, 100, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_textarea(...) htmc_surround_by_tag(&htmc_ha, 101, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tfoot(...) htmc_surround_by_tag(&htmc_ha, 102, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_th(...) htmc_surround_by_tag(&htmc_ha, 103, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_thead(...) htmc_surround_by_tag(&htmc_ha, 104, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_time(...) htmc_surround_by_tag(&htmc_ha, 105, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_title(...) htmc_surround_by_tag(&htmc_ha, 106, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tr(...) htmc_surround_by_tag(&htmc_ha, 107, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_u(...) htmc_surround_by_tag(&htmc_ha, 109, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ul(...) htmc_surround_by_tag(&htmc_ha, 110, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_var(...) htmc_surround_by_tag(&htmc_ha, 111, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_video(...) htmc_surround_by_tag(&htmc_ha, 112, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that don't terminate +#define htmc_area(...) htmc_make_tag_with_attrs(&htmc_ha, 3, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_base(...) htmc_make_tag_with_attrs(&htmc_ha, 8, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_br(...) htmc_make_tag_with_attrs(&htmc_ha, 13, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_col(...) htmc_make_tag_with_attrs(&htmc_ha, 19, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_embed(...) htmc_make_tag_with_attrs(&htmc_ha, 32, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_hr(...) htmc_make_tag_with_attrs(&htmc_ha, 47, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_img(...) htmc_make_tag_with_attrs(&htmc_ha, 51, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_input(...) htmc_make_tag_with_attrs(&htmc_ha, 52, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_link(...) htmc_make_tag_with_attrs(&htmc_ha, 58, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_meta(...) htmc_make_tag_with_attrs(&htmc_ha, 64, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_param(...) htmc_make_tag_with_attrs(&htmc_ha, 74, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_source(...) htmc_make_tag_with_attrs(&htmc_ha, 89, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_track(...) htmc_make_tag_with_attrs(&htmc_ha, 108, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_wbr(...) htmc_make_tag_with_attrs(&htmc_ha, 113, htmc_strsarr(__VA_ARGS__), NULL) + +#define htmc_id_a 0 +#define htmc_id_abbr 1 +#define htmc_id_address 2 +#define htmc_id_area 3 +#define htmc_id_article 4 +#define htmc_id_aside 5 +#define htmc_id_audio 6 +#define htmc_id_b 7 +#define htmc_id_base 8 +#define htmc_id_bdi 9 +#define htmc_id_bdo 10 +#define htmc_id_blockquote 11 +#define htmc_id_body 12 +#define htmc_id_br 13 +#define htmc_id_button 14 +#define htmc_id_canvas 15 +#define htmc_id_caption 16 +#define htmc_id_cite 17 +#define htmc_id_code 18 +#define htmc_id_col 19 +#define htmc_id_colgroup 20 +#define htmc_id_data 21 +#define htmc_id_datalist 22 +#define htmc_id_dd 23 +#define htmc_id_del 24 +#define htmc_id_details 25 +#define htmc_id_dfn 26 +#define htmc_id_dialog 27 +#define htmc_id_div 28 +#define htmc_id_dl 29 +#define htmc_id_dt 30 +#define htmc_id_em 31 +#define htmc_id_embed 32 +#define htmc_id_fieldset 33 +#define htmc_id_figcaption 34 +#define htmc_id_figure 35 +#define htmc_id_footer 36 +#define htmc_id_form 37 +#define htmc_id_h1 38 +#define htmc_id_h2 39 +#define htmc_id_h3 40 +#define htmc_id_h4 41 +#define htmc_id_h5 42 +#define htmc_id_h6 43 +#define htmc_id_head 44 +#define htmc_id_header 45 +#define htmc_id_hgroup 46 +#define htmc_id_hr 47 +#define htmc_id_html 48 +#define htmc_id_i 49 +#define htmc_id_iframe 50 +#define htmc_id_img 51 +#define htmc_id_input 52 +#define htmc_id_ins 53 +#define htmc_id_kbd 54 +#define htmc_id_label 55 +#define htmc_id_legend 56 +#define htmc_id_li 57 +#define htmc_id_link 58 +#define htmc_id_main 59 +#define htmc_id_map 60 +#define htmc_id_mark 61 +#define htmc_id_math 62 +#define htmc_id_menu 63 +#define htmc_id_meta 64 +#define htmc_id_meter 65 +#define htmc_id_nav 66 +#define htmc_id_noscript 67 +#define htmc_id_object 68 +#define htmc_id_ol 69 +#define htmc_id_optgroup 70 +#define htmc_id_option 71 +#define htmc_id_output 72 +#define htmc_id_p 73 +#define htmc_id_param 74 +#define htmc_id_picture 75 +#define htmc_id_pre 76 +#define htmc_id_progress 77 +#define htmc_id_q 78 +#define htmc_id_rp 79 +#define htmc_id_rt 80 +#define htmc_id_ruby 81 +#define htmc_id_s 82 +#define htmc_id_samp 83 +#define htmc_id_script 84 +#define htmc_id_section 85 +#define htmc_id_select 86 +#define htmc_id_slot 87 +#define htmc_id_small 88 +#define htmc_id_source 89 +#define htmc_id_span 90 +#define htmc_id_strong 91 +#define htmc_id_style 92 +#define htmc_id_sub 93 +#define htmc_id_summary 94 +#define htmc_id_sup 95 +#define htmc_id_svg 96 +#define htmc_id_table 97 +#define htmc_id_tbody 98 +#define htmc_id_td 99 +#define htmc_id_template 100 +#define htmc_id_textarea 101 +#define htmc_id_tfoot 102 +#define htmc_id_th 103 +#define htmc_id_thead 104 +#define htmc_id_time 105 +#define htmc_id_title 106 +#define htmc_id_tr 107 +#define htmc_id_track 108 +#define htmc_id_u 109 +#define htmc_id_ul 110 +#define htmc_id_var 111 +#define htmc_id_video 112 +#define htmc_id_wbr 113 + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx); +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer); +void htmc_grow_buffers(HtmcAllocations *ha); +void htmc_set_unused(HtmcAllocations *ha, const char *str); +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str); +size_t htmc_find_unused(const HtmcAllocations *ha); +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_size); +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs); +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx); +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx); +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id); +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy); +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs); +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs); +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs); +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...); +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t buffer_idx, HtmcStrsArr strs); +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx); + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap); + +#endif + +#ifdef HTMC_PREFIX + +#undef HTMC_PREFIX + +#undef doctypehtml + +#undef comment + +#undef a +#undef abbr +#undef address +#undef area +#undef article +#undef aside +#undef audio +#undef b +#undef base +#undef bdi +#undef bdo +#undef blockquote +#undef body +#undef br +#undef button +#undef canvas +#undef caption +#undef cite +#undef code +#undef col +#undef colgroup +#undef data +#undef datalist +#undef dd +#undef del +#undef details +#undef dfn +#undef dialog +#undef div +#undef dl +#undef dt +#undef em +#undef embed +#undef fieldset +#undef figcaption +#undef figure +#undef footer +#undef form +#undef h1 +#undef h2 +#undef h3 +#undef h4 +#undef h5 +#undef h6 +#undef head +#undef header +#undef hgroup +#undef hr +#undef html +#undef i +#undef iframe +#undef img +#undef input +#undef ins +#undef kbd +#undef label +#undef legend +#undef li +#undef link +#undef map +#undef mark +#undef math +#undef menu +#undef meta +#undef meter +#undef nav +#undef noscript +#undef object +#undef ol +#undef optgroup +#undef option +#undef output +#undef p +#undef param +#undef picture +#undef pre +#undef progress +#undef q +#undef rp +#undef rt +#undef ruby +#undef s +#undef samp +#undef script +#undef section +#undef select +#undef slot +#undef small +#undef source +#undef span +#undef strong +#undef style +#undef sub +#undef summary +#undef sup +#undef svg +#undef table +#undef tbody +#undef td +#undef template +#undef textarea +#undef tfoot +#undef th +#undef thead +#undef time +#undef title +#undef tr +#undef track +#undef u +#undef ul +#undef var +#undef video +#undef wbr + +#undef attr + +#else + +#define doctypehtml htmc_doctypehtml + +#define comment htmc_comment + +#define a(...) htmc_a(__VA_ARGS__) +#define abbr(...) htmc_abbr(__VA_ARGS__) +#define address(...) htmc_address(__VA_ARGS__) +#define area(...) htmc_area(__VA_ARGS__) +#define article(...) htmc_article(__VA_ARGS__) +#define aside(...) htmc_aside(__VA_ARGS__) +#define audio(...) htmc_audio(__VA_ARGS__) +#define b(...) htmc_b(__VA_ARGS__) +#define base(...) htmc_base(__VA_ARGS__) +#define bdi(...) htmc_bdi(__VA_ARGS__) +#define bdo(...) htmc_bdo(__VA_ARGS__) +#define blockquote(...) htmc_blockquote(__VA_ARGS__) +#define body(...) htmc_body(__VA_ARGS__) +#define br(...) htmc_br(__VA_ARGS__) +#define button(...) htmc_button(__VA_ARGS__) +#define canvas(...) htmc_canvas(__VA_ARGS__) +#define caption(...) htmc_caption(__VA_ARGS__) +#define cite(...) htmc_cite(__VA_ARGS__) +#define code(...) htmc_code(__VA_ARGS__) +#define col(...) htmc_col(__VA_ARGS__) +#define colgroup(...) htmc_colgroup(__VA_ARGS__) +#define data(...) htmc_data(__VA_ARGS__) +#define datalist(...) htmc_datalist(__VA_ARGS__) +#define dd(...) htmc_dd(__VA_ARGS__) +#define del(...) htmc_del(__VA_ARGS__) +#define details(...) htmc_details(__VA_ARGS__) +#define dfn(...) htmc_dfn(__VA_ARGS__) +#define dialog(...) htmc_dialog(__VA_ARGS__) +#define div(...) htmc_div(__VA_ARGS__) +#define dl(...) htmc_dl(__VA_ARGS__) +#define dt(...) htmc_dt(__VA_ARGS__) +#define em(...) htmc_em(__VA_ARGS__) +#define embed(...) htmc_embed(__VA_ARGS__) +#define fieldset(...) htmc_fieldset(__VA_ARGS__) +#define figcaption(...) htmc_figcaption(__VA_ARGS__) +#define figure(...) htmc_figure(__VA_ARGS__) +#define footer(...) htmc_footer(__VA_ARGS__) +#define form(...) htmc_form(__VA_ARGS__) +#define h1(...) htmc_h1(__VA_ARGS__) +#define h2(...) htmc_h2(__VA_ARGS__) +#define h3(...) htmc_h3(__VA_ARGS__) +#define h4(...) htmc_h4(__VA_ARGS__) +#define h5(...) htmc_h5(__VA_ARGS__) +#define h6(...) htmc_h6(__VA_ARGS__) +#define head(...) htmc_head(__VA_ARGS__) +#define header(...) htmc_header(__VA_ARGS__) +#define hgroup(...) htmc_hgroup(__VA_ARGS__) +#define hr(...) htmc_hr(__VA_ARGS__) +#define html(...) htmc_html(__VA_ARGS__) +#define i(...) htmc_i(__VA_ARGS__) +#define iframe(...) htmc_iframe(__VA_ARGS__) +#define img(...) htmc_img(__VA_ARGS__) +#define input(...) htmc_input(__VA_ARGS__) +#define ins(...) htmc_ins(__VA_ARGS__) +#define kbd(...) htmc_kbd(__VA_ARGS__) +#define label(...) htmc_label(__VA_ARGS__) +#define legend(...) htmc_legend(__VA_ARGS__) +#define li(...) htmc_li(__VA_ARGS__) +#define link(...) htmc_link(__VA_ARGS__) +#define map(...) htmc_map(__VA_ARGS__) +#define mark(...) htmc_mark(__VA_ARGS__) +#define math(...) htmc_math(__VA_ARGS__) +#define menu(...) htmc_menu(__VA_ARGS__) +#define meta(...) htmc_meta(__VA_ARGS__) +#define meter(...) htmc_meter(__VA_ARGS__) +#define nav(...) htmc_nav(__VA_ARGS__) +#define noscript(...) htmc_noscript(__VA_ARGS__) +#define object(...) htmc_object(__VA_ARGS__) +#define ol(...) htmc_ol(__VA_ARGS__) +#define optgroup(...) htmc_optgroup(__VA_ARGS__) +#define option(...) htmc_option(__VA_ARGS__) +#define output(...) htmc_output(__VA_ARGS__) +#define p(...) htmc_p(__VA_ARGS__) +#define param(...) htmc_param(__VA_ARGS__) +#define picture(...) htmc_picture(__VA_ARGS__) +#define pre(...) htmc_pre(__VA_ARGS__) +#define progress(...) htmc_progress(__VA_ARGS__) +#define q(...) htmc_q(__VA_ARGS__) +#define rp(...) htmc_rp(__VA_ARGS__) +#define rt(...) htmc_rt(__VA_ARGS__) +#define ruby(...) htmc_ruby(__VA_ARGS__) +#define s(...) htmc_s(__VA_ARGS__) +#define samp(...) htmc_samp(__VA_ARGS__) +#define script(...) htmc_script(__VA_ARGS__) +#define section(...) htmc_section(__VA_ARGS__) +#define select(...) htmc_select(__VA_ARGS__) +#define slot(...) htmc_slot(__VA_ARGS__) +#define small(...) htmc_small(__VA_ARGS__) +#define source(...) htmc_source(__VA_ARGS__) +#define span(...) htmc_span(__VA_ARGS__) +#define strong(...) htmc_strong(__VA_ARGS__) +#define style(...) htmc_style(__VA_ARGS__) +#define sub(...) htmc_sub(__VA_ARGS__) +#define summary(...) htmc_summary(__VA_ARGS__) +#define sup(...) htmc_sup(__VA_ARGS__) +#define svg(...) htmc_svg(__VA_ARGS__) +#define table(...) htmc_table(__VA_ARGS__) +#define tbody(...) htmc_tbody(__VA_ARGS__) +#define td(...) htmc_td(__VA_ARGS__) +#define template(...) htmc_template(__VA_ARGS__) +#define textarea(...) htmc_textarea(__VA_ARGS__) +#define tfoot(...) htmc_tfoot(__VA_ARGS__) +#define th(...) htmc_th(__VA_ARGS__) +#define thead(...) htmc_thead(__VA_ARGS__) +#define time(...) htmc_time(__VA_ARGS__) +#define title(...) htmc_title(__VA_ARGS__) +#define tr(...) htmc_tr(__VA_ARGS__) +#define track(...) htmc_track(__VA_ARGS__) +#define u(...) htmc_u(__VA_ARGS__) +#define ul(...) htmc_ul(__VA_ARGS__) +#define var(...) htmc_var(__VA_ARGS__) +#define video(...) htmc_video(__VA_ARGS__) +#define wbr(...) htmc_wbr(__VA_ARGS__) + +#define attr(...) htmc_attr(__VA_ARGS__) + +#endif diff --git a/example/scalalib/native/3-multi-module/foo/src/Foo.scala b/example/scalalib/native/3-multi-module/foo/src/Foo.scala index 952d4d41dbc..00dfb5c7f64 100644 --- a/example/scalalib/native/3-multi-module/foo/src/Foo.scala +++ b/example/scalalib/native/3-multi-module/foo/src/Foo.scala @@ -1,12 +1,22 @@ package foo +import scala.scalanative.unsafe._ import mainargs.{main, ParserForMethods, arg} + object Foo { @main - def main(@arg(name = "foo-text") fooText: String, - @arg(name = "bar-text") barText: String): Unit = { - println("Foo.value: " + fooText) + def main(@arg(name = "foo-text") fooText: CString, + @arg(name = "bar-text") barText: CString): Unit = { + println("Foo.value: " + HelloWorldFoo.generateHtml(fooText)) println("Bar.value: " + bar.Bar.generateHtml(barText)) } def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) } + +@extern +@link("HelloWorldFoo") +// Arbitrary object name +object HelloWorldFoo { + // Name and signature of C function + def generateHtml(str: CString): CString = extern +} From 4f3a61b25c18bd164658c684edb4c1aa9d918d3f Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 5 Oct 2024 14:06:38 +0100 Subject: [PATCH 17/37] update scala=native example code --- .../native/3-multi-module/bar/test/src/BarTests.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala index 4033fdd973b..08f919dee94 100644 --- a/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala +++ b/example/scalalib/native/3-multi-module/bar/test/src/BarTests.scala @@ -5,12 +5,12 @@ import scala.scalanative.unsafe._ object BarTests extends TestSuite { def tests = Tests { test("simple") { - val result = Bar.generateHtml(c"hello") + val result = HelloWorldBar.generateHtml(c"hello") assert(result == "

hello

") result } test("escaping") { - val result = Bar.generateHtml(c"") + val result = HelloWorldBar.generateHtml(c"") assert(result == "

<hello>

") result } From dfb0e5e13d9214e79db73596f4343b091ecca69b Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Sat, 5 Oct 2024 16:41:31 +0100 Subject: [PATCH 18/37] Create draft build.mill for multi-module example --- .../scalalib/native/3-multi-module/build.mill | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 example/scalalib/native/3-multi-module/build.mill diff --git a/example/scalalib/native/3-multi-module/build.mill b/example/scalalib/native/3-multi-module/build.mill new file mode 100644 index 00000000000..afb6a618d95 --- /dev/null +++ b/example/scalalib/native/3-multi-module/build.mill @@ -0,0 +1,57 @@ +//// SNIPPET:BUILD +package build +import mill._, scalalib._, scalanativelib._ + +trait MyModule extends ScalaNativeModule { + def scalaVersion = "2.13.11" + def scalaNativeVersion = "0.5.5" + object test extends ScalaNativeTests { + def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def testFramework = "utest.runner.Framework" + } +} + +object foo extends MyModule { + def moduleDeps = Seq(bar) + def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0") +} + +object bar extends MyModule { + def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2") +} +//// SNIPPET:END + +// This example contains a simple Mill build with two modules, `foo` and `bar`. +// We don't mark either module as top-level using `extends RootModule`, so +// running tasks needs to use the module name as the prefix e.g. `foo.run` or +// `bar.run`. You can define multiple modules the same way you define a single +// module, using `def moduleDeps` to define the relationship between them. +// +// Note that we split out the `test` submodule configuration common to both +// modules into a separate `trait MyModule`. This lets us avoid the need to +// copy-paste common settings, while still letting us define any per-module +// configuration such as `ivyDeps` specific to a particular module. +// +// The above builds expect the following project layout: +// +//// SNIPPET:TREE +// +// ---- +// build.mill +// bar/ +// native-src/ +// HelloWorldBar.c +// src/ +// Bar.scala +// test/ +// src/ +// BarTests.scala +// foo/ +// native-src/ + HelloWorldFoo.c +// src/ +// Foo.scala +// +// +// +//// SNIPPET:END From bd1f75677303af511cf284e44d541f95f27205a8 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Sat, 5 Oct 2024 17:57:16 +0100 Subject: [PATCH 19/37] Create MyResource.txt --- example/scalalib/native/4-common-config/resources/MyResource.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 example/scalalib/native/4-common-config/resources/MyResource.txt diff --git a/example/scalalib/native/4-common-config/resources/MyResource.txt b/example/scalalib/native/4-common-config/resources/MyResource.txt new file mode 100644 index 00000000000..13a6ffaf112 --- /dev/null +++ b/example/scalalib/native/4-common-config/resources/MyResource.txt @@ -0,0 +1 @@ +My Resource Contents From e41d6094f46d4bf50ecf0b9a493d4fe333b251b0 Mon Sep 17 00:00:00 2001 From: c0d33ngr <106184818+c0d33ngr@users.noreply.github.com> Date: Sat, 5 Oct 2024 17:59:09 +0100 Subject: [PATCH 20/37] Create MyOtherResource.txt --- .../native/4-common-config/common-resources/MyOtherResource.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 example/scalalib/native/4-common-config/common-resources/MyOtherResource.txt diff --git a/example/scalalib/native/4-common-config/common-resources/MyOtherResource.txt b/example/scalalib/native/4-common-config/common-resources/MyOtherResource.txt new file mode 100644 index 00000000000..0ecf4cc2eb2 --- /dev/null +++ b/example/scalalib/native/4-common-config/common-resources/MyOtherResource.txt @@ -0,0 +1 @@ +My Other Resource Contents From 69ffd7d097a09a6267674c65a0c65a3d3028f37a Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 6 Oct 2024 01:22:21 +0100 Subject: [PATCH 21/37] add common-config code --- .../2-interop/test/src/HelloWorldTests.scala | 4 +- .../4-common-config/custom-src/Foo2.scala | 32 + .../4-common-config/native-src/HelloWorld.c | 7 + .../native/4-common-config/native-src/htm.c | 547 ++++++++++++++++ .../native/4-common-config/native-src/htmc.h | 586 ++++++++++++++++++ .../native/4-common-config/src/Foo.scala | 21 + 6 files changed, 1195 insertions(+), 2 deletions(-) create mode 100644 example/scalalib/native/4-common-config/custom-src/Foo2.scala create mode 100644 example/scalalib/native/4-common-config/native-src/HelloWorld.c create mode 100644 example/scalalib/native/4-common-config/native-src/htm.c create mode 100644 example/scalalib/native/4-common-config/native-src/htmc.h create mode 100644 example/scalalib/native/4-common-config/src/Foo.scala diff --git a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala index 049363003ae..c668a72bed5 100644 --- a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala +++ b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala @@ -8,10 +8,10 @@ object HelloWorldTest extends TestSuite { test("reverseString should reverse a C string correctly") { val expected = c"!dlrow olleH" - val reversed = HelloWorld.reverseString(c"Hello World!") + val result = HelloWorld.reverseString(c"Hello World!") // Check if the reversed string matches the expected result - assert(reversed == expected) + assert(result == expected) result } } diff --git a/example/scalalib/native/4-common-config/custom-src/Foo2.scala b/example/scalalib/native/4-common-config/custom-src/Foo2.scala new file mode 100644 index 00000000000..5e450d79bd2 --- /dev/null +++ b/example/scalalib/native/4-common-config/custom-src/Foo2.scala @@ -0,0 +1,32 @@ +package foo + +import scala.scalanative.unsafe._ + +object Foo2 { + val value = generateHtml(c"hello2") + def main(args: Array[String]): Unit = { + println("Foo2.value: " + Foo2.value) + println("Foo.value: " + Foo.value) + + println("FooA.value: " + FooA.value) + println("FooB.value: " + FooB.value) + println("FooC.value: " + FooC.value) + + println("MyResource: " + os.read(os.resource / "MyResource.txt")) + println("MyOtherResource: " + os.read(os.resource / "MyOtherResource.txt")) + + println("my.custom.property: " + sys.props("my.custom.property")) + + if (sys.env.contains("MY_CUSTOM_ENV")) println("MY_CUSTOM_ENV: " + sys.env("MY_CUSTOM_ENV")) + } +} + + +// Define the external module, the C library containing our function "generateHtml" +@extern +@link("HelloWorld") +// Arbitrary object name +object HelloWorld { + // Name and signature of C function + def generateHtml(str: CString): CString = extern +} diff --git a/example/scalalib/native/4-common-config/native-src/HelloWorld.c b/example/scalalib/native/4-common-config/native-src/HelloWorld.c new file mode 100644 index 00000000000..3fd48576930 --- /dev/null +++ b/example/scalalib/native/4-common-config/native-src/HelloWorld.c @@ -0,0 +1,7 @@ +#include "htmc.h" +#include + + +char* generateHtml(const char* text) { + return htmc(h1(text)); +} diff --git a/example/scalalib/native/4-common-config/native-src/htm.c b/example/scalalib/native/4-common-config/native-src/htm.c new file mode 100644 index 00000000000..298492900d9 --- /dev/null +++ b/example/scalalib/native/4-common-config/native-src/htm.c @@ -0,0 +1,547 @@ +#include "htmc.h" + +#ifndef HTMC_C +#define HTMC_C + +#include + +const char *htmc_tags[] = { +"a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "math", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr" +}; + +const uint32_t htmc_tag_lengths[] = { +sizeof("a") - 1, sizeof("abbr") - 1, sizeof("address") - 1, sizeof("area") - 1, sizeof("article") - 1, sizeof("aside") - 1, sizeof("audio") - 1, sizeof("b") - 1, sizeof("base") - 1, sizeof("bdi") - 1, sizeof("bdo") - 1, sizeof("blockquote") - 1, sizeof("body") - 1, sizeof("br") - 1, sizeof("button") - 1, sizeof("canvas") - 1, sizeof("caption") - 1, sizeof("cite") - 1, sizeof("code") - 1, sizeof("col") - 1, sizeof("colgroup") - 1, sizeof("data") - 1, sizeof("datalist") - 1, sizeof("dd") - 1, sizeof("del") - 1, sizeof("details") - 1, sizeof("dfn") - 1, sizeof("dialog") - 1, sizeof("div") - 1, sizeof("dl") - 1, sizeof("dt") - 1, sizeof("em") - 1, sizeof("embed") - 1, sizeof("fieldset") - 1, sizeof("figcaption") - 1, sizeof("figure") - 1, sizeof("footer") - 1, sizeof("form") - 1, sizeof("h1") - 1, sizeof("h2") - 1, sizeof("h3") - 1, sizeof("h4") - 1, sizeof("h5") - 1, sizeof("h6") - 1, sizeof("head") - 1, sizeof("header") - 1, sizeof("hgroup") - 1, sizeof("hr") - 1, sizeof("html") - 1, sizeof("i") - 1, sizeof("iframe") - 1, sizeof("img") - 1, sizeof("input") - 1, sizeof("ins") - 1, sizeof("kbd") - 1, sizeof("label") - 1, sizeof("legend") - 1, sizeof("li") - 1, sizeof("link") - 1, sizeof("main") - 1, sizeof("map") - 1, sizeof("mark") - 1, sizeof("math") - 1, sizeof("menu") - 1, sizeof("meta") - 1, sizeof("meter") - 1, sizeof("nav") - 1, sizeof("noscript") - 1, sizeof("object") - 1, sizeof("ol") - 1, sizeof("optgroup") - 1, sizeof("option") - 1, sizeof("output") - 1, sizeof("p") - 1, sizeof("param") - 1, sizeof("picture") - 1, sizeof("pre") - 1, sizeof("progress") - 1, sizeof("q") - 1, sizeof("rp") - 1, sizeof("rt") - 1, sizeof("ruby") - 1, sizeof("s") - 1, sizeof("samp") - 1, sizeof("script") - 1, sizeof("section") - 1, sizeof("select") - 1, sizeof("slot") - 1, sizeof("small") - 1, sizeof("source") - 1, sizeof("span") - 1, sizeof("strong") - 1, sizeof("style") - 1, sizeof("sub") - 1, sizeof("summary") - 1, sizeof("sup") - 1, sizeof("svg") - 1, sizeof("table") - 1, sizeof("tbody") - 1, sizeof("td") - 1, sizeof("template") - 1, sizeof("textarea") - 1, sizeof("tfoot") - 1, sizeof("th") - 1, sizeof("thead") - 1, sizeof("time") - 1, sizeof("title") - 1, sizeof("tr") - 1, sizeof("track") - 1, sizeof("u") - 1, sizeof("ul") - 1, sizeof("var") - 1, sizeof("video") - 1, sizeof("wbr") - 1 +}; + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx) +{ + size_t i = 0; + for( ; i != used_idx ; i++) + { + free(ha->buffers[i]); + } + for(i += 1; i < ha->nb ; i++) + { + free(ha->buffers[i]); + } + + free(ha->caps); + free(ha->sizes); + free(ha->unused); + free(ha->buffers); +} + +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer) +{ + size_t i; + for(i = 0; i < ha->nb ; i++) + { + if(buffer == ha->buffers[i]) + break; + } + return i; +} + +void htmc_grow_buffers(HtmcAllocations *ha) +{ + ha->buffers = realloc(ha->buffers, ha->nb * 2 * sizeof(char*)); + memset(ha->buffers + ha->nb, 0, ha->nb * sizeof(char*)); + + ha->caps = realloc(ha->caps, ha->nb * 2 * sizeof(size_t)); + memset(ha->caps + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->sizes = realloc(ha->sizes, ha->nb * 2 * sizeof(size_t)); + memset(ha->sizes + ha->nb, 0, ha->nb * sizeof(size_t)); + + ha->unused = realloc(ha->unused, ha->nb * 2 * sizeof(bool)); + memset(ha->unused + ha->nb, 1, ha->nb * sizeof(bool)); + + ha->nb *= 2; +} + +void htmc_set_unused(HtmcAllocations *ha, const char *str) +{ + size_t idx = htmc_find_buffer(ha, str); + ha->unused[idx] = true; +} + +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str) +{ + size_t found = htmc_find_buffer(ha, str); + if(found != ha->nb) + { + ha->unused[found] = true; + } +} + +size_t htmc_find_unused(const HtmcAllocations *ha) +{ + size_t first_unused; + + for(first_unused = 0 ; first_unused < ha->nb ; first_unused++) + { + if(ha->unused[first_unused]) + { + goto find_unused_and_alloced; + } + } + + // no unused buffers were found + return first_unused; + + find_unused_and_alloced: + for(size_t i = first_unused ; i < ha->nb ; i++) + { + if(ha->unused[i] && ha->caps[i] != 0) + { + return i; + } + } + + return first_unused; +} + +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_cap) +{ + size_t unused_buffer_idx = htmc_find_unused(ha); + if(unused_buffer_idx == ha->nb) + { + unused_buffer_idx = ha->nb; + htmc_grow_buffers(ha); + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = calloc(with_cap, sizeof(char)); + ha->caps[ unused_buffer_idx ] = with_cap; + } + else if(with_cap > ha->caps[ unused_buffer_idx ]) + { + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + *unused_buffer = realloc(*unused_buffer, with_cap); + ha->caps[ unused_buffer_idx ] = with_cap; + } + + ha->unused[ unused_buffer_idx ] = false; + + return unused_buffer_idx; +} + +size_t htmc_concat_strings_into(HtmcAllocations *ha, HtmcStrsArr strs, size_t unused_buffer_idx) +{ + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + + // if no strings were provided, return an empty string + if(strs.nb == 0) + { + if(*cap == 0) + { + *unused_buffer = calloc(1, sizeof(char)); + } + **unused_buffer = '\0'; + return unused_buffer_idx; + } + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(next_str); + if(*size + next_len >= *cap) + { + *cap = (next_len + *cap) * 2; + *unused_buffer = realloc(*unused_buffer, *cap); + } + memcpy(*unused_buffer + *size, next_str, next_len); + + htmc_set_unused_if_alloced(ha, next_str); + + *size = *size + next_len; + } + + (*unused_buffer)[*size] = '\0'; + return unused_buffer_idx; +} + +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs) +{ + size_t unused_buffer_idx = htmc_get_unused(ha, 16); + return htmc_concat_strings_into(ha, strs, unused_buffer_idx); +} + +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t append_to, HtmcStrsArr strs) +{ + char **append_to_str = &ha->buffers[ append_to ]; + size_t *len = &ha->sizes[ append_to ]; + size_t *cap = &ha->caps [ append_to ]; + + for(size_t i = 0 ; i < strs.nb ; i++) + { + char *next_str = strs.arr[i]; + size_t next_len = strlen(strs.arr[i]); + bool is_copy = (next_str == *append_to_str); + + if(*len + next_len >= *cap) + { + htmc_gurantee_cap(append_to_str, cap, (next_len + *cap) * 2); + } + + // if it's a copy of *append_to_str that means it might have been invalidate with the htmc_gurantee_cap + if(is_copy) + { + memmove(*append_to_str + *len, *append_to_str, next_len); + *len += next_len; + } + else + { + memmove(*append_to_str + *len, next_str, next_len); + *len += next_len; + + htmc_set_unused_if_alloced(ha, next_str); + } + } + + (*append_to_str)[*len] = '\0'; +} + +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **between_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + htmc_gurantee_cap(between_ptr, cap, needed_cap); + + memmove(*between_ptr + 1 + tag_len + 1, *between_ptr, between_len); + + memcpy(*between_ptr, "<", 1); + memcpy(*between_ptr + 1, tag, tag_len); + memcpy(*between_ptr + 1 + tag_len, ">", 1); + memcpy(*between_ptr + 1 + tag_len + 1 + between_len, "", 1); + (*between_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *between_ptr; +} + +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; + const char *tag = htmc_tags[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, needed_cap); + const char *between = ha->buffers[ str_idx ]; + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + size_t *cap = &ha->caps[ unused_buffer_idx ]; + size_t size = 0; + + memcpy(*unused_buffer, "<", 1); + size += 1; + + memcpy(*unused_buffer + size, tag, tag_len); + size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*cap <= size + attr_len + 1) // 1 for the spaces between each attribute + { + *unused_buffer = realloc(*unused_buffer, size + (attr_len * 2)); + *cap = size + (attr_len * 2); + } + memcpy(*unused_buffer + size, " ", 1); + size += 1; + memcpy(*unused_buffer + size, attrs.arr[i], attr_len); + size += attr_len; + } + + if(*cap <= size + 1 + between_len + 2 + tag_len + 1) + { + *unused_buffer = realloc(*unused_buffer, size + 1 + between_len + 2 + tag_len + 1 + 1); + *cap = size + 1 + between_len + 2 + tag_len + 1 + 1; + } + + memcpy(*unused_buffer + size, ">", 1); + size += 1; + + memcpy(*unused_buffer + size, between, between_len); + size += between_len; + + memcpy(*unused_buffer + size, "", 1); + size += 1; + + (*unused_buffer)[size] = '\0'; + + ha->sizes[ unused_buffer_idx ] = size; + ha->unused[ str_idx ] = true; + + return *unused_buffer; +} + +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id) +{ + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + memcpy(*unused_buffer + 1, tag, tag_len); + memcpy(*unused_buffer + 1 + tag_len, ">", 1); + (*unused_buffer)[ 1 + tag_len + 1 ] = '\0'; + + ha->sizes[ unused_buffer_idx ] = tag_len + 2; + + return *unused_buffer; +} + +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy) +{ + (void)dummy; + + const char *tag = htmc_tags[ tag_id ]; + const size_t tag_len = htmc_tag_lengths[ tag_id ]; + + size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + size_t *size = &ha->sizes[ unused_buffer_idx ]; + *size = 0; + size_t *cap = &ha->caps[ unused_buffer_idx ]; + + memcpy(*unused_buffer, "<", 1); + *size += 1; + + memcpy(*unused_buffer + 1, tag, tag_len); + *size += tag_len; + + // insert attributes here: + for(size_t i = 0 ; i < attrs.nb ; i++) + { + size_t attr_len = strlen(attrs.arr[i]); + if(*size + attr_len + 1 >= *cap) + { + *unused_buffer = realloc(*unused_buffer, (*size + attr_len) * 2); + *cap = (*size + attr_len) * 2; + } + + memcpy(*unused_buffer + *size, " ", 1); + *size += 1; + + memcpy(*unused_buffer + *size, attrs.arr[i], attr_len); + *size += attr_len; + } + + memcpy(*unused_buffer + *size, ">", 2); // 2 for the '\0' + *size += 1; + + return *unused_buffer; +} + +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + const size_t combined_strlen = ha->sizes[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + if(combined_strlen * nb >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, combined_strlen * nb + 1); + *cap = combined_strlen * nb + 1; + } + + for(uint32_t i = 1 ; i < nb ; i++) + { + memcpy(*combined_str_ptr + *size, *combined_str_ptr, combined_strlen); + *size += combined_strlen; + } + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +// should mod take idx? maybe leave that as the re-entrant version with void*, and let user handle idx +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs) +{ + size_t combined_str_idx = htmc_concat_strings(ha, strs); + + size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); + + size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); + + char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; + size_t *cap = &ha->caps[ combined_str_idx ]; + size_t *size = &ha->sizes[ combined_str_idx ]; + + char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; + const char *iter_copy = *iter_copy_buffer; + const size_t copy_len = *size; + + char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; + **unused_buffer = '\0'; + size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; + + for(uint32_t i = 0 ; i < nb ; i++) + { + mod(iter_copy, copy_len, unused_buffer, unused_cap, i, arg); + size_t modified_len = strlen(*unused_buffer); + + if(modified_len + *size >= *cap) + { + *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); + *cap = *size + (modified_len * 2); + } + + memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); + + *size += modified_len; + } + + ha->unused[ iter_copy_idx ] = true; + ha->unused[ unused_buffer_idx ] = true; + + (*combined_str_ptr)[*size] = '\0'; + + return *combined_str_ptr; +} + +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t len = ha->sizes[ str_idx ]; + size_t unused_buffer_idx = htmc_get_unused(ha, len + 1); + char **dup = &ha->buffers[ unused_buffer_idx ]; + + memcpy(*dup, ha->buffers[ str_idx ], len + 1); + + ha->sizes[ unused_buffer_idx ] = len; + + return unused_buffer_idx; +} + +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx) +{ + size_t idx = htmc_strdup(ha, str_idx); + return ha->buffers[ idx ]; +} + +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + + va_list args_copy1; + va_copy(args_copy1, args); + + int str_len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + + size_t unused_buffer_idx = htmc_get_unused(ha, str_len + 1); + char **unused = &ha->buffers[ unused_buffer_idx ]; + ha->sizes[ unused_buffer_idx ] = str_len; + + vsnprintf(*unused, str_len + 1, fmt, args_copy1); + va_end(args_copy1); + + htmc_set_unused_if_alloced(ha, fmt); + + return *unused; +} + +// TODO check in the string for '--' and report error +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx) +{ + const size_t between_len = ha->sizes[ str_idx ]; + char **buffer_ptr = &ha->buffers[ str_idx ]; + size_t *cap = &ha->caps[ str_idx ]; + const size_t comment_start_len = 4; + const size_t comment_end_len = 3; + const size_t needed_cap = comment_start_len + between_len + comment_end_len + 1; + + htmc_gurantee_cap(buffer_ptr, cap, needed_cap); + + memmove(*buffer_ptr + comment_start_len, *buffer_ptr, between_len); + + memcpy(*buffer_ptr, "", 3); + (*buffer_ptr)[ needed_cap - 1 ] = '\0'; + + ha->sizes[ str_idx ] = needed_cap - 1; + + return *buffer_ptr; +} + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap) +{ + if(*cap < new_cap) + { + *buffer = realloc(*buffer, new_cap); + *cap = new_cap; + } +} + +#endif /* HTMC_C */ diff --git a/example/scalalib/native/4-common-config/native-src/htmc.h b/example/scalalib/native/4-common-config/native-src/htmc.h new file mode 100644 index 00000000000..c7be0829643 --- /dev/null +++ b/example/scalalib/native/4-common-config/native-src/htmc.h @@ -0,0 +1,586 @@ +#ifndef HTMC_H +#define HTMC_H + +#include +#include +#include +#include +#include +#include + +typedef struct +{ + size_t nb; + bool *unused; + size_t *caps; + size_t *sizes; + char **buffers; +} HtmcAllocations; + +typedef struct +{ + char **arr; + size_t nb; +} HtmcStrsArr; + +#define htmc(...) \ +({ \ + const size_t init_cap = 4; \ + HtmcAllocations htmc_ha = { \ + .nb = init_cap, \ + .buffers = calloc(init_cap, sizeof(char*)), \ + .caps = calloc(init_cap, sizeof(size_t)), \ + .sizes = calloc(init_cap, sizeof(size_t)), \ + .unused = malloc(init_cap * sizeof(bool)), \ + }; \ + memset(htmc_ha.unused, 1, init_cap * sizeof(bool)); \ + size_t ret_idx = htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__)); \ + char *ret = htmc_ha.buffers[ ret_idx ]; \ + htmc_cleanup_unused_buffers(&htmc_ha, ret_idx); \ + ret; \ +}) + +#define htmc_strsarr(...) (HtmcStrsArr){.arr=(char*[]){__VA_ARGS__}, .nb=sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)} + +#define htmc_repeat(nb, ...) htmc_repeat_(&htmc_ha, nb, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify(nb, mod, ...) htmc_repeat_modify_(&htmc_ha, nb, mod, htmc_strsarr(__VA_ARGS__)) +#define htmc_repeat_modify_r(nb, mod, ctx, ...) htmc_repeat_modify_r_(&htmc_ha, nb, mod, ctx, htmc_strsarr(__VA_ARGS__)) + +#define htmc_fmt(fmt, ...) htmc_fmt_(&htmc_ha, fmt, ##__VA_ARGS__) + +#define htmc_ccode(...) \ +({ \ + size_t htmc_ccode_yielded_idx = htmc_get_unused(&htmc_ha, 16); \ + htmc_ha.sizes[ htmc_ccode_yielded_idx ] = 0; \ + htmc_ha.buffers[ htmc_ccode_yielded_idx ][0] = '\0'; \ + __VA_ARGS__ \ + char *htmc_ccode_yielded = htmc_ha.buffers[ htmc_ccode_yielded_idx ]; \ + htmc_ccode_yielded; \ +}) +#define htmc_yield(...) htmc_append_to_buffer_idx(&htmc_ha, htmc_ccode_yielded_idx, htmc_strsarr(__VA_ARGS__)) +#define htmc_yielded htmc_ha.buffers[ htmc_ccode_yielded_idx ] +#define htmc_yielded_len htmc_ha.sizes[ htmc_ccode_yielded_idx ] + +#define htmc_attr_(...) \ +htmc_strsarr(__VA_ARGS__))) + +#define htmc_attr(tag, ...) \ +_Generic(&(char[htmc_is_single_tag(htmc_id_##tag) + 1]){ 0 } , \ + char(*)[1]: htmc_surround_by_tag_with_attrs, \ + char(*)[2]: htmc_make_tag_with_attrs \ +)(&htmc_ha, htmc_id_##tag, htmc_strsarr(__VA_ARGS__), htmc_concat_strings(&htmc_ha, htmc_attr_ + +#define htmc_strlit(...) #__VA_ARGS__ + +#define htmc_is_single_tag(id) \ +(id == (htmc_id_area || htmc_id_base || htmc_id_br || htmc_id_col || htmc_id_embed || htmc_id_hr || htmc_id_img || htmc_id_input || htmc_id_link || htmc_id_meta || htmc_id_param || htmc_id_source || htmc_id_track || htmc_id_wbr)) + +#define htmc_doctypehtml ("") + +#define htmc_comment(...) htmc_comment_(&htmc_ha, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that need a closing tag: +#define htmc_a(...) htmc_surround_by_tag(&htmc_ha, 0, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_abbr(...) htmc_surround_by_tag(&htmc_ha, 1, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_address(...) htmc_surround_by_tag(&htmc_ha, 2, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_article(...) htmc_surround_by_tag(&htmc_ha, 4, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_aside(...) htmc_surround_by_tag(&htmc_ha, 5, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_audio(...) htmc_surround_by_tag(&htmc_ha, 6, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_b(...) htmc_surround_by_tag(&htmc_ha, 7, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdi(...) htmc_surround_by_tag(&htmc_ha, 9, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_bdo(...) htmc_surround_by_tag(&htmc_ha, 10, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_blockquote(...) htmc_surround_by_tag(&htmc_ha, 11, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_body(...) htmc_surround_by_tag(&htmc_ha, 12, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_button(...) htmc_surround_by_tag(&htmc_ha, 14, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_canvas(...) htmc_surround_by_tag(&htmc_ha, 15, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_caption(...) htmc_surround_by_tag(&htmc_ha, 16, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_cite(...) htmc_surround_by_tag(&htmc_ha, 17, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_code(...) htmc_surround_by_tag(&htmc_ha, 18, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_colgroup(...) htmc_surround_by_tag(&htmc_ha, 20, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_data(...) htmc_surround_by_tag(&htmc_ha, 21, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_datalist(...) htmc_surround_by_tag(&htmc_ha, 22, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dd(...) htmc_surround_by_tag(&htmc_ha, 23, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_del(...) htmc_surround_by_tag(&htmc_ha, 24, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_details(...) htmc_surround_by_tag(&htmc_ha, 25, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dfn(...) htmc_surround_by_tag(&htmc_ha, 26, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dialog(...) htmc_surround_by_tag(&htmc_ha, 27, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_div(...) htmc_surround_by_tag(&htmc_ha, 28, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dl(...) htmc_surround_by_tag(&htmc_ha, 29, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_dt(...) htmc_surround_by_tag(&htmc_ha, 30, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_em(...) htmc_surround_by_tag(&htmc_ha, 31, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_fieldset(...) htmc_surround_by_tag(&htmc_ha, 33, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figcaption(...) htmc_surround_by_tag(&htmc_ha, 34, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_figure(...) htmc_surround_by_tag(&htmc_ha, 35, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_footer(...) htmc_surround_by_tag(&htmc_ha, 36, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_form(...) htmc_surround_by_tag(&htmc_ha, 37, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h1(...) htmc_surround_by_tag(&htmc_ha, 38, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h2(...) htmc_surround_by_tag(&htmc_ha, 39, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h3(...) htmc_surround_by_tag(&htmc_ha, 40, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h4(...) htmc_surround_by_tag(&htmc_ha, 41, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h5(...) htmc_surround_by_tag(&htmc_ha, 42, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_h6(...) htmc_surround_by_tag(&htmc_ha, 43, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_head(...) htmc_surround_by_tag(&htmc_ha, 44, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_header(...) htmc_surround_by_tag(&htmc_ha, 45, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_hgroup(...) htmc_surround_by_tag(&htmc_ha, 46, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_html(...) htmc_surround_by_tag(&htmc_ha, 48, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_i(...) htmc_surround_by_tag(&htmc_ha, 49, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_iframe(...) htmc_surround_by_tag(&htmc_ha, 50, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ins(...) htmc_surround_by_tag(&htmc_ha, 53, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_kbd(...) htmc_surround_by_tag(&htmc_ha, 54, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_label(...) htmc_surround_by_tag(&htmc_ha, 55, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_legend(...) htmc_surround_by_tag(&htmc_ha, 56, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_li(...) htmc_surround_by_tag(&htmc_ha, 57, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_main(...) htmc_surround_by_tag(&htmc_ha, 59, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_map(...) htmc_surround_by_tag(&htmc_ha, 60, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_mark(...) htmc_surround_by_tag(&htmc_ha, 61, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_math(...) htmc_surround_by_tag(&htmc_ha, 62, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_menu(...) htmc_surround_by_tag(&htmc_ha, 63, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_meter(...) htmc_surround_by_tag(&htmc_ha, 65, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_nav(...) htmc_surround_by_tag(&htmc_ha, 66, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_noscript(...) htmc_surround_by_tag(&htmc_ha, 67, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_object(...) htmc_surround_by_tag(&htmc_ha, 68, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ol(...) htmc_surround_by_tag(&htmc_ha, 69, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_optgroup(...) htmc_surround_by_tag(&htmc_ha, 70, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_option(...) htmc_surround_by_tag(&htmc_ha, 71, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_output(...) htmc_surround_by_tag(&htmc_ha, 72, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_p(...) htmc_surround_by_tag(&htmc_ha, 73, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_picture(...) htmc_surround_by_tag(&htmc_ha, 75, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_pre(...) htmc_surround_by_tag(&htmc_ha, 76, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_progress(...) htmc_surround_by_tag(&htmc_ha, 77, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_q(...) htmc_surround_by_tag(&htmc_ha, 78, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rp(...) htmc_surround_by_tag(&htmc_ha, 79, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_rt(...) htmc_surround_by_tag(&htmc_ha, 80, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ruby(...) htmc_surround_by_tag(&htmc_ha, 81, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_s(...) htmc_surround_by_tag(&htmc_ha, 82, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_samp(...) htmc_surround_by_tag(&htmc_ha, 83, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_script(...) htmc_surround_by_tag(&htmc_ha, 84, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_section(...) htmc_surround_by_tag(&htmc_ha, 85, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_select(...) htmc_surround_by_tag(&htmc_ha, 86, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_slot(...) htmc_surround_by_tag(&htmc_ha, 87, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_small(...) htmc_surround_by_tag(&htmc_ha, 88, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_span(...) htmc_surround_by_tag(&htmc_ha, 90, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_strong(...) htmc_surround_by_tag(&htmc_ha, 91, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_style(...) htmc_surround_by_tag(&htmc_ha, 92, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sub(...) htmc_surround_by_tag(&htmc_ha, 93, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_summary(...) htmc_surround_by_tag(&htmc_ha, 94, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_sup(...) htmc_surround_by_tag(&htmc_ha, 95, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_svg(...) htmc_surround_by_tag(&htmc_ha, 96, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_table(...) htmc_surround_by_tag(&htmc_ha, 97, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tbody(...) htmc_surround_by_tag(&htmc_ha, 98, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_td(...) htmc_surround_by_tag(&htmc_ha, 99, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_template(...) htmc_surround_by_tag(&htmc_ha, 100, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_textarea(...) htmc_surround_by_tag(&htmc_ha, 101, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tfoot(...) htmc_surround_by_tag(&htmc_ha, 102, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_th(...) htmc_surround_by_tag(&htmc_ha, 103, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_thead(...) htmc_surround_by_tag(&htmc_ha, 104, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_time(...) htmc_surround_by_tag(&htmc_ha, 105, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_title(...) htmc_surround_by_tag(&htmc_ha, 106, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_tr(...) htmc_surround_by_tag(&htmc_ha, 107, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_u(...) htmc_surround_by_tag(&htmc_ha, 109, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_ul(...) htmc_surround_by_tag(&htmc_ha, 110, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_var(...) htmc_surround_by_tag(&htmc_ha, 111, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) +#define htmc_video(...) htmc_surround_by_tag(&htmc_ha, 112, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) + +// tags that don't terminate +#define htmc_area(...) htmc_make_tag_with_attrs(&htmc_ha, 3, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_base(...) htmc_make_tag_with_attrs(&htmc_ha, 8, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_br(...) htmc_make_tag_with_attrs(&htmc_ha, 13, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_col(...) htmc_make_tag_with_attrs(&htmc_ha, 19, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_embed(...) htmc_make_tag_with_attrs(&htmc_ha, 32, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_hr(...) htmc_make_tag_with_attrs(&htmc_ha, 47, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_img(...) htmc_make_tag_with_attrs(&htmc_ha, 51, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_input(...) htmc_make_tag_with_attrs(&htmc_ha, 52, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_link(...) htmc_make_tag_with_attrs(&htmc_ha, 58, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_meta(...) htmc_make_tag_with_attrs(&htmc_ha, 64, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_param(...) htmc_make_tag_with_attrs(&htmc_ha, 74, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_source(...) htmc_make_tag_with_attrs(&htmc_ha, 89, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_track(...) htmc_make_tag_with_attrs(&htmc_ha, 108, htmc_strsarr(__VA_ARGS__), NULL) +#define htmc_wbr(...) htmc_make_tag_with_attrs(&htmc_ha, 113, htmc_strsarr(__VA_ARGS__), NULL) + +#define htmc_id_a 0 +#define htmc_id_abbr 1 +#define htmc_id_address 2 +#define htmc_id_area 3 +#define htmc_id_article 4 +#define htmc_id_aside 5 +#define htmc_id_audio 6 +#define htmc_id_b 7 +#define htmc_id_base 8 +#define htmc_id_bdi 9 +#define htmc_id_bdo 10 +#define htmc_id_blockquote 11 +#define htmc_id_body 12 +#define htmc_id_br 13 +#define htmc_id_button 14 +#define htmc_id_canvas 15 +#define htmc_id_caption 16 +#define htmc_id_cite 17 +#define htmc_id_code 18 +#define htmc_id_col 19 +#define htmc_id_colgroup 20 +#define htmc_id_data 21 +#define htmc_id_datalist 22 +#define htmc_id_dd 23 +#define htmc_id_del 24 +#define htmc_id_details 25 +#define htmc_id_dfn 26 +#define htmc_id_dialog 27 +#define htmc_id_div 28 +#define htmc_id_dl 29 +#define htmc_id_dt 30 +#define htmc_id_em 31 +#define htmc_id_embed 32 +#define htmc_id_fieldset 33 +#define htmc_id_figcaption 34 +#define htmc_id_figure 35 +#define htmc_id_footer 36 +#define htmc_id_form 37 +#define htmc_id_h1 38 +#define htmc_id_h2 39 +#define htmc_id_h3 40 +#define htmc_id_h4 41 +#define htmc_id_h5 42 +#define htmc_id_h6 43 +#define htmc_id_head 44 +#define htmc_id_header 45 +#define htmc_id_hgroup 46 +#define htmc_id_hr 47 +#define htmc_id_html 48 +#define htmc_id_i 49 +#define htmc_id_iframe 50 +#define htmc_id_img 51 +#define htmc_id_input 52 +#define htmc_id_ins 53 +#define htmc_id_kbd 54 +#define htmc_id_label 55 +#define htmc_id_legend 56 +#define htmc_id_li 57 +#define htmc_id_link 58 +#define htmc_id_main 59 +#define htmc_id_map 60 +#define htmc_id_mark 61 +#define htmc_id_math 62 +#define htmc_id_menu 63 +#define htmc_id_meta 64 +#define htmc_id_meter 65 +#define htmc_id_nav 66 +#define htmc_id_noscript 67 +#define htmc_id_object 68 +#define htmc_id_ol 69 +#define htmc_id_optgroup 70 +#define htmc_id_option 71 +#define htmc_id_output 72 +#define htmc_id_p 73 +#define htmc_id_param 74 +#define htmc_id_picture 75 +#define htmc_id_pre 76 +#define htmc_id_progress 77 +#define htmc_id_q 78 +#define htmc_id_rp 79 +#define htmc_id_rt 80 +#define htmc_id_ruby 81 +#define htmc_id_s 82 +#define htmc_id_samp 83 +#define htmc_id_script 84 +#define htmc_id_section 85 +#define htmc_id_select 86 +#define htmc_id_slot 87 +#define htmc_id_small 88 +#define htmc_id_source 89 +#define htmc_id_span 90 +#define htmc_id_strong 91 +#define htmc_id_style 92 +#define htmc_id_sub 93 +#define htmc_id_summary 94 +#define htmc_id_sup 95 +#define htmc_id_svg 96 +#define htmc_id_table 97 +#define htmc_id_tbody 98 +#define htmc_id_td 99 +#define htmc_id_template 100 +#define htmc_id_textarea 101 +#define htmc_id_tfoot 102 +#define htmc_id_th 103 +#define htmc_id_thead 104 +#define htmc_id_time 105 +#define htmc_id_title 106 +#define htmc_id_tr 107 +#define htmc_id_track 108 +#define htmc_id_u 109 +#define htmc_id_ul 110 +#define htmc_id_var 111 +#define htmc_id_video 112 +#define htmc_id_wbr 113 + +void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx); +size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer); +void htmc_grow_buffers(HtmcAllocations *ha); +void htmc_set_unused(HtmcAllocations *ha, const char *str); +void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str); +size_t htmc_find_unused(const HtmcAllocations *ha); +size_t htmc_get_unused(HtmcAllocations *ha, size_t with_size); +size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs); +char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx); +char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx); +char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id); +char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy); +char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs); +char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs); +char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs); +char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...); +void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t buffer_idx, HtmcStrsArr strs); +size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx); +char *htmc_comment_(HtmcAllocations *ha, size_t str_idx); + +void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap); + +#endif + +#ifdef HTMC_PREFIX + +#undef HTMC_PREFIX + +#undef doctypehtml + +#undef comment + +#undef a +#undef abbr +#undef address +#undef area +#undef article +#undef aside +#undef audio +#undef b +#undef base +#undef bdi +#undef bdo +#undef blockquote +#undef body +#undef br +#undef button +#undef canvas +#undef caption +#undef cite +#undef code +#undef col +#undef colgroup +#undef data +#undef datalist +#undef dd +#undef del +#undef details +#undef dfn +#undef dialog +#undef div +#undef dl +#undef dt +#undef em +#undef embed +#undef fieldset +#undef figcaption +#undef figure +#undef footer +#undef form +#undef h1 +#undef h2 +#undef h3 +#undef h4 +#undef h5 +#undef h6 +#undef head +#undef header +#undef hgroup +#undef hr +#undef html +#undef i +#undef iframe +#undef img +#undef input +#undef ins +#undef kbd +#undef label +#undef legend +#undef li +#undef link +#undef map +#undef mark +#undef math +#undef menu +#undef meta +#undef meter +#undef nav +#undef noscript +#undef object +#undef ol +#undef optgroup +#undef option +#undef output +#undef p +#undef param +#undef picture +#undef pre +#undef progress +#undef q +#undef rp +#undef rt +#undef ruby +#undef s +#undef samp +#undef script +#undef section +#undef select +#undef slot +#undef small +#undef source +#undef span +#undef strong +#undef style +#undef sub +#undef summary +#undef sup +#undef svg +#undef table +#undef tbody +#undef td +#undef template +#undef textarea +#undef tfoot +#undef th +#undef thead +#undef time +#undef title +#undef tr +#undef track +#undef u +#undef ul +#undef var +#undef video +#undef wbr + +#undef attr + +#else + +#define doctypehtml htmc_doctypehtml + +#define comment htmc_comment + +#define a(...) htmc_a(__VA_ARGS__) +#define abbr(...) htmc_abbr(__VA_ARGS__) +#define address(...) htmc_address(__VA_ARGS__) +#define area(...) htmc_area(__VA_ARGS__) +#define article(...) htmc_article(__VA_ARGS__) +#define aside(...) htmc_aside(__VA_ARGS__) +#define audio(...) htmc_audio(__VA_ARGS__) +#define b(...) htmc_b(__VA_ARGS__) +#define base(...) htmc_base(__VA_ARGS__) +#define bdi(...) htmc_bdi(__VA_ARGS__) +#define bdo(...) htmc_bdo(__VA_ARGS__) +#define blockquote(...) htmc_blockquote(__VA_ARGS__) +#define body(...) htmc_body(__VA_ARGS__) +#define br(...) htmc_br(__VA_ARGS__) +#define button(...) htmc_button(__VA_ARGS__) +#define canvas(...) htmc_canvas(__VA_ARGS__) +#define caption(...) htmc_caption(__VA_ARGS__) +#define cite(...) htmc_cite(__VA_ARGS__) +#define code(...) htmc_code(__VA_ARGS__) +#define col(...) htmc_col(__VA_ARGS__) +#define colgroup(...) htmc_colgroup(__VA_ARGS__) +#define data(...) htmc_data(__VA_ARGS__) +#define datalist(...) htmc_datalist(__VA_ARGS__) +#define dd(...) htmc_dd(__VA_ARGS__) +#define del(...) htmc_del(__VA_ARGS__) +#define details(...) htmc_details(__VA_ARGS__) +#define dfn(...) htmc_dfn(__VA_ARGS__) +#define dialog(...) htmc_dialog(__VA_ARGS__) +#define div(...) htmc_div(__VA_ARGS__) +#define dl(...) htmc_dl(__VA_ARGS__) +#define dt(...) htmc_dt(__VA_ARGS__) +#define em(...) htmc_em(__VA_ARGS__) +#define embed(...) htmc_embed(__VA_ARGS__) +#define fieldset(...) htmc_fieldset(__VA_ARGS__) +#define figcaption(...) htmc_figcaption(__VA_ARGS__) +#define figure(...) htmc_figure(__VA_ARGS__) +#define footer(...) htmc_footer(__VA_ARGS__) +#define form(...) htmc_form(__VA_ARGS__) +#define h1(...) htmc_h1(__VA_ARGS__) +#define h2(...) htmc_h2(__VA_ARGS__) +#define h3(...) htmc_h3(__VA_ARGS__) +#define h4(...) htmc_h4(__VA_ARGS__) +#define h5(...) htmc_h5(__VA_ARGS__) +#define h6(...) htmc_h6(__VA_ARGS__) +#define head(...) htmc_head(__VA_ARGS__) +#define header(...) htmc_header(__VA_ARGS__) +#define hgroup(...) htmc_hgroup(__VA_ARGS__) +#define hr(...) htmc_hr(__VA_ARGS__) +#define html(...) htmc_html(__VA_ARGS__) +#define i(...) htmc_i(__VA_ARGS__) +#define iframe(...) htmc_iframe(__VA_ARGS__) +#define img(...) htmc_img(__VA_ARGS__) +#define input(...) htmc_input(__VA_ARGS__) +#define ins(...) htmc_ins(__VA_ARGS__) +#define kbd(...) htmc_kbd(__VA_ARGS__) +#define label(...) htmc_label(__VA_ARGS__) +#define legend(...) htmc_legend(__VA_ARGS__) +#define li(...) htmc_li(__VA_ARGS__) +#define link(...) htmc_link(__VA_ARGS__) +#define map(...) htmc_map(__VA_ARGS__) +#define mark(...) htmc_mark(__VA_ARGS__) +#define math(...) htmc_math(__VA_ARGS__) +#define menu(...) htmc_menu(__VA_ARGS__) +#define meta(...) htmc_meta(__VA_ARGS__) +#define meter(...) htmc_meter(__VA_ARGS__) +#define nav(...) htmc_nav(__VA_ARGS__) +#define noscript(...) htmc_noscript(__VA_ARGS__) +#define object(...) htmc_object(__VA_ARGS__) +#define ol(...) htmc_ol(__VA_ARGS__) +#define optgroup(...) htmc_optgroup(__VA_ARGS__) +#define option(...) htmc_option(__VA_ARGS__) +#define output(...) htmc_output(__VA_ARGS__) +#define p(...) htmc_p(__VA_ARGS__) +#define param(...) htmc_param(__VA_ARGS__) +#define picture(...) htmc_picture(__VA_ARGS__) +#define pre(...) htmc_pre(__VA_ARGS__) +#define progress(...) htmc_progress(__VA_ARGS__) +#define q(...) htmc_q(__VA_ARGS__) +#define rp(...) htmc_rp(__VA_ARGS__) +#define rt(...) htmc_rt(__VA_ARGS__) +#define ruby(...) htmc_ruby(__VA_ARGS__) +#define s(...) htmc_s(__VA_ARGS__) +#define samp(...) htmc_samp(__VA_ARGS__) +#define script(...) htmc_script(__VA_ARGS__) +#define section(...) htmc_section(__VA_ARGS__) +#define select(...) htmc_select(__VA_ARGS__) +#define slot(...) htmc_slot(__VA_ARGS__) +#define small(...) htmc_small(__VA_ARGS__) +#define source(...) htmc_source(__VA_ARGS__) +#define span(...) htmc_span(__VA_ARGS__) +#define strong(...) htmc_strong(__VA_ARGS__) +#define style(...) htmc_style(__VA_ARGS__) +#define sub(...) htmc_sub(__VA_ARGS__) +#define summary(...) htmc_summary(__VA_ARGS__) +#define sup(...) htmc_sup(__VA_ARGS__) +#define svg(...) htmc_svg(__VA_ARGS__) +#define table(...) htmc_table(__VA_ARGS__) +#define tbody(...) htmc_tbody(__VA_ARGS__) +#define td(...) htmc_td(__VA_ARGS__) +#define template(...) htmc_template(__VA_ARGS__) +#define textarea(...) htmc_textarea(__VA_ARGS__) +#define tfoot(...) htmc_tfoot(__VA_ARGS__) +#define th(...) htmc_th(__VA_ARGS__) +#define thead(...) htmc_thead(__VA_ARGS__) +#define time(...) htmc_time(__VA_ARGS__) +#define title(...) htmc_title(__VA_ARGS__) +#define tr(...) htmc_tr(__VA_ARGS__) +#define track(...) htmc_track(__VA_ARGS__) +#define u(...) htmc_u(__VA_ARGS__) +#define ul(...) htmc_ul(__VA_ARGS__) +#define var(...) htmc_var(__VA_ARGS__) +#define video(...) htmc_video(__VA_ARGS__) +#define wbr(...) htmc_wbr(__VA_ARGS__) + +#define attr(...) htmc_attr(__VA_ARGS__) + +#endif diff --git a/example/scalalib/native/4-common-config/src/Foo.scala b/example/scalalib/native/4-common-config/src/Foo.scala new file mode 100644 index 00000000000..9c63ab32eaa --- /dev/null +++ b/example/scalalib/native/4-common-config/src/Foo.scala @@ -0,0 +1,21 @@ +package foo + +import scala.scalanative.unsafe._ + +object Bar { + def main(args: Array[String]): Unit = { + println("Running HelloWorld function") + val result = HelloWorld.generateHtml(c"Hello") + println(("Bar value:" + result) + println("Done...) + } +} + +// Define the external module, the C library containing our function "generateHtml" +@extern +@link("HelloWorld") +// Arbitrary object name +object HelloWorld { + // Name and signature of C function + def generateHtml(str: CString): CString = extern +} From 7cada7378e848d2ad082c5cde786b65ce856e8bc Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 6 Oct 2024 01:48:27 +0100 Subject: [PATCH 22/37] add doc file for scala-native examples --- .../ROOT/pages/scalalib/native-examples.adoc | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 docs/modules/ROOT/pages/scalalib/native-examples.adoc diff --git a/docs/modules/ROOT/pages/scalalib/native-examples.adoc b/docs/modules/ROOT/pages/scalalib/native-examples.adoc new file mode 100644 index 00000000000..7365f945d7c --- /dev/null +++ b/docs/modules/ROOT/pages/scalalib/native-examples.adoc @@ -0,0 +1,30 @@ += Scala Native Examples +:page-aliases: Web_Build_Examples.adoc, Scala_Web_Examples.adoc + +++++ + +++++ + + +This page contains examples of using Mill as a build tool for scala-native applications. +It covers setting up a basic basic scala-native application that calls C function within it, +as well as example of two modules with a scala-naive application. + +== Simple + +include::partial$example/scalalib/native/1-simple.adoc[] + +== Interop + +include::partial$example/scalalib/native/2-interop.adoc[] + +== Multi-Module + +include::partial$example/scalalib/native/3-multi-module.adoc[] + +== Common Config + +include::partial$example/scalalib/native/4-common-config.adoc[] + From bf2edb283b8a9d53d6f63c2cabae9deaa71b912e Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 6 Oct 2024 03:17:45 +0100 Subject: [PATCH 23/37] add draft build.mill for common-config example --- .../native/4-common-config/build.mill | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 example/scalalib/native/4-common-config/build.mill diff --git a/example/scalalib/native/4-common-config/build.mill b/example/scalalib/native/4-common-config/build.mill new file mode 100644 index 00000000000..ad15807aa2e --- /dev/null +++ b/example/scalalib/native/4-common-config/build.mill @@ -0,0 +1,128 @@ +// This example shows some of the common tasks you may want to override on a +// `{language}Module`: specifying the `mainClass`, adding additional +// sources/resources, generating resources, and setting compilation/run +// options. + +//// SNIPPET:BUILD +package build +import mill._, scalalib._ + +object `package` extends RootModule with ScalaModule { + def scalaVersion = "2.13.8" + def scalaNativeVersion = "0.5.5" + + // You can have arbitrary numbers of third-party dependencies + def ivyDeps = Agg( + ivy"com.lihaoyi::os-lib:0.10.7" + ) + + // Choose a main class to use for `.run` if there are multiple present + def mainClass: T[Option[String]] = Some("foo.Foo2") + + // Add (or replace) source folders for the module to use + def sources = Task.Sources{ + super.sources() ++ Seq(PathRef(millSourcePath / "custom-src")) + } + + // Add (or replace) resource folders for the module to use + def resources = Task.Sources{ + super.resources() ++ Seq(PathRef(millSourcePath / "custom-resources")) + } + + // Generate sources at build time + def generatedSources: T[Seq[PathRef]] = Task { + for(name <- Seq("A", "B", "C")) os.write( + Task.dest / s"Foo$name.scala", + s""" + |package foo + |object Foo$name { + | val value = "hello $name" + |} + """.stripMargin + ) + + Seq(PathRef(Task.dest)) + } + + // Pass additional JVM flags when `.run` is called or in the executable + // generated by `.assembly` + def forkArgs: T[Seq[String]] = Seq("-Dmy.custom.property=my-prop-value") + + // Pass additional environmental variables when `.run` is called. Note that + // this does not apply to running externally via `.assembly + def forkEnv: T[Map[String, String]] = Map("MY_CUSTOM_ENV" -> "my-env-value") + + // Additional Scala compiler options, e.g. to turn warnings into errors + def scalacOptions: T[Seq[String]] = Seq("-deprecation", "-Xfatal-warnings") +} +// If you want to better understand how the various upstream tasks feed into +// a task of interest, such as `run`, you can visualize their relationships via +/** Usage +> mill visualizePlan run +*/ +// +// image::VisualizePlanScala.svg[VisualizePlanScala.svg] +// +// (right-click open in new tab to see full sized) +// +//// SNIPPET:END +// +// +// Note the use of `millSourcePath`, `Task.dest`, and `PathRef` when preforming +// various filesystem operations: +// +// 1. `millSourcePath` refers to the base path of the module. For the root +// module, this is the root of the repo, and for inner modules it would be +// the module path e.g. for module `foo.bar.qux` the `millSourcePath` would +// be `foo/bar/qux`. This can also be overriden if necessary +// +// 2. `Task.dest` refers to the destination folder for a task in the `out/` +// folder. This is unique to each task, and can act as both a scratch space +// for temporary computations as well as a place to put "output" files, +// without worrying about filesystem conflicts with other tasks +// +// 3. `PathRef` is a way to return the *contents* of a file or folder, rather +// than just its path as a string. This ensures that downstream tasks +// properly invalidate when the contents changes even when the path stays +// the same + +/** Usage + +> mill run +Foo2.value:

hello2

+Foo.value:

hello

+FooA.value: hello A +FooB.value: hello B +FooC.value: hello C +MyResource: My Resource Contents +MyOtherResource: My Other Resource Contents +my.custom.property: my-prop-value +MY_CUSTOM_ENV: my-env-value + +> mill show assembly +".../out/assembly.dest/out.jar" + +> ./out/assembly.dest/out.jar # mac/linux +Foo2.value:

hello2

+Foo.value:

hello

+FooA.value: hello A +FooB.value: hello B +FooC.value: hello C +MyResource: My Resource Contents +MyOtherResource: My Other Resource Contents +my.custom.property: my-prop-value + +*/ + +//// SNIPPET:FATAL_WARNINGS + +/** Usage + +> sed -i.bak 's/Foo2 {/Foo2 { println(this + "hello")/g' custom-src/Foo2.scala + +> mill compile # demonstrate -deprecation/-Xfatal-warnings flags +error: object Foo2 { println(this + "hello") +error: ^ +error: ...Implicit injection of + is deprecated. Convert to String to call +... + +*/ From 8dc0853ddd3f2b009c55c5bd5aa96556d680a79e Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sun, 6 Oct 2024 13:37:22 +0100 Subject: [PATCH 24/37] update 1-simple example code --- example/scalalib/native/1-simple/src/Foo.scala | 12 ++++++++---- .../scalalib/native/1-simple/test/src/FooTests.scala | 5 +++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index 2de577a0280..68460a9cb6c 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -1,15 +1,19 @@ package foo + +import scala.scalanative.unsafe._ +import scala.scalanative.libc._ import scalatags.Text.all._ import mainargs.{main, ParserForMethods} + object Foo { - def generateHtml(text: String) = { - h1(text).toString + def generateHtml(text: CString) = { + h1(text).toCString } @main - def main(text: String) = { - println(generateHtml(text)) + def main(text: CString) = { + stdio.printf(generateHtml(text)) } def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) diff --git a/example/scalalib/native/1-simple/test/src/FooTests.scala b/example/scalalib/native/1-simple/test/src/FooTests.scala index 9dcd8bf4e04..b357ffe2d11 100644 --- a/example/scalalib/native/1-simple/test/src/FooTests.scala +++ b/example/scalalib/native/1-simple/test/src/FooTests.scala @@ -1,16 +1,17 @@ package foo +import scala.scalanative.unsafe._ import utest._ object FooTests extends TestSuite { def tests = Tests { test("simple") { - val result = Foo.generateHtml("hello") + val result = Foo.generateHtml(c"hello") assert(result == "

hello

") result } test("escaping") { - val result = Foo.generateHtml("") + val result = Foo.generateHtml(c"") assert(result == "

<hello>

") result } From a367eade5c981a8d75e9f11e04d20af97437efa1 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Mon, 7 Oct 2024 15:44:04 +0100 Subject: [PATCH 25/37] fix the errors in 1-simple and 2-interop examples --- example/scalalib/native/1-simple/build.mill | 4 --- .../scalalib/native/1-simple/src/Foo.scala | 20 +++++------ example/scalalib/native/2-interop/build.mill | 34 ++++++------------- .../native/2-interop/src/foo/HelloWorld.scala | 8 ++--- 4 files changed, 23 insertions(+), 43 deletions(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index 7b96b7c3d32..8e45a87311a 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -5,10 +5,6 @@ import mill._, scalalib._, scalanativelib._ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" - def ivyDeps = Agg( - ivy"com.lihaoyi::scalatags:0.12.0", - ivy"com.lihaoyi::mainargs:0.6.2" - ) object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index 68460a9cb6c..2ac77ff1e26 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -1,20 +1,18 @@ package foo - -import scala.scalanative.unsafe._ import scala.scalanative.libc._ -import scalatags.Text.all._ -import mainargs.{main, ParserForMethods} - +import scala.scalanative.unsafe._ object Foo { + def generateHtml(text: CString) = { - h1(text).toCString + stdio.printf(c"

%s

\n", text) } - @main - def main(text: CString) = { - stdio.printf(generateHtml(text)) + def main(args: Array[String]): Unit = { + implicit val z: Zone = Zone.open + val text = args(0) + generateHtml(toCString(text)) + z.close() } - - def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) } + diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill index b0a43a1f729..e69bb709e94 100644 --- a/example/scalalib/native/2-interop/build.mill +++ b/example/scalalib/native/2-interop/build.mill @@ -5,35 +5,21 @@ import mill._, scalalib._, scalanativelib._ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" - def nativeLinkingOptions = Seq("-L" + millSourcePath + "/output") - - // Additional source folder to put C sources - def nativeSources = T.sources(millSourcePath / "native-src") - - - - // Compile C - def nativeCompiled = T { - val cSourceFiles = nativeSources().map(_.path).flatMap(os.walk(_)).filter(_.ext == "c") - val output = "libhelloworld.so" - - os.proc( - "gcc", "-m64", "-shared", - "-c", cSourceFiles, - "-o", T.dest.toString + "/output" - ) - .call() - - - PathRef(T.dest / output) - } - - + object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") def testFramework = "utest.runner.Framework" + } + + def nativeLinkingOptions = Seq("-L" + millSourcePath.toString + "/target") + os.makeDir(millSourcePath / "target") + os.proc("gcc", "-m64", "-shared", + "-c", millSourcePath.toString + "/native-src/HelloWorld.c", + "-o", millSourcePath.toString + "/target/libHelloWorld.so" + ).call(stdout = os.Inherit) + } //// SNIPPET:END diff --git a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala index 39732d095c7..55bf43573bd 100644 --- a/example/scalalib/native/2-interop/src/foo/HelloWorld.scala +++ b/example/scalalib/native/2-interop/src/foo/HelloWorld.scala @@ -1,12 +1,11 @@ package foo +import scala.scalanative.libc._ import scala.scalanative.unsafe._ object Main { def main(args: Array[String]): Unit = { - print("Running HelloWorld function\n") - val input = c"Hello, World!!\n" - val reversed = HelloWorld.reverseString(input) - println(c"Reversed: %s", reversed) + println("Running HelloWorld function") + stdio.printf(c"Reversed: %s\n", HelloWorld.reverseString(c"Hello, World!")) println("Done...") } } @@ -19,3 +18,4 @@ object HelloWorld { // Name and signature of C function def reverseString(str: CString): CString = extern } + From 55c143f174be4dff7e78280713f8f6f400d64f94 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Tue, 8 Oct 2024 05:23:00 +0100 Subject: [PATCH 26/37] add third party dependency to 1-simple --- example/scalalib/native/1-simple/build.mill | 5 +++++ example/scalalib/native/1-simple/src/Foo.scala | 14 ++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index 8e45a87311a..8f2e7d45ac5 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -6,6 +6,11 @@ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" + // You can have arbitrary numbers of third-party dependencies + def ivyDeps = Agg( + ivy"com.lihaoyi::fansi::0.5.0" + ) + object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") def testFramework = "utest.runner.Framework" diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index 2ac77ff1e26..75b271ab12c 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -1,18 +1,20 @@ package foo import scala.scalanative.libc._ import scala.scalanative.unsafe._ +import fansi._ object Foo { - def generateHtml(text: CString) = { - stdio.printf(c"

%s

\n", text) + def generateHtml(text: String) = { + val colored = fansi.Color.Green(text) + println(colored) + implicit val z: Zone = Zone.open + stdio.printf(c"

%s

\n", toCString(text)) + z.close() } def main(args: Array[String]): Unit = { - implicit val z: Zone = Zone.open val text = args(0) - generateHtml(toCString(text)) - z.close() + generateHtml(text) } } - From c37e9a05a41d4915ecb52e2350512f6b26d7bf3e Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Wed, 9 Oct 2024 10:10:33 +0100 Subject: [PATCH 27/37] update code to fix some errors --- .../scalalib/native/1-simple/src/Foo.scala | 13 +- .../native/1-simple/test/src/FooTests.scala | 9 +- .../native/3-multi-module/bar/src/Bar.scala | 12 +- .../scalalib/native/3-multi-module/build.mill | 23 + .../native/3-multi-module/foo/src/Foo.scala | 16 +- .../native/4-common-config/build.mill | 39 +- .../4-common-config/custom-src/Foo2.scala | 40 +- .../4-common-config/native-src/HelloWorld.c | 7 - .../native/4-common-config/native-src/htm.c | 547 ---------------- .../native/4-common-config/native-src/htmc.h | 586 ------------------ .../native/4-common-config/src/Foo.scala | 30 +- 11 files changed, 102 insertions(+), 1220 deletions(-) delete mode 100644 example/scalalib/native/4-common-config/native-src/HelloWorld.c delete mode 100644 example/scalalib/native/4-common-config/native-src/htm.c delete mode 100644 example/scalalib/native/4-common-config/native-src/htmc.h diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index 75b271ab12c..fb75bdcec5c 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -1,20 +1,23 @@ package foo + import scala.scalanative.libc._ import scala.scalanative.unsafe._ import fansi._ object Foo { - def generateHtml(text: String) = { - val colored = fansi.Color.Green(text) - println(colored) + def generateHtml(text: String): CString = { + val colored = Console.RED + "

" + text + "

" + Console.RESET + "\n" + implicit val z: Zone = Zone.open - stdio.printf(c"

%s

\n", toCString(text)) + val cResult = toCString(colored) z.close() + cResult } def main(args: Array[String]): Unit = { val text = args(0) - generateHtml(text) + stdio.printf(generateHtml(text)) // Now printing the result } } + diff --git a/example/scalalib/native/1-simple/test/src/FooTests.scala b/example/scalalib/native/1-simple/test/src/FooTests.scala index b357ffe2d11..767031ba814 100644 --- a/example/scalalib/native/1-simple/test/src/FooTests.scala +++ b/example/scalalib/native/1-simple/test/src/FooTests.scala @@ -6,14 +6,15 @@ import utest._ object FooTests extends TestSuite { def tests = Tests { test("simple") { - val result = Foo.generateHtml(c"hello") - assert(result == "

hello

") + val result = Foo.generateHtml("hello") + assert(result == c"

hello

") result } test("escaping") { - val result = Foo.generateHtml(c"") - assert(result == "

<hello>

") + val result = Foo.generateHtml("") + assert(result == c"

<hello>

") result } } } + diff --git a/example/scalalib/native/3-multi-module/bar/src/Bar.scala b/example/scalalib/native/3-multi-module/bar/src/Bar.scala index c066d709757..4be66c2d6c4 100644 --- a/example/scalalib/native/3-multi-module/bar/src/Bar.scala +++ b/example/scalalib/native/3-multi-module/bar/src/Bar.scala @@ -1,13 +1,17 @@ package bar -import scalatags.Text.all._ + +import scala.scalanative.libc._ import scala.scalanative.unsafe._ object Bar { def main(args: Array[String]): Unit = { println("Running HelloWorld function") - val result = HelloWorldBar.generateHtml(args(0)) - println(("Bar value:" + result) - println("Done...) + implitct val z: Zone = Zone.open + val input = toCString(ags(0)) + val result = HelloWorldBar.generateHtml(input) + stdio.printf(c"Bar value: %s", input) + z.close() + stdio.printf("Done...") } } diff --git a/example/scalalib/native/3-multi-module/build.mill b/example/scalalib/native/3-multi-module/build.mill index afb6a618d95..fa3c9ca19a3 100644 --- a/example/scalalib/native/3-multi-module/build.mill +++ b/example/scalalib/native/3-multi-module/build.mill @@ -5,6 +5,7 @@ import mill._, scalalib._, scalanativelib._ trait MyModule extends ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" + object test extends ScalaNativeTests { def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") def testFramework = "utest.runner.Framework" @@ -14,10 +15,32 @@ trait MyModule extends ScalaNativeModule { object foo extends MyModule { def moduleDeps = Seq(bar) def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0") + + os.proc("mkdir", millSourcePath.toString + "/target").call(stdout = os.Inherit) + + def nativeLinkingOptions = Seq("-L" + millSourcePath.toString + "/target") + + os.proc( + "gcc", "-m64", "-shared", "-fPIC", + millSourcePath.toString + "/native-src/HelloWorldFoo.c", millSourcePath.toString + "/native-src/htm.c", + "-o", millSourcePath.toString + "/target/libHelloWorldFoo.so" + ).call(stdout = os.Inherit) + } object bar extends MyModule { def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2") + + os.proc("mkdir", millSourcePath.toString + "/target").call(stdout = os.Inherit) + + def nativeLinkingOptions = Seq("-L" + millSourcePath.toString + "/target") + + os.proc( + "gcc", "-m64", "-shared", "-fPIC", + millSourcePath.toString + "/native-src/HelloWorldBar.c", millSourcePath.toString + "/native-src/htm.c", + "-o", millSourcePath.toString + "/target/libHelloWorldBar.so") + .call(stdout = os.Inherit) + } //// SNIPPET:END diff --git a/example/scalalib/native/3-multi-module/foo/src/Foo.scala b/example/scalalib/native/3-multi-module/foo/src/Foo.scala index 00dfb5c7f64..e078e472d01 100644 --- a/example/scalalib/native/3-multi-module/foo/src/Foo.scala +++ b/example/scalalib/native/3-multi-module/foo/src/Foo.scala @@ -1,13 +1,21 @@ package foo + +import scala.scalanative.libc._ import scala.scalanative.unsafe._ import mainargs.{main, ParserForMethods, arg} object Foo { @main - def main(@arg(name = "foo-text") fooText: CString, - @arg(name = "bar-text") barText: CString): Unit = { - println("Foo.value: " + HelloWorldFoo.generateHtml(fooText)) - println("Bar.value: " + bar.Bar.generateHtml(barText)) + def main(@arg(name = "foo-text") fooText: String, + @arg(name = "bar-text") barText: String): Unit = { + + implicit val z: Zone = Zone.open + val cFooText = toCString(fooText) + val cBarText = toCString(barText) + z.close + + stdio.printf("Foo.value: %s\n", HelloWorldFoo.generateHtml(cFooText)) + stdio.printf("Bar.value: %s\n", bar.Bar.generateHtml(cBarText)) } def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) diff --git a/example/scalalib/native/4-common-config/build.mill b/example/scalalib/native/4-common-config/build.mill index ad15807aa2e..c7a817d57e9 100644 --- a/example/scalalib/native/4-common-config/build.mill +++ b/example/scalalib/native/4-common-config/build.mill @@ -5,34 +5,24 @@ //// SNIPPET:BUILD package build -import mill._, scalalib._ +import mill._, scalalib._, scalanativelib._ -object `package` extends RootModule with ScalaModule { - def scalaVersion = "2.13.8" +object `package` extends RootModule with ScalaNativeModule { + def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" // You can have arbitrary numbers of third-party dependencies def ivyDeps = Agg( - ivy"com.lihaoyi::os-lib:0.10.7" + ivy"com.lihaoyi::fansi::0.5.0" ) // Choose a main class to use for `.run` if there are multiple present - def mainClass: T[Option[String]] = Some("foo.Foo2") - - // Add (or replace) source folders for the module to use - def sources = Task.Sources{ - super.sources() ++ Seq(PathRef(millSourcePath / "custom-src")) - } - - // Add (or replace) resource folders for the module to use - def resources = Task.Sources{ - super.resources() ++ Seq(PathRef(millSourcePath / "custom-resources")) - } - + //def mainClass: T[Option[String]] = Some("foo.Foo2") + // Generate sources at build time - def generatedSources: T[Seq[PathRef]] = Task { + def generatedSources: T[Seq[PathRef]] = T { for(name <- Seq("A", "B", "C")) os.write( - Task.dest / s"Foo$name.scala", + T.dest / s"Foo$name.scala", s""" |package foo |object Foo$name { @@ -41,20 +31,11 @@ object `package` extends RootModule with ScalaModule { """.stripMargin ) - Seq(PathRef(Task.dest)) + Seq(PathRef(T.dest)) } +} - // Pass additional JVM flags when `.run` is called or in the executable - // generated by `.assembly` - def forkArgs: T[Seq[String]] = Seq("-Dmy.custom.property=my-prop-value") - - // Pass additional environmental variables when `.run` is called. Note that - // this does not apply to running externally via `.assembly - def forkEnv: T[Map[String, String]] = Map("MY_CUSTOM_ENV" -> "my-env-value") - // Additional Scala compiler options, e.g. to turn warnings into errors - def scalacOptions: T[Seq[String]] = Seq("-deprecation", "-Xfatal-warnings") -} // If you want to better understand how the various upstream tasks feed into // a task of interest, such as `run`, you can visualize their relationships via /** Usage diff --git a/example/scalalib/native/4-common-config/custom-src/Foo2.scala b/example/scalalib/native/4-common-config/custom-src/Foo2.scala index 5e450d79bd2..5b6dc2a5641 100644 --- a/example/scalalib/native/4-common-config/custom-src/Foo2.scala +++ b/example/scalalib/native/4-common-config/custom-src/Foo2.scala @@ -1,32 +1,32 @@ package foo +import scala.scalanative.libc._ import scala.scalanative.unsafe._ +import fansi._ object Foo2 { - val value = generateHtml(c"hello2") - def main(args: Array[String]): Unit = { - println("Foo2.value: " + Foo2.value) - println("Foo.value: " + Foo.value) - println("FooA.value: " + FooA.value) - println("FooB.value: " + FooB.value) - println("FooC.value: " + FooC.value) + def generateHtml(text: String): CString = { + val colored = Console.RED + "

" + text + "

" + Console.RESET + "\n" - println("MyResource: " + os.read(os.resource / "MyResource.txt")) - println("MyOtherResource: " + os.read(os.resource / "MyOtherResource.txt")) + implicit val z: Zone = Zone.open + val cResult = toCString(colored) + z.close() + cResult + } - println("my.custom.property: " + sys.props("my.custom.property")) + val value = generateHtml("hello2") - if (sys.env.contains("MY_CUSTOM_ENV")) println("MY_CUSTOM_ENV: " + sys.env("MY_CUSTOM_ENV")) - } -} + def main(args: Array[String]): Unit = { + stdio.printf("Foo2.value: %s", Foo2.value) + stdio.printf("Foo.value: %s", Foo.value) + stdio.printf("FooA.value: %s", FooA.value) + stdio.printf("FooB.value: %s", FooB.value) + stdio.printf("FooC.value: %s", FooC.value) -// Define the external module, the C library containing our function "generateHtml" -@extern -@link("HelloWorld") -// Arbitrary object name -object HelloWorld { - // Name and signature of C function - def generateHtml(str: CString): CString = extern + println("MyResource: " + os.read(os.resource / "MyResource.txt")) + println("MyOtherResource: " + os.read(os.resource / "MyOtherResource.txt")) + } + } diff --git a/example/scalalib/native/4-common-config/native-src/HelloWorld.c b/example/scalalib/native/4-common-config/native-src/HelloWorld.c deleted file mode 100644 index 3fd48576930..00000000000 --- a/example/scalalib/native/4-common-config/native-src/HelloWorld.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "htmc.h" -#include - - -char* generateHtml(const char* text) { - return htmc(h1(text)); -} diff --git a/example/scalalib/native/4-common-config/native-src/htm.c b/example/scalalib/native/4-common-config/native-src/htm.c deleted file mode 100644 index 298492900d9..00000000000 --- a/example/scalalib/native/4-common-config/native-src/htm.c +++ /dev/null @@ -1,547 +0,0 @@ -#include "htmc.h" - -#ifndef HTMC_C -#define HTMC_C - -#include - -const char *htmc_tags[] = { -"a", "abbr", "address", "area", "article", "aside", "audio", "b", "base", "bdi", "bdo", "blockquote", "body", "br", "button", "canvas", "caption", "cite", "code", "col", "colgroup", "data", "datalist", "dd", "del", "details", "dfn", "dialog", "div", "dl", "dt", "em", "embed", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "head", "header", "hgroup", "hr", "html", "i", "iframe", "img", "input", "ins", "kbd", "label", "legend", "li", "link", "main", "map", "mark", "math", "menu", "meta", "meter", "nav", "noscript", "object", "ol", "optgroup", "option", "output", "p", "param", "picture", "pre", "progress", "q", "rp", "rt", "ruby", "s", "samp", "script", "section", "select", "slot", "small", "source", "span", "strong", "style", "sub", "summary", "sup", "svg", "table", "tbody", "td", "template", "textarea", "tfoot", "th", "thead", "time", "title", "tr", "track", "u", "ul", "var", "video", "wbr" -}; - -const uint32_t htmc_tag_lengths[] = { -sizeof("a") - 1, sizeof("abbr") - 1, sizeof("address") - 1, sizeof("area") - 1, sizeof("article") - 1, sizeof("aside") - 1, sizeof("audio") - 1, sizeof("b") - 1, sizeof("base") - 1, sizeof("bdi") - 1, sizeof("bdo") - 1, sizeof("blockquote") - 1, sizeof("body") - 1, sizeof("br") - 1, sizeof("button") - 1, sizeof("canvas") - 1, sizeof("caption") - 1, sizeof("cite") - 1, sizeof("code") - 1, sizeof("col") - 1, sizeof("colgroup") - 1, sizeof("data") - 1, sizeof("datalist") - 1, sizeof("dd") - 1, sizeof("del") - 1, sizeof("details") - 1, sizeof("dfn") - 1, sizeof("dialog") - 1, sizeof("div") - 1, sizeof("dl") - 1, sizeof("dt") - 1, sizeof("em") - 1, sizeof("embed") - 1, sizeof("fieldset") - 1, sizeof("figcaption") - 1, sizeof("figure") - 1, sizeof("footer") - 1, sizeof("form") - 1, sizeof("h1") - 1, sizeof("h2") - 1, sizeof("h3") - 1, sizeof("h4") - 1, sizeof("h5") - 1, sizeof("h6") - 1, sizeof("head") - 1, sizeof("header") - 1, sizeof("hgroup") - 1, sizeof("hr") - 1, sizeof("html") - 1, sizeof("i") - 1, sizeof("iframe") - 1, sizeof("img") - 1, sizeof("input") - 1, sizeof("ins") - 1, sizeof("kbd") - 1, sizeof("label") - 1, sizeof("legend") - 1, sizeof("li") - 1, sizeof("link") - 1, sizeof("main") - 1, sizeof("map") - 1, sizeof("mark") - 1, sizeof("math") - 1, sizeof("menu") - 1, sizeof("meta") - 1, sizeof("meter") - 1, sizeof("nav") - 1, sizeof("noscript") - 1, sizeof("object") - 1, sizeof("ol") - 1, sizeof("optgroup") - 1, sizeof("option") - 1, sizeof("output") - 1, sizeof("p") - 1, sizeof("param") - 1, sizeof("picture") - 1, sizeof("pre") - 1, sizeof("progress") - 1, sizeof("q") - 1, sizeof("rp") - 1, sizeof("rt") - 1, sizeof("ruby") - 1, sizeof("s") - 1, sizeof("samp") - 1, sizeof("script") - 1, sizeof("section") - 1, sizeof("select") - 1, sizeof("slot") - 1, sizeof("small") - 1, sizeof("source") - 1, sizeof("span") - 1, sizeof("strong") - 1, sizeof("style") - 1, sizeof("sub") - 1, sizeof("summary") - 1, sizeof("sup") - 1, sizeof("svg") - 1, sizeof("table") - 1, sizeof("tbody") - 1, sizeof("td") - 1, sizeof("template") - 1, sizeof("textarea") - 1, sizeof("tfoot") - 1, sizeof("th") - 1, sizeof("thead") - 1, sizeof("time") - 1, sizeof("title") - 1, sizeof("tr") - 1, sizeof("track") - 1, sizeof("u") - 1, sizeof("ul") - 1, sizeof("var") - 1, sizeof("video") - 1, sizeof("wbr") - 1 -}; - -void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx) -{ - size_t i = 0; - for( ; i != used_idx ; i++) - { - free(ha->buffers[i]); - } - for(i += 1; i < ha->nb ; i++) - { - free(ha->buffers[i]); - } - - free(ha->caps); - free(ha->sizes); - free(ha->unused); - free(ha->buffers); -} - -size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer) -{ - size_t i; - for(i = 0; i < ha->nb ; i++) - { - if(buffer == ha->buffers[i]) - break; - } - return i; -} - -void htmc_grow_buffers(HtmcAllocations *ha) -{ - ha->buffers = realloc(ha->buffers, ha->nb * 2 * sizeof(char*)); - memset(ha->buffers + ha->nb, 0, ha->nb * sizeof(char*)); - - ha->caps = realloc(ha->caps, ha->nb * 2 * sizeof(size_t)); - memset(ha->caps + ha->nb, 0, ha->nb * sizeof(size_t)); - - ha->sizes = realloc(ha->sizes, ha->nb * 2 * sizeof(size_t)); - memset(ha->sizes + ha->nb, 0, ha->nb * sizeof(size_t)); - - ha->unused = realloc(ha->unused, ha->nb * 2 * sizeof(bool)); - memset(ha->unused + ha->nb, 1, ha->nb * sizeof(bool)); - - ha->nb *= 2; -} - -void htmc_set_unused(HtmcAllocations *ha, const char *str) -{ - size_t idx = htmc_find_buffer(ha, str); - ha->unused[idx] = true; -} - -void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str) -{ - size_t found = htmc_find_buffer(ha, str); - if(found != ha->nb) - { - ha->unused[found] = true; - } -} - -size_t htmc_find_unused(const HtmcAllocations *ha) -{ - size_t first_unused; - - for(first_unused = 0 ; first_unused < ha->nb ; first_unused++) - { - if(ha->unused[first_unused]) - { - goto find_unused_and_alloced; - } - } - - // no unused buffers were found - return first_unused; - - find_unused_and_alloced: - for(size_t i = first_unused ; i < ha->nb ; i++) - { - if(ha->unused[i] && ha->caps[i] != 0) - { - return i; - } - } - - return first_unused; -} - -size_t htmc_get_unused(HtmcAllocations *ha, size_t with_cap) -{ - size_t unused_buffer_idx = htmc_find_unused(ha); - if(unused_buffer_idx == ha->nb) - { - unused_buffer_idx = ha->nb; - htmc_grow_buffers(ha); - - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - *unused_buffer = calloc(with_cap, sizeof(char)); - ha->caps[ unused_buffer_idx ] = with_cap; - } - else if(with_cap > ha->caps[ unused_buffer_idx ]) - { - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - *unused_buffer = realloc(*unused_buffer, with_cap); - ha->caps[ unused_buffer_idx ] = with_cap; - } - - ha->unused[ unused_buffer_idx ] = false; - - return unused_buffer_idx; -} - -size_t htmc_concat_strings_into(HtmcAllocations *ha, HtmcStrsArr strs, size_t unused_buffer_idx) -{ - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - - size_t *cap = &ha->caps[ unused_buffer_idx ]; - size_t *size = &ha->sizes[ unused_buffer_idx ]; - *size = 0; - - // if no strings were provided, return an empty string - if(strs.nb == 0) - { - if(*cap == 0) - { - *unused_buffer = calloc(1, sizeof(char)); - } - **unused_buffer = '\0'; - return unused_buffer_idx; - } - - for(size_t i = 0 ; i < strs.nb ; i++) - { - char *next_str = strs.arr[i]; - size_t next_len = strlen(next_str); - if(*size + next_len >= *cap) - { - *cap = (next_len + *cap) * 2; - *unused_buffer = realloc(*unused_buffer, *cap); - } - memcpy(*unused_buffer + *size, next_str, next_len); - - htmc_set_unused_if_alloced(ha, next_str); - - *size = *size + next_len; - } - - (*unused_buffer)[*size] = '\0'; - return unused_buffer_idx; -} - -size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs) -{ - size_t unused_buffer_idx = htmc_get_unused(ha, 16); - return htmc_concat_strings_into(ha, strs, unused_buffer_idx); -} - -void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t append_to, HtmcStrsArr strs) -{ - char **append_to_str = &ha->buffers[ append_to ]; - size_t *len = &ha->sizes[ append_to ]; - size_t *cap = &ha->caps [ append_to ]; - - for(size_t i = 0 ; i < strs.nb ; i++) - { - char *next_str = strs.arr[i]; - size_t next_len = strlen(strs.arr[i]); - bool is_copy = (next_str == *append_to_str); - - if(*len + next_len >= *cap) - { - htmc_gurantee_cap(append_to_str, cap, (next_len + *cap) * 2); - } - - // if it's a copy of *append_to_str that means it might have been invalidate with the htmc_gurantee_cap - if(is_copy) - { - memmove(*append_to_str + *len, *append_to_str, next_len); - *len += next_len; - } - else - { - memmove(*append_to_str + *len, next_str, next_len); - *len += next_len; - - htmc_set_unused_if_alloced(ha, next_str); - } - } - - (*append_to_str)[*len] = '\0'; -} - -char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx) -{ - const size_t between_len = ha->sizes[ str_idx ]; - char **between_ptr = &ha->buffers[ str_idx ]; - size_t *cap = &ha->caps[ str_idx ]; - const size_t tag_len = htmc_tag_lengths[ tag_id ]; - const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; - const char *tag = htmc_tags[ tag_id ]; - - htmc_gurantee_cap(between_ptr, cap, needed_cap); - - memmove(*between_ptr + 1 + tag_len + 1, *between_ptr, between_len); - - memcpy(*between_ptr, "<", 1); - memcpy(*between_ptr + 1, tag, tag_len); - memcpy(*between_ptr + 1 + tag_len, ">", 1); - memcpy(*between_ptr + 1 + tag_len + 1 + between_len, "", 1); - (*between_ptr)[ needed_cap - 1 ] = '\0'; - - ha->sizes[ str_idx ] = needed_cap - 1; - - return *between_ptr; -} - -char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx) -{ - const size_t between_len = ha->sizes[ str_idx ]; - const size_t tag_len = htmc_tag_lengths[ tag_id ]; - const size_t needed_cap = 1 + tag_len + 1 + between_len + 1 + 1 + tag_len + 1 + 1; - const char *tag = htmc_tags[ tag_id ]; - - size_t unused_buffer_idx = htmc_get_unused(ha, needed_cap); - const char *between = ha->buffers[ str_idx ]; - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - - size_t *cap = &ha->caps[ unused_buffer_idx ]; - size_t size = 0; - - memcpy(*unused_buffer, "<", 1); - size += 1; - - memcpy(*unused_buffer + size, tag, tag_len); - size += tag_len; - - // insert attributes here: - for(size_t i = 0 ; i < attrs.nb ; i++) - { - size_t attr_len = strlen(attrs.arr[i]); - if(*cap <= size + attr_len + 1) // 1 for the spaces between each attribute - { - *unused_buffer = realloc(*unused_buffer, size + (attr_len * 2)); - *cap = size + (attr_len * 2); - } - memcpy(*unused_buffer + size, " ", 1); - size += 1; - memcpy(*unused_buffer + size, attrs.arr[i], attr_len); - size += attr_len; - } - - if(*cap <= size + 1 + between_len + 2 + tag_len + 1) - { - *unused_buffer = realloc(*unused_buffer, size + 1 + between_len + 2 + tag_len + 1 + 1); - *cap = size + 1 + between_len + 2 + tag_len + 1 + 1; - } - - memcpy(*unused_buffer + size, ">", 1); - size += 1; - - memcpy(*unused_buffer + size, between, between_len); - size += between_len; - - memcpy(*unused_buffer + size, "", 1); - size += 1; - - (*unused_buffer)[size] = '\0'; - - ha->sizes[ unused_buffer_idx ] = size; - ha->unused[ str_idx ] = true; - - return *unused_buffer; -} - -char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id) -{ - const char *tag = htmc_tags[ tag_id ]; - const size_t tag_len = htmc_tag_lengths[ tag_id ]; - - size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - - memcpy(*unused_buffer, "<", 1); - memcpy(*unused_buffer + 1, tag, tag_len); - memcpy(*unused_buffer + 1 + tag_len, ">", 1); - (*unused_buffer)[ 1 + tag_len + 1 ] = '\0'; - - ha->sizes[ unused_buffer_idx ] = tag_len + 2; - - return *unused_buffer; -} - -char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy) -{ - (void)dummy; - - const char *tag = htmc_tags[ tag_id ]; - const size_t tag_len = htmc_tag_lengths[ tag_id ]; - - size_t unused_buffer_idx = htmc_get_unused(ha, 1 + tag_len + 1 + 1); - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - size_t *size = &ha->sizes[ unused_buffer_idx ]; - *size = 0; - size_t *cap = &ha->caps[ unused_buffer_idx ]; - - memcpy(*unused_buffer, "<", 1); - *size += 1; - - memcpy(*unused_buffer + 1, tag, tag_len); - *size += tag_len; - - // insert attributes here: - for(size_t i = 0 ; i < attrs.nb ; i++) - { - size_t attr_len = strlen(attrs.arr[i]); - if(*size + attr_len + 1 >= *cap) - { - *unused_buffer = realloc(*unused_buffer, (*size + attr_len) * 2); - *cap = (*size + attr_len) * 2; - } - - memcpy(*unused_buffer + *size, " ", 1); - *size += 1; - - memcpy(*unused_buffer + *size, attrs.arr[i], attr_len); - *size += attr_len; - } - - memcpy(*unused_buffer + *size, ">", 2); // 2 for the '\0' - *size += 1; - - return *unused_buffer; -} - -char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs) -{ - size_t combined_str_idx = htmc_concat_strings(ha, strs); - - char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; - size_t *cap = &ha->caps[ combined_str_idx ]; - const size_t combined_strlen = ha->sizes[ combined_str_idx ]; - size_t *size = &ha->sizes[ combined_str_idx ]; - - if(combined_strlen * nb >= *cap) - { - *combined_str_ptr = realloc(*combined_str_ptr, combined_strlen * nb + 1); - *cap = combined_strlen * nb + 1; - } - - for(uint32_t i = 1 ; i < nb ; i++) - { - memcpy(*combined_str_ptr + *size, *combined_str_ptr, combined_strlen); - *size += combined_strlen; - } - - (*combined_str_ptr)[*size] = '\0'; - - return *combined_str_ptr; -} - -// should mod take idx? maybe leave that as the re-entrant version with void*, and let user handle idx -char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs) -{ - size_t combined_str_idx = htmc_concat_strings(ha, strs); - - size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); - - size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); - - char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; - size_t *cap = &ha->caps[ combined_str_idx ]; - size_t *size = &ha->sizes[ combined_str_idx ]; - - char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; - const char *iter_copy = *iter_copy_buffer; - const size_t copy_len = *size; - - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - **unused_buffer = '\0'; - size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; - - for(uint32_t i = 0 ; i < nb ; i++) - { - mod(iter_copy, copy_len, unused_buffer, unused_cap, i); - size_t modified_len = strlen(*unused_buffer); - - if(modified_len + *size >= *cap) - { - *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); - *cap = *size + (modified_len * 2); - } - - memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); - - *size += modified_len; - } - - ha->unused[ iter_copy_idx ] = true; - ha->unused[ unused_buffer_idx ] = true; - - (*combined_str_ptr)[*size] = '\0'; - - return *combined_str_ptr; -} - -char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs) -{ - size_t combined_str_idx = htmc_concat_strings(ha, strs); - - size_t iter_copy_idx = htmc_strdup(ha, combined_str_idx); - - size_t unused_buffer_idx = htmc_get_unused(ha, ha->sizes[ combined_str_idx ] + 1); - - char **combined_str_ptr = &ha->buffers[ combined_str_idx ]; - size_t *cap = &ha->caps[ combined_str_idx ]; - size_t *size = &ha->sizes[ combined_str_idx ]; - - char **iter_copy_buffer = &ha->buffers[ iter_copy_idx ]; - const char *iter_copy = *iter_copy_buffer; - const size_t copy_len = *size; - - char **unused_buffer = &ha->buffers[ unused_buffer_idx ]; - **unused_buffer = '\0'; - size_t *unused_cap = &ha->caps[ unused_buffer_idx ]; - - for(uint32_t i = 0 ; i < nb ; i++) - { - mod(iter_copy, copy_len, unused_buffer, unused_cap, i, arg); - size_t modified_len = strlen(*unused_buffer); - - if(modified_len + *size >= *cap) - { - *combined_str_ptr = realloc(*combined_str_ptr, *size + (modified_len * 2)); - *cap = *size + (modified_len * 2); - } - - memcpy(*combined_str_ptr + *size, *unused_buffer, modified_len); - - *size += modified_len; - } - - ha->unused[ iter_copy_idx ] = true; - ha->unused[ unused_buffer_idx ] = true; - - (*combined_str_ptr)[*size] = '\0'; - - return *combined_str_ptr; -} - -size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx) -{ - size_t len = ha->sizes[ str_idx ]; - size_t unused_buffer_idx = htmc_get_unused(ha, len + 1); - char **dup = &ha->buffers[ unused_buffer_idx ]; - - memcpy(*dup, ha->buffers[ str_idx ], len + 1); - - ha->sizes[ unused_buffer_idx ] = len; - - return unused_buffer_idx; -} - -char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx) -{ - size_t idx = htmc_strdup(ha, str_idx); - return ha->buffers[ idx ]; -} - -char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - - va_list args_copy1; - va_copy(args_copy1, args); - - int str_len = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - size_t unused_buffer_idx = htmc_get_unused(ha, str_len + 1); - char **unused = &ha->buffers[ unused_buffer_idx ]; - ha->sizes[ unused_buffer_idx ] = str_len; - - vsnprintf(*unused, str_len + 1, fmt, args_copy1); - va_end(args_copy1); - - htmc_set_unused_if_alloced(ha, fmt); - - return *unused; -} - -// TODO check in the string for '--' and report error -char *htmc_comment_(HtmcAllocations *ha, size_t str_idx) -{ - const size_t between_len = ha->sizes[ str_idx ]; - char **buffer_ptr = &ha->buffers[ str_idx ]; - size_t *cap = &ha->caps[ str_idx ]; - const size_t comment_start_len = 4; - const size_t comment_end_len = 3; - const size_t needed_cap = comment_start_len + between_len + comment_end_len + 1; - - htmc_gurantee_cap(buffer_ptr, cap, needed_cap); - - memmove(*buffer_ptr + comment_start_len, *buffer_ptr, between_len); - - memcpy(*buffer_ptr, "", 3); - (*buffer_ptr)[ needed_cap - 1 ] = '\0'; - - ha->sizes[ str_idx ] = needed_cap - 1; - - return *buffer_ptr; -} - -void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap) -{ - if(*cap < new_cap) - { - *buffer = realloc(*buffer, new_cap); - *cap = new_cap; - } -} - -#endif /* HTMC_C */ diff --git a/example/scalalib/native/4-common-config/native-src/htmc.h b/example/scalalib/native/4-common-config/native-src/htmc.h deleted file mode 100644 index c7be0829643..00000000000 --- a/example/scalalib/native/4-common-config/native-src/htmc.h +++ /dev/null @@ -1,586 +0,0 @@ -#ifndef HTMC_H -#define HTMC_H - -#include -#include -#include -#include -#include -#include - -typedef struct -{ - size_t nb; - bool *unused; - size_t *caps; - size_t *sizes; - char **buffers; -} HtmcAllocations; - -typedef struct -{ - char **arr; - size_t nb; -} HtmcStrsArr; - -#define htmc(...) \ -({ \ - const size_t init_cap = 4; \ - HtmcAllocations htmc_ha = { \ - .nb = init_cap, \ - .buffers = calloc(init_cap, sizeof(char*)), \ - .caps = calloc(init_cap, sizeof(size_t)), \ - .sizes = calloc(init_cap, sizeof(size_t)), \ - .unused = malloc(init_cap * sizeof(bool)), \ - }; \ - memset(htmc_ha.unused, 1, init_cap * sizeof(bool)); \ - size_t ret_idx = htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__)); \ - char *ret = htmc_ha.buffers[ ret_idx ]; \ - htmc_cleanup_unused_buffers(&htmc_ha, ret_idx); \ - ret; \ -}) - -#define htmc_strsarr(...) (HtmcStrsArr){.arr=(char*[]){__VA_ARGS__}, .nb=sizeof((char*[]){__VA_ARGS__}) / sizeof(char*)} - -#define htmc_repeat(nb, ...) htmc_repeat_(&htmc_ha, nb, htmc_strsarr(__VA_ARGS__)) -#define htmc_repeat_modify(nb, mod, ...) htmc_repeat_modify_(&htmc_ha, nb, mod, htmc_strsarr(__VA_ARGS__)) -#define htmc_repeat_modify_r(nb, mod, ctx, ...) htmc_repeat_modify_r_(&htmc_ha, nb, mod, ctx, htmc_strsarr(__VA_ARGS__)) - -#define htmc_fmt(fmt, ...) htmc_fmt_(&htmc_ha, fmt, ##__VA_ARGS__) - -#define htmc_ccode(...) \ -({ \ - size_t htmc_ccode_yielded_idx = htmc_get_unused(&htmc_ha, 16); \ - htmc_ha.sizes[ htmc_ccode_yielded_idx ] = 0; \ - htmc_ha.buffers[ htmc_ccode_yielded_idx ][0] = '\0'; \ - __VA_ARGS__ \ - char *htmc_ccode_yielded = htmc_ha.buffers[ htmc_ccode_yielded_idx ]; \ - htmc_ccode_yielded; \ -}) -#define htmc_yield(...) htmc_append_to_buffer_idx(&htmc_ha, htmc_ccode_yielded_idx, htmc_strsarr(__VA_ARGS__)) -#define htmc_yielded htmc_ha.buffers[ htmc_ccode_yielded_idx ] -#define htmc_yielded_len htmc_ha.sizes[ htmc_ccode_yielded_idx ] - -#define htmc_attr_(...) \ -htmc_strsarr(__VA_ARGS__))) - -#define htmc_attr(tag, ...) \ -_Generic(&(char[htmc_is_single_tag(htmc_id_##tag) + 1]){ 0 } , \ - char(*)[1]: htmc_surround_by_tag_with_attrs, \ - char(*)[2]: htmc_make_tag_with_attrs \ -)(&htmc_ha, htmc_id_##tag, htmc_strsarr(__VA_ARGS__), htmc_concat_strings(&htmc_ha, htmc_attr_ - -#define htmc_strlit(...) #__VA_ARGS__ - -#define htmc_is_single_tag(id) \ -(id == (htmc_id_area || htmc_id_base || htmc_id_br || htmc_id_col || htmc_id_embed || htmc_id_hr || htmc_id_img || htmc_id_input || htmc_id_link || htmc_id_meta || htmc_id_param || htmc_id_source || htmc_id_track || htmc_id_wbr)) - -#define htmc_doctypehtml ("") - -#define htmc_comment(...) htmc_comment_(&htmc_ha, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) - -// tags that need a closing tag: -#define htmc_a(...) htmc_surround_by_tag(&htmc_ha, 0, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_abbr(...) htmc_surround_by_tag(&htmc_ha, 1, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_address(...) htmc_surround_by_tag(&htmc_ha, 2, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_article(...) htmc_surround_by_tag(&htmc_ha, 4, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_aside(...) htmc_surround_by_tag(&htmc_ha, 5, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_audio(...) htmc_surround_by_tag(&htmc_ha, 6, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_b(...) htmc_surround_by_tag(&htmc_ha, 7, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_bdi(...) htmc_surround_by_tag(&htmc_ha, 9, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_bdo(...) htmc_surround_by_tag(&htmc_ha, 10, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_blockquote(...) htmc_surround_by_tag(&htmc_ha, 11, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_body(...) htmc_surround_by_tag(&htmc_ha, 12, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_button(...) htmc_surround_by_tag(&htmc_ha, 14, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_canvas(...) htmc_surround_by_tag(&htmc_ha, 15, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_caption(...) htmc_surround_by_tag(&htmc_ha, 16, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_cite(...) htmc_surround_by_tag(&htmc_ha, 17, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_code(...) htmc_surround_by_tag(&htmc_ha, 18, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_colgroup(...) htmc_surround_by_tag(&htmc_ha, 20, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_data(...) htmc_surround_by_tag(&htmc_ha, 21, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_datalist(...) htmc_surround_by_tag(&htmc_ha, 22, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_dd(...) htmc_surround_by_tag(&htmc_ha, 23, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_del(...) htmc_surround_by_tag(&htmc_ha, 24, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_details(...) htmc_surround_by_tag(&htmc_ha, 25, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_dfn(...) htmc_surround_by_tag(&htmc_ha, 26, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_dialog(...) htmc_surround_by_tag(&htmc_ha, 27, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_div(...) htmc_surround_by_tag(&htmc_ha, 28, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_dl(...) htmc_surround_by_tag(&htmc_ha, 29, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_dt(...) htmc_surround_by_tag(&htmc_ha, 30, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_em(...) htmc_surround_by_tag(&htmc_ha, 31, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_fieldset(...) htmc_surround_by_tag(&htmc_ha, 33, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_figcaption(...) htmc_surround_by_tag(&htmc_ha, 34, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_figure(...) htmc_surround_by_tag(&htmc_ha, 35, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_footer(...) htmc_surround_by_tag(&htmc_ha, 36, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_form(...) htmc_surround_by_tag(&htmc_ha, 37, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h1(...) htmc_surround_by_tag(&htmc_ha, 38, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h2(...) htmc_surround_by_tag(&htmc_ha, 39, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h3(...) htmc_surround_by_tag(&htmc_ha, 40, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h4(...) htmc_surround_by_tag(&htmc_ha, 41, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h5(...) htmc_surround_by_tag(&htmc_ha, 42, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_h6(...) htmc_surround_by_tag(&htmc_ha, 43, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_head(...) htmc_surround_by_tag(&htmc_ha, 44, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_header(...) htmc_surround_by_tag(&htmc_ha, 45, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_hgroup(...) htmc_surround_by_tag(&htmc_ha, 46, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_html(...) htmc_surround_by_tag(&htmc_ha, 48, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_i(...) htmc_surround_by_tag(&htmc_ha, 49, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_iframe(...) htmc_surround_by_tag(&htmc_ha, 50, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_ins(...) htmc_surround_by_tag(&htmc_ha, 53, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_kbd(...) htmc_surround_by_tag(&htmc_ha, 54, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_label(...) htmc_surround_by_tag(&htmc_ha, 55, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_legend(...) htmc_surround_by_tag(&htmc_ha, 56, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_li(...) htmc_surround_by_tag(&htmc_ha, 57, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_main(...) htmc_surround_by_tag(&htmc_ha, 59, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_map(...) htmc_surround_by_tag(&htmc_ha, 60, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_mark(...) htmc_surround_by_tag(&htmc_ha, 61, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_math(...) htmc_surround_by_tag(&htmc_ha, 62, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_menu(...) htmc_surround_by_tag(&htmc_ha, 63, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_meter(...) htmc_surround_by_tag(&htmc_ha, 65, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_nav(...) htmc_surround_by_tag(&htmc_ha, 66, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_noscript(...) htmc_surround_by_tag(&htmc_ha, 67, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_object(...) htmc_surround_by_tag(&htmc_ha, 68, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_ol(...) htmc_surround_by_tag(&htmc_ha, 69, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_optgroup(...) htmc_surround_by_tag(&htmc_ha, 70, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_option(...) htmc_surround_by_tag(&htmc_ha, 71, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_output(...) htmc_surround_by_tag(&htmc_ha, 72, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_p(...) htmc_surround_by_tag(&htmc_ha, 73, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_picture(...) htmc_surround_by_tag(&htmc_ha, 75, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_pre(...) htmc_surround_by_tag(&htmc_ha, 76, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_progress(...) htmc_surround_by_tag(&htmc_ha, 77, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_q(...) htmc_surround_by_tag(&htmc_ha, 78, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_rp(...) htmc_surround_by_tag(&htmc_ha, 79, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_rt(...) htmc_surround_by_tag(&htmc_ha, 80, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_ruby(...) htmc_surround_by_tag(&htmc_ha, 81, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_s(...) htmc_surround_by_tag(&htmc_ha, 82, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_samp(...) htmc_surround_by_tag(&htmc_ha, 83, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_script(...) htmc_surround_by_tag(&htmc_ha, 84, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_section(...) htmc_surround_by_tag(&htmc_ha, 85, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_select(...) htmc_surround_by_tag(&htmc_ha, 86, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_slot(...) htmc_surround_by_tag(&htmc_ha, 87, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_small(...) htmc_surround_by_tag(&htmc_ha, 88, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_span(...) htmc_surround_by_tag(&htmc_ha, 90, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_strong(...) htmc_surround_by_tag(&htmc_ha, 91, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_style(...) htmc_surround_by_tag(&htmc_ha, 92, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_sub(...) htmc_surround_by_tag(&htmc_ha, 93, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_summary(...) htmc_surround_by_tag(&htmc_ha, 94, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_sup(...) htmc_surround_by_tag(&htmc_ha, 95, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_svg(...) htmc_surround_by_tag(&htmc_ha, 96, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_table(...) htmc_surround_by_tag(&htmc_ha, 97, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_tbody(...) htmc_surround_by_tag(&htmc_ha, 98, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_td(...) htmc_surround_by_tag(&htmc_ha, 99, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_template(...) htmc_surround_by_tag(&htmc_ha, 100, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_textarea(...) htmc_surround_by_tag(&htmc_ha, 101, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_tfoot(...) htmc_surround_by_tag(&htmc_ha, 102, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_th(...) htmc_surround_by_tag(&htmc_ha, 103, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_thead(...) htmc_surround_by_tag(&htmc_ha, 104, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_time(...) htmc_surround_by_tag(&htmc_ha, 105, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_title(...) htmc_surround_by_tag(&htmc_ha, 106, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_tr(...) htmc_surround_by_tag(&htmc_ha, 107, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_u(...) htmc_surround_by_tag(&htmc_ha, 109, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_ul(...) htmc_surround_by_tag(&htmc_ha, 110, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_var(...) htmc_surround_by_tag(&htmc_ha, 111, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) -#define htmc_video(...) htmc_surround_by_tag(&htmc_ha, 112, htmc_concat_strings(&htmc_ha, htmc_strsarr(__VA_ARGS__))) - -// tags that don't terminate -#define htmc_area(...) htmc_make_tag_with_attrs(&htmc_ha, 3, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_base(...) htmc_make_tag_with_attrs(&htmc_ha, 8, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_br(...) htmc_make_tag_with_attrs(&htmc_ha, 13, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_col(...) htmc_make_tag_with_attrs(&htmc_ha, 19, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_embed(...) htmc_make_tag_with_attrs(&htmc_ha, 32, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_hr(...) htmc_make_tag_with_attrs(&htmc_ha, 47, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_img(...) htmc_make_tag_with_attrs(&htmc_ha, 51, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_input(...) htmc_make_tag_with_attrs(&htmc_ha, 52, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_link(...) htmc_make_tag_with_attrs(&htmc_ha, 58, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_meta(...) htmc_make_tag_with_attrs(&htmc_ha, 64, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_param(...) htmc_make_tag_with_attrs(&htmc_ha, 74, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_source(...) htmc_make_tag_with_attrs(&htmc_ha, 89, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_track(...) htmc_make_tag_with_attrs(&htmc_ha, 108, htmc_strsarr(__VA_ARGS__), NULL) -#define htmc_wbr(...) htmc_make_tag_with_attrs(&htmc_ha, 113, htmc_strsarr(__VA_ARGS__), NULL) - -#define htmc_id_a 0 -#define htmc_id_abbr 1 -#define htmc_id_address 2 -#define htmc_id_area 3 -#define htmc_id_article 4 -#define htmc_id_aside 5 -#define htmc_id_audio 6 -#define htmc_id_b 7 -#define htmc_id_base 8 -#define htmc_id_bdi 9 -#define htmc_id_bdo 10 -#define htmc_id_blockquote 11 -#define htmc_id_body 12 -#define htmc_id_br 13 -#define htmc_id_button 14 -#define htmc_id_canvas 15 -#define htmc_id_caption 16 -#define htmc_id_cite 17 -#define htmc_id_code 18 -#define htmc_id_col 19 -#define htmc_id_colgroup 20 -#define htmc_id_data 21 -#define htmc_id_datalist 22 -#define htmc_id_dd 23 -#define htmc_id_del 24 -#define htmc_id_details 25 -#define htmc_id_dfn 26 -#define htmc_id_dialog 27 -#define htmc_id_div 28 -#define htmc_id_dl 29 -#define htmc_id_dt 30 -#define htmc_id_em 31 -#define htmc_id_embed 32 -#define htmc_id_fieldset 33 -#define htmc_id_figcaption 34 -#define htmc_id_figure 35 -#define htmc_id_footer 36 -#define htmc_id_form 37 -#define htmc_id_h1 38 -#define htmc_id_h2 39 -#define htmc_id_h3 40 -#define htmc_id_h4 41 -#define htmc_id_h5 42 -#define htmc_id_h6 43 -#define htmc_id_head 44 -#define htmc_id_header 45 -#define htmc_id_hgroup 46 -#define htmc_id_hr 47 -#define htmc_id_html 48 -#define htmc_id_i 49 -#define htmc_id_iframe 50 -#define htmc_id_img 51 -#define htmc_id_input 52 -#define htmc_id_ins 53 -#define htmc_id_kbd 54 -#define htmc_id_label 55 -#define htmc_id_legend 56 -#define htmc_id_li 57 -#define htmc_id_link 58 -#define htmc_id_main 59 -#define htmc_id_map 60 -#define htmc_id_mark 61 -#define htmc_id_math 62 -#define htmc_id_menu 63 -#define htmc_id_meta 64 -#define htmc_id_meter 65 -#define htmc_id_nav 66 -#define htmc_id_noscript 67 -#define htmc_id_object 68 -#define htmc_id_ol 69 -#define htmc_id_optgroup 70 -#define htmc_id_option 71 -#define htmc_id_output 72 -#define htmc_id_p 73 -#define htmc_id_param 74 -#define htmc_id_picture 75 -#define htmc_id_pre 76 -#define htmc_id_progress 77 -#define htmc_id_q 78 -#define htmc_id_rp 79 -#define htmc_id_rt 80 -#define htmc_id_ruby 81 -#define htmc_id_s 82 -#define htmc_id_samp 83 -#define htmc_id_script 84 -#define htmc_id_section 85 -#define htmc_id_select 86 -#define htmc_id_slot 87 -#define htmc_id_small 88 -#define htmc_id_source 89 -#define htmc_id_span 90 -#define htmc_id_strong 91 -#define htmc_id_style 92 -#define htmc_id_sub 93 -#define htmc_id_summary 94 -#define htmc_id_sup 95 -#define htmc_id_svg 96 -#define htmc_id_table 97 -#define htmc_id_tbody 98 -#define htmc_id_td 99 -#define htmc_id_template 100 -#define htmc_id_textarea 101 -#define htmc_id_tfoot 102 -#define htmc_id_th 103 -#define htmc_id_thead 104 -#define htmc_id_time 105 -#define htmc_id_title 106 -#define htmc_id_tr 107 -#define htmc_id_track 108 -#define htmc_id_u 109 -#define htmc_id_ul 110 -#define htmc_id_var 111 -#define htmc_id_video 112 -#define htmc_id_wbr 113 - -void htmc_cleanup_unused_buffers(HtmcAllocations *ha, size_t used_idx); -size_t htmc_find_buffer(const HtmcAllocations *ha, const char *buffer); -void htmc_grow_buffers(HtmcAllocations *ha); -void htmc_set_unused(HtmcAllocations *ha, const char *str); -void htmc_set_unused_if_alloced(HtmcAllocations *ha, const char *str); -size_t htmc_find_unused(const HtmcAllocations *ha); -size_t htmc_get_unused(HtmcAllocations *ha, size_t with_size); -size_t htmc_concat_strings(HtmcAllocations *ha, HtmcStrsArr strs); -char *htmc_surround_by_tag(HtmcAllocations *ha, uint16_t tag_id, size_t str_idx); -char *htmc_surround_by_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, size_t str_idx); -char *htmc_make_tag(HtmcAllocations *ha, uint16_t tag_id); -char *htmc_make_tag_with_attrs(HtmcAllocations *ha, uint16_t tag_id, HtmcStrsArr attrs, char *dummy); -char *htmc_repeat_(HtmcAllocations *ha, uint32_t nb, HtmcStrsArr strs); -char *htmc_repeat_modify_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx), HtmcStrsArr strs); -char *htmc_repeat_modify_r_(HtmcAllocations *ha, uint32_t nb, void(*mod)(const char *before_mod, size_t len, char **buffer, size_t *cap, uint32_t idx, void *arg), void *arg, HtmcStrsArr strs); -char *htmc_fmt_(HtmcAllocations *ha, const char *fmt, ...); -void htmc_append_to_buffer_idx(HtmcAllocations *ha, size_t buffer_idx, HtmcStrsArr strs); -size_t htmc_strdup(HtmcAllocations *ha, size_t str_idx); -char *htmc_get_strdup(HtmcAllocations *ha, size_t str_idx); -char *htmc_comment_(HtmcAllocations *ha, size_t str_idx); - -void htmc_gurantee_cap(char **buffer, size_t *cap, size_t new_cap); - -#endif - -#ifdef HTMC_PREFIX - -#undef HTMC_PREFIX - -#undef doctypehtml - -#undef comment - -#undef a -#undef abbr -#undef address -#undef area -#undef article -#undef aside -#undef audio -#undef b -#undef base -#undef bdi -#undef bdo -#undef blockquote -#undef body -#undef br -#undef button -#undef canvas -#undef caption -#undef cite -#undef code -#undef col -#undef colgroup -#undef data -#undef datalist -#undef dd -#undef del -#undef details -#undef dfn -#undef dialog -#undef div -#undef dl -#undef dt -#undef em -#undef embed -#undef fieldset -#undef figcaption -#undef figure -#undef footer -#undef form -#undef h1 -#undef h2 -#undef h3 -#undef h4 -#undef h5 -#undef h6 -#undef head -#undef header -#undef hgroup -#undef hr -#undef html -#undef i -#undef iframe -#undef img -#undef input -#undef ins -#undef kbd -#undef label -#undef legend -#undef li -#undef link -#undef map -#undef mark -#undef math -#undef menu -#undef meta -#undef meter -#undef nav -#undef noscript -#undef object -#undef ol -#undef optgroup -#undef option -#undef output -#undef p -#undef param -#undef picture -#undef pre -#undef progress -#undef q -#undef rp -#undef rt -#undef ruby -#undef s -#undef samp -#undef script -#undef section -#undef select -#undef slot -#undef small -#undef source -#undef span -#undef strong -#undef style -#undef sub -#undef summary -#undef sup -#undef svg -#undef table -#undef tbody -#undef td -#undef template -#undef textarea -#undef tfoot -#undef th -#undef thead -#undef time -#undef title -#undef tr -#undef track -#undef u -#undef ul -#undef var -#undef video -#undef wbr - -#undef attr - -#else - -#define doctypehtml htmc_doctypehtml - -#define comment htmc_comment - -#define a(...) htmc_a(__VA_ARGS__) -#define abbr(...) htmc_abbr(__VA_ARGS__) -#define address(...) htmc_address(__VA_ARGS__) -#define area(...) htmc_area(__VA_ARGS__) -#define article(...) htmc_article(__VA_ARGS__) -#define aside(...) htmc_aside(__VA_ARGS__) -#define audio(...) htmc_audio(__VA_ARGS__) -#define b(...) htmc_b(__VA_ARGS__) -#define base(...) htmc_base(__VA_ARGS__) -#define bdi(...) htmc_bdi(__VA_ARGS__) -#define bdo(...) htmc_bdo(__VA_ARGS__) -#define blockquote(...) htmc_blockquote(__VA_ARGS__) -#define body(...) htmc_body(__VA_ARGS__) -#define br(...) htmc_br(__VA_ARGS__) -#define button(...) htmc_button(__VA_ARGS__) -#define canvas(...) htmc_canvas(__VA_ARGS__) -#define caption(...) htmc_caption(__VA_ARGS__) -#define cite(...) htmc_cite(__VA_ARGS__) -#define code(...) htmc_code(__VA_ARGS__) -#define col(...) htmc_col(__VA_ARGS__) -#define colgroup(...) htmc_colgroup(__VA_ARGS__) -#define data(...) htmc_data(__VA_ARGS__) -#define datalist(...) htmc_datalist(__VA_ARGS__) -#define dd(...) htmc_dd(__VA_ARGS__) -#define del(...) htmc_del(__VA_ARGS__) -#define details(...) htmc_details(__VA_ARGS__) -#define dfn(...) htmc_dfn(__VA_ARGS__) -#define dialog(...) htmc_dialog(__VA_ARGS__) -#define div(...) htmc_div(__VA_ARGS__) -#define dl(...) htmc_dl(__VA_ARGS__) -#define dt(...) htmc_dt(__VA_ARGS__) -#define em(...) htmc_em(__VA_ARGS__) -#define embed(...) htmc_embed(__VA_ARGS__) -#define fieldset(...) htmc_fieldset(__VA_ARGS__) -#define figcaption(...) htmc_figcaption(__VA_ARGS__) -#define figure(...) htmc_figure(__VA_ARGS__) -#define footer(...) htmc_footer(__VA_ARGS__) -#define form(...) htmc_form(__VA_ARGS__) -#define h1(...) htmc_h1(__VA_ARGS__) -#define h2(...) htmc_h2(__VA_ARGS__) -#define h3(...) htmc_h3(__VA_ARGS__) -#define h4(...) htmc_h4(__VA_ARGS__) -#define h5(...) htmc_h5(__VA_ARGS__) -#define h6(...) htmc_h6(__VA_ARGS__) -#define head(...) htmc_head(__VA_ARGS__) -#define header(...) htmc_header(__VA_ARGS__) -#define hgroup(...) htmc_hgroup(__VA_ARGS__) -#define hr(...) htmc_hr(__VA_ARGS__) -#define html(...) htmc_html(__VA_ARGS__) -#define i(...) htmc_i(__VA_ARGS__) -#define iframe(...) htmc_iframe(__VA_ARGS__) -#define img(...) htmc_img(__VA_ARGS__) -#define input(...) htmc_input(__VA_ARGS__) -#define ins(...) htmc_ins(__VA_ARGS__) -#define kbd(...) htmc_kbd(__VA_ARGS__) -#define label(...) htmc_label(__VA_ARGS__) -#define legend(...) htmc_legend(__VA_ARGS__) -#define li(...) htmc_li(__VA_ARGS__) -#define link(...) htmc_link(__VA_ARGS__) -#define map(...) htmc_map(__VA_ARGS__) -#define mark(...) htmc_mark(__VA_ARGS__) -#define math(...) htmc_math(__VA_ARGS__) -#define menu(...) htmc_menu(__VA_ARGS__) -#define meta(...) htmc_meta(__VA_ARGS__) -#define meter(...) htmc_meter(__VA_ARGS__) -#define nav(...) htmc_nav(__VA_ARGS__) -#define noscript(...) htmc_noscript(__VA_ARGS__) -#define object(...) htmc_object(__VA_ARGS__) -#define ol(...) htmc_ol(__VA_ARGS__) -#define optgroup(...) htmc_optgroup(__VA_ARGS__) -#define option(...) htmc_option(__VA_ARGS__) -#define output(...) htmc_output(__VA_ARGS__) -#define p(...) htmc_p(__VA_ARGS__) -#define param(...) htmc_param(__VA_ARGS__) -#define picture(...) htmc_picture(__VA_ARGS__) -#define pre(...) htmc_pre(__VA_ARGS__) -#define progress(...) htmc_progress(__VA_ARGS__) -#define q(...) htmc_q(__VA_ARGS__) -#define rp(...) htmc_rp(__VA_ARGS__) -#define rt(...) htmc_rt(__VA_ARGS__) -#define ruby(...) htmc_ruby(__VA_ARGS__) -#define s(...) htmc_s(__VA_ARGS__) -#define samp(...) htmc_samp(__VA_ARGS__) -#define script(...) htmc_script(__VA_ARGS__) -#define section(...) htmc_section(__VA_ARGS__) -#define select(...) htmc_select(__VA_ARGS__) -#define slot(...) htmc_slot(__VA_ARGS__) -#define small(...) htmc_small(__VA_ARGS__) -#define source(...) htmc_source(__VA_ARGS__) -#define span(...) htmc_span(__VA_ARGS__) -#define strong(...) htmc_strong(__VA_ARGS__) -#define style(...) htmc_style(__VA_ARGS__) -#define sub(...) htmc_sub(__VA_ARGS__) -#define summary(...) htmc_summary(__VA_ARGS__) -#define sup(...) htmc_sup(__VA_ARGS__) -#define svg(...) htmc_svg(__VA_ARGS__) -#define table(...) htmc_table(__VA_ARGS__) -#define tbody(...) htmc_tbody(__VA_ARGS__) -#define td(...) htmc_td(__VA_ARGS__) -#define template(...) htmc_template(__VA_ARGS__) -#define textarea(...) htmc_textarea(__VA_ARGS__) -#define tfoot(...) htmc_tfoot(__VA_ARGS__) -#define th(...) htmc_th(__VA_ARGS__) -#define thead(...) htmc_thead(__VA_ARGS__) -#define time(...) htmc_time(__VA_ARGS__) -#define title(...) htmc_title(__VA_ARGS__) -#define tr(...) htmc_tr(__VA_ARGS__) -#define track(...) htmc_track(__VA_ARGS__) -#define u(...) htmc_u(__VA_ARGS__) -#define ul(...) htmc_ul(__VA_ARGS__) -#define var(...) htmc_var(__VA_ARGS__) -#define video(...) htmc_video(__VA_ARGS__) -#define wbr(...) htmc_wbr(__VA_ARGS__) - -#define attr(...) htmc_attr(__VA_ARGS__) - -#endif diff --git a/example/scalalib/native/4-common-config/src/Foo.scala b/example/scalalib/native/4-common-config/src/Foo.scala index 9c63ab32eaa..301a59b1166 100644 --- a/example/scalalib/native/4-common-config/src/Foo.scala +++ b/example/scalalib/native/4-common-config/src/Foo.scala @@ -1,21 +1,23 @@ package foo +import scala.scalanative.libc._ import scala.scalanative.unsafe._ +import fansi._ -object Bar { - def main(args: Array[String]): Unit = { - println("Running HelloWorld function") - val result = HelloWorld.generateHtml(c"Hello") - println(("Bar value:" + result) - println("Done...) +object Foo { + + def generateHtml(text: String): CString = { + val colored = Console.RED + "

" + text + "

" + Console.RESET + "\n" + + implicit val z: Zone = Zone.open + val cResult = toCString(colored) + z.close() + cResult } -} + + val value = generateHtml("Hello") -// Define the external module, the C library containing our function "generateHtml" -@extern -@link("HelloWorld") -// Arbitrary object name -object HelloWorld { - // Name and signature of C function - def generateHtml(str: CString): CString = extern + def main(args: Array[String]): Unit = { + stdio.printf(c"Foo.value: %s", Foo.value) + } } From 24729eabfd402d9df13a23aa2e7e02671a8e12b9 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 12 Oct 2024 06:45:58 +0100 Subject: [PATCH 28/37] updated code examples --- example/scalalib/native/1-simple/build.mill | 18 ++++++----- .../scalalib/native/1-simple/src/Foo.scala | 10 +++--- .../native/1-simple/test/src/FooTests.scala | 17 +++++----- example/scalalib/native/2-interop/build.mill | 7 ++-- .../2-interop/test/src/HelloWorldTests.scala | 7 ++-- .../scalalib/native/3-multi-module/build.mill | 15 ++++----- .../native/4-common-config/build.mill | 16 ++++++++-- .../4-common-config/custom-src/Foo2.scala | 32 ++++++++++++++----- .../native/4-common-config/src/Foo.scala | 7 ++-- 9 files changed, 82 insertions(+), 47 deletions(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index 8f2e7d45ac5..82b897a315f 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -8,7 +8,8 @@ object `package` extends RootModule with ScalaNativeModule { // You can have arbitrary numbers of third-party dependencies def ivyDeps = Agg( - ivy"com.lihaoyi::fansi::0.5.0" + ivy"com.lihaoyi::fansi::0.5.0", + ivy"com.lihaoyi::mainargs:0.7.6" ) object test extends ScalaNativeTests { @@ -74,23 +75,24 @@ compiling 1 Scala source to... > ./mill run # run the main method, if any error: Missing argument: --text -> ./mill run -Hello World Ansi (colored in Green) +> ./mill run --text hello +

hello

(colored in Red) > ./mill test ... -+ foo.FooTests...simple ...

hello

-+ foo.FooTests...escaping ...

<hello>

- +-------------------------------- Running Tests -------------------------------- ++ foo.FooTests.simple one 0ms

hello

++ foo.FooTests.simple two 0ms

hello world

+Tests: 2, Passed: 2, Failed: 0 > ./mill assembly # bundle classfiles and libraries into a jar for deployment > ./mill show assembly # show the output of the assembly task ".../out/assembly.dest/out.jar" > java -jar ./out/assembly.dest/out.jar -Hello World Ansi (colored in Green) +

hello

(colored in Red) > ./out/assembly.dest/out.jar # mac/linux -Hello World Ansi (colored in Green) +

hello

(colored in Red) */ diff --git a/example/scalalib/native/1-simple/src/Foo.scala b/example/scalalib/native/1-simple/src/Foo.scala index fb75bdcec5c..6c6d9b4760c 100644 --- a/example/scalalib/native/1-simple/src/Foo.scala +++ b/example/scalalib/native/1-simple/src/Foo.scala @@ -2,6 +2,7 @@ package foo import scala.scalanative.libc._ import scala.scalanative.unsafe._ +import mainargs.{main, ParserForMethods} import fansi._ object Foo { @@ -15,9 +16,10 @@ object Foo { cResult } - def main(args: Array[String]): Unit = { - val text = args(0) - stdio.printf(generateHtml(text)) // Now printing the result + @main + def main(text: String) = { + stdio.printf(generateHtml(text)) } -} + def main(args: Array[String]): Unit = ParserForMethods(this).runOrExit(args) +} diff --git a/example/scalalib/native/1-simple/test/src/FooTests.scala b/example/scalalib/native/1-simple/test/src/FooTests.scala index 767031ba814..ef7a49b7aae 100644 --- a/example/scalalib/native/1-simple/test/src/FooTests.scala +++ b/example/scalalib/native/1-simple/test/src/FooTests.scala @@ -5,16 +5,17 @@ import utest._ object FooTests extends TestSuite { def tests = Tests { - test("simple") { + test("simple one") { val result = Foo.generateHtml("hello") - assert(result == c"

hello

") - result + val colored = Console.RED + "

hello

" + Console.RESET + "\n" + assert(fromCString(result) == colored) + fromCString(result) } - test("escaping") { - val result = Foo.generateHtml("") - assert(result == c"

<hello>

") - result + test("simple two") { + val result = Foo.generateHtml("hello world") + val colored = Console.RED + "

hello world

" + Console.RESET + "\n" + assert(fromCString(result) == colored) + fromCString(result) } } } - diff --git a/example/scalalib/native/2-interop/build.mill b/example/scalalib/native/2-interop/build.mill index e69bb709e94..6086a2a8628 100644 --- a/example/scalalib/native/2-interop/build.mill +++ b/example/scalalib/native/2-interop/build.mill @@ -6,15 +6,16 @@ object `package` extends RootModule with ScalaNativeModule { def scalaVersion = "2.13.11" def scalaNativeVersion = "0.5.5" - object test extends ScalaNativeTests { - def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.8.4") def testFramework = "utest.runner.Framework" } + def nativeLinking = true def nativeLinkingOptions = Seq("-L" + millSourcePath.toString + "/target") - os.makeDir(millSourcePath / "target") + + os.proc("mkdir", millSourcePath.toString + "/target").call(stdout = os.Inherit) os.proc("gcc", "-m64", "-shared", "-c", millSourcePath.toString + "/native-src/HelloWorld.c", "-o", millSourcePath.toString + "/target/libHelloWorld.so" diff --git a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala index c668a72bed5..e88bda99693 100644 --- a/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala +++ b/example/scalalib/native/2-interop/test/src/HelloWorldTests.scala @@ -6,13 +6,14 @@ import scala.scalanative.unsafe._ object HelloWorldTest extends TestSuite { val tests = Tests { test("reverseString should reverse a C string correctly") { - val expected = c"!dlrow olleH" + val expected = "!dlrow olleH" val result = HelloWorld.reverseString(c"Hello World!") // Check if the reversed string matches the expected result - assert(result == expected) - result + assert(fromCString(result) == expected) + fromCString(result) } } } + diff --git a/example/scalalib/native/3-multi-module/build.mill b/example/scalalib/native/3-multi-module/build.mill index fa3c9ca19a3..b28b96eb120 100644 --- a/example/scalalib/native/3-multi-module/build.mill +++ b/example/scalalib/native/3-multi-module/build.mill @@ -7,14 +7,14 @@ trait MyModule extends ScalaNativeModule { def scalaNativeVersion = "0.5.5" object test extends ScalaNativeTests { - def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.8.4") def testFramework = "utest.runner.Framework" } } object foo extends MyModule { def moduleDeps = Seq(bar) - def ivyDeps = Agg(ivy"com.lihaoyi::mainargs:0.4.0") + def ivyDeps = Agg(ivy"com.lihaoyi::mainargs::0.4.0") os.proc("mkdir", millSourcePath.toString + "/target").call(stdout = os.Inherit) @@ -23,13 +23,11 @@ object foo extends MyModule { os.proc( "gcc", "-m64", "-shared", "-fPIC", millSourcePath.toString + "/native-src/HelloWorldFoo.c", millSourcePath.toString + "/native-src/htm.c", - "-o", millSourcePath.toString + "/target/libHelloWorldFoo.so" - ).call(stdout = os.Inherit) - + "-o", millSourcePath.toString + "/target/libHelloWorldFoo.so") + .call(stdout = os.Inherit) } object bar extends MyModule { - def ivyDeps = Agg(ivy"com.lihaoyi::scalatags:0.8.2") os.proc("mkdir", millSourcePath.toString + "/target").call(stdout = os.Inherit) @@ -40,7 +38,7 @@ object bar extends MyModule { millSourcePath.toString + "/native-src/HelloWorldBar.c", millSourcePath.toString + "/native-src/htm.c", "-o", millSourcePath.toString + "/target/libHelloWorldBar.so") .call(stdout = os.Inherit) - + } //// SNIPPET:END @@ -71,10 +69,11 @@ object bar extends MyModule { // BarTests.scala // foo/ // native-src/ - HelloWorldFoo.c +// HelloWorldFoo.c // src/ // Foo.scala // // // //// SNIPPET:END + diff --git a/example/scalalib/native/4-common-config/build.mill b/example/scalalib/native/4-common-config/build.mill index c7a817d57e9..0cd88e8cf35 100644 --- a/example/scalalib/native/4-common-config/build.mill +++ b/example/scalalib/native/4-common-config/build.mill @@ -13,12 +13,23 @@ object `package` extends RootModule with ScalaNativeModule { // You can have arbitrary numbers of third-party dependencies def ivyDeps = Agg( - ivy"com.lihaoyi::fansi::0.5.0" + ivy"com.lihaoyi::fansi::0.5.0", + ivy"com.lihaoyi::os-lib::0.11.1" ) // Choose a main class to use for `.run` if there are multiple present - //def mainClass: T[Option[String]] = Some("foo.Foo2") + def mainClass: T[Option[String]] = Some("foo.Foo2") + // Add (or replace) source folders for the module to use + def sources = T.sources{ + super.sources() ++ Seq(PathRef(millSourcePath / "custom-src")) + } + + // Add (or replace) resource folders for the module to use + def resources = T.sources{ + super.resources() ++ Seq(PathRef(millSourcePath / "custom-resources")) + } + // Generate sources at build time def generatedSources: T[Seq[PathRef]] = T { for(name <- Seq("A", "B", "C")) os.write( @@ -107,3 +118,4 @@ error: ^ error: ...Implicit injection of + is deprecated. Convert to String to call +... */ + diff --git a/example/scalalib/native/4-common-config/custom-src/Foo2.scala b/example/scalalib/native/4-common-config/custom-src/Foo2.scala index 5b6dc2a5641..e1bb6c305d0 100644 --- a/example/scalalib/native/4-common-config/custom-src/Foo2.scala +++ b/example/scalalib/native/4-common-config/custom-src/Foo2.scala @@ -7,7 +7,7 @@ import fansi._ object Foo2 { def generateHtml(text: String): CString = { - val colored = Console.RED + "

" + text + "

" + Console.RESET + "\n" + val colored = Console.RED + "

" + text + "

" + Console.RESET implicit val z: Zone = Zone.open val cResult = toCString(colored) @@ -18,15 +18,31 @@ object Foo2 { val value = generateHtml("hello2") def main(args: Array[String]): Unit = { - stdio.printf("Foo2.value: %s", Foo2.value) - stdio.printf("Foo.value: %s", Foo.value) + stdio.printf(c"Foo2.value: %s\n", Foo2.value) + stdio.fflush(null) + stdio.printf(c"Foo.value: %s\n", Foo.value) + stdio.fflush(null) - stdio.printf("FooA.value: %s", FooA.value) - stdio.printf("FooB.value: %s", FooB.value) - stdio.printf("FooC.value: %s", FooC.value) + implicit val z: Zone = Zone.open + val cFooA = toCString(FooA.value) + val cFooB = toCString(FooB.value) + val cFooC = toCString(FooC.value) + z.close + + stdio.printf(c"FooA.value: %s\n", cFooA) + stdio.fflush(null) + stdio.printf(c"FooB.value: %s\n", cFooB) + stdio.fflush(null) + stdio.printf(c"FooC.value: %s\n", cFooC) + stdio.fflush(null) + + val myResource = os.read(os.pwd / "resources" / "MyResource.txt") + val myOtherResource = os.read(os.pwd / "common-resources" / "MyOtherResource.txt") + + println("MyResource: " + myResource) + println("MyOtherResource: " + myOtherResource) - println("MyResource: " + os.read(os.resource / "MyResource.txt")) - println("MyOtherResource: " + os.read(os.resource / "MyOtherResource.txt")) } } + diff --git a/example/scalalib/native/4-common-config/src/Foo.scala b/example/scalalib/native/4-common-config/src/Foo.scala index 301a59b1166..05b82b0f561 100644 --- a/example/scalalib/native/4-common-config/src/Foo.scala +++ b/example/scalalib/native/4-common-config/src/Foo.scala @@ -7,7 +7,7 @@ import fansi._ object Foo { def generateHtml(text: String): CString = { - val colored = Console.RED + "

" + text + "

" + Console.RESET + "\n" + val colored = Console.RED + "

" + text + "

" + Console.RESET implicit val z: Zone = Zone.open val cResult = toCString(colored) @@ -15,9 +15,10 @@ object Foo { cResult } - val value = generateHtml("Hello") + val value = generateHtml("hello") def main(args: Array[String]): Unit = { - stdio.printf(c"Foo.value: %s", Foo.value) + stdio.printf(c"Foo.value: %s\n", Foo.value) } } + From f047193cfe4d6e812cf4b5dbda2ec62b30da8dfa Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 12 Oct 2024 07:23:32 +0100 Subject: [PATCH 29/37] fix syntax in 1-simple example build.mill file --- example/scalalib/native/1-simple/build.mill | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/scalalib/native/1-simple/build.mill b/example/scalalib/native/1-simple/build.mill index 82b897a315f..b8c27c16849 100644 --- a/example/scalalib/native/1-simple/build.mill +++ b/example/scalalib/native/1-simple/build.mill @@ -9,11 +9,11 @@ object `package` extends RootModule with ScalaNativeModule { // You can have arbitrary numbers of third-party dependencies def ivyDeps = Agg( ivy"com.lihaoyi::fansi::0.5.0", - ivy"com.lihaoyi::mainargs:0.7.6" + ivy"com.lihaoyi::mainargs::0.7.6" ) object test extends ScalaNativeTests { - def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.8.4") + def ivyDeps = Agg(ivy"com.lihaoyi::utest::0.8.4") def testFramework = "utest.runner.Framework" } } From 39199331ea8d7a1cb0b8437ca37ef2be68c49ba8 Mon Sep 17 00:00:00 2001 From: Jeffrey Date: Sat, 12 Oct 2024 08:14:22 +0100 Subject: [PATCH 30/37] update code --- .../modules/ROOT/pages/scalalib/native-examples.adoc | 2 +- .../scalalib/native/3-multi-module/bar/src/Bar.scala | 11 ++++++----- .../3-multi-module/bar/test/src/BarTests.scala | 12 ++++++------ example/scalalib/native/3-multi-module/build.mill | 4 +--- .../scalalib/native/3-multi-module/foo/src/Foo.scala | 4 ++-- 5 files changed, 16 insertions(+), 17 deletions(-) diff --git a/docs/modules/ROOT/pages/scalalib/native-examples.adoc b/docs/modules/ROOT/pages/scalalib/native-examples.adoc index 7365f945d7c..675d4666eeb 100644 --- a/docs/modules/ROOT/pages/scalalib/native-examples.adoc +++ b/docs/modules/ROOT/pages/scalalib/native-examples.adoc @@ -1,5 +1,5 @@ = Scala Native Examples -:page-aliases: Web_Build_Examples.adoc, Scala_Web_Examples.adoc +:page-aliases: native-examples.adoc ++++