-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Created by .ignore support plugin (hsz.mobi) | ||
### CMake template | ||
CMakeCache.txt | ||
CMakeFiles | ||
CMakeScripts | ||
Testing | ||
Makefile | ||
cmake_install.cmake | ||
install_manifest.txt | ||
compile_commands.json | ||
CTestTestfile.cmake | ||
### JetBrains template | ||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm | ||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||
|
||
# User-specific stuff: | ||
.idea/**/workspace.xml | ||
.idea/**/tasks.xml | ||
.idea/dictionaries | ||
|
||
# Sensitive or high-churn files: | ||
.idea/**/dataSources/ | ||
.idea/**/dataSources.ids | ||
.idea/**/dataSources.xml | ||
.idea/**/dataSources.local.xml | ||
.idea/**/sqlDataSources.xml | ||
.idea/**/dynamic.xml | ||
.idea/**/uiDesigner.xml | ||
|
||
# Gradle: | ||
.idea/**/gradle.xml | ||
.idea/**/libraries | ||
|
||
# CMake | ||
cmake-build-debug/ | ||
cmake-build-release/ | ||
|
||
# Mongo Explorer plugin: | ||
.idea/**/mongoSettings.xml | ||
|
||
## File-based project format: | ||
*.iws | ||
|
||
## Plugin-specific files: | ||
|
||
# IntelliJ | ||
out/ | ||
|
||
# mpeltonen/sbt-idea plugin | ||
.idea_modules/ | ||
|
||
# JIRA plugin | ||
atlassian-ide-plugin.xml | ||
|
||
# Cursive Clojure plugin | ||
.idea/replstate.xml | ||
|
||
# Crashlytics plugin (for Android Studio and IntelliJ) | ||
com_crashlytics_export_strings.xml | ||
crashlytics.properties | ||
crashlytics-build.properties | ||
fabric.properties |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
cmake_minimum_required(VERSION 3.9) | ||
project(t2b) | ||
|
||
set(CMAKE_CXX_STANDARD 11) | ||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) | ||
|
||
add_executable(t2b main.cc) | ||
install(TARGETS t2b DESTINATION bin) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
# t2b | ||
A wicked-powerful text macro language for building binary files. | ||
Supports comments, looping, Unicode, variables, conditionals, macros and recursion. | ||
|
||
TLDR; Check out `example/`. | ||
|
||
## Usage | ||
```bash | ||
$ t2b <filename> here | ||
$ t2b # Read directly from stdin | ||
``` | ||
|
||
`t2b` always writes to stdout. To output to a file, simply use a pipe (`|`). | ||
|
||
## Language | ||
Newlines are solely for the sake of readability; all whitespace is the same. | ||
|
||
```t2b | ||
# This is a comment! | ||
# | ||
# Comments must be on their own line. | ||
# Emit a byte. In DECIMAL. | ||
u8 10 | ||
# Toggle hex mode ON. | ||
# In hex mode, numbers will be interpreted as hexadecimal. | ||
hex | ||
u8 10 | ||
# Toggle hex mode OFF. | ||
hex | ||
# Spit out a signed integer. | ||
i64 25677 | ||
# Print a string (no line break) | ||
str hello | ||
# Print with a line break. | ||
strl hello | ||
# Wrap in quotes to capture whitespace. | ||
strl "hello world!" | ||
# Escapes are supported. | ||
str "hello, world!\n" | ||
# Unicode? | ||
str "\u{1234}" | ||
# Print a newline. | ||
endl | ||
# Do something 5 times. | ||
# Indentation is purely for readability. | ||
times 5 | ||
u8 23 | ||
u32 24 | ||
times 10 | ||
# We can nest loops | ||
str "50 times!!!" | ||
endtimes | ||
endtimes | ||
# Capture the output of another command. | ||
# Oh, and store it into a variable. | ||
set foo (u8 33) | ||
# Access its value. | ||
set bar (get foo) | ||
# Emit its value 3 times. | ||
times 3 get foo | ||
# Create a simple macro. | ||
macro emit_twice x | ||
begin | ||
times 2 (get x) | ||
endmacro | ||
# Call it! | ||
emit_twice 24 | ||
``` | ||
|
||
## Why? | ||
The need for such a program arose when I was working on writing a simple VM. | ||
Manually hex-editing files for an ever changing bytecode spec is tedious, error-prone, | ||
and most of all - *sucky*. | ||
|
||
Now there's a lightweight way to do just that. | ||
|
||
## Supported Commands | ||
* `u8...u64` - Emit unsigned integer | ||
* `i8...i64` - Emit signed integer | ||
* `hex` - Toggle hex mode on/off (defaults to OFF) | ||
* `str <expr>` - Write a string | ||
* `strl <expr>` - Write a string AND newline | ||
* `endl` - Write a newline | ||
* `not <expr>` Boolean NOT a char | ||
* `if <cond> <pred> endif` Execute `<pred>` if `<cond> == 1` | ||
* `get <expr>` - Fetch the global variable named `expr` | ||
* `set <expr1> <expr2>` - Assign the global variable named `expr1` to `expr2` | ||
* `=` - Compare two values, return `0` or `1` | ||
* `times <count> <pred> endtimes` - Execute `<pred>` `<count>` times. `i` is always set to the current iteration's index. | ||
* `macro <name> <param-names...> begin <pred> endmacro` - Declare a custom macro named `<name>`. | ||
|
||
# What's next? | ||
It's now feasible to write a machine code compiler in shell. Hooray. | ||
Not sure why you would ever do that to yourself, though. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# Say hello!!! | ||
strl "Hello, T2B!!!" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# `if` handles u8 only. Do as you will. | ||
if (u8 1) | ||
strl "true == true" | ||
endif | ||
|
||
if (not (u8 0)) | ||
strl "!false == true" | ||
endif | ||
|
||
if (not (u8 1)) | ||
strl "This never prints." | ||
endif | ||
|
||
if (= (str 2) (str 2)) | ||
strl "2 == 2" | ||
endif | ||
|
||
if (= (str 24) (str 2)) | ||
strl "This never prints either." | ||
endif |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Using parentheses, we can use the outputs of commands as inputs. | ||
# | ||
# Let's be verbose and write out "T2B!!!". | ||
times 5 | ||
str (u8 84) | ||
str (u8 50) | ||
str (u8 66) | ||
times 10 str (u8 33) endtimes | ||
endl | ||
endtimes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# Create a simple macro. | ||
macro emit_times value count | ||
begin | ||
str "Emitting value: \"" | ||
get value | ||
str "\" " | ||
get count | ||
str " time(s)!" | ||
endl | ||
endl | ||
|
||
times (get count) | ||
get value | ||
endl | ||
endtimes | ||
endmacro | ||
|
||
# Call it! | ||
#emit_times "Hello!" 34 | ||
|
||
# Yes, you can technically nest macros and create them dynamically. | ||
|
||
# We'll even dynamically create their names. | ||
macro create_macro_name | ||
begin | ||
str dyn_macro | ||
get i | ||
endmacro | ||
|
||
|
||
macro create_dynamic_macros count | ||
begin | ||
times (get count) | ||
macro (create_macro_name) | ||
begin | ||
strl "Wow! This is a dynamic macro." | ||
endmacro | ||
endtimes | ||
endmacro | ||
|
||
create_dynamic_macros 23 | ||
|
||
dyn_macro16 | ||
dyn_macro4 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
strl "Programmers love powers of 2. How about 2^4?" | ||
endl | ||
|
||
times 2 | ||
times 2 | ||
times 2 | ||
times 2 | ||
str loop! | ||
endtimes | ||
endtimes | ||
endtimes | ||
endtimes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Use `set` to assign a GLOBAL variable. | ||
set foo (u8 33) | ||
|
||
# Use `get` to retrieve the current value. | ||
set bar (get foo) | ||
|
||
# Loops are fun | ||
times 10 | ||
str (get bar) | ||
endtimes |