├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── msvc.mk ├── t ├── Makefile ├── calc.ws ├── count.ws ├── expects │ ├── calc.txt │ ├── count.txt │ ├── fact.txt │ ├── fibonacci.txt │ ├── hanoi.txt │ ├── hworld.txt │ ├── name.txt │ └── sudoku.txt ├── fact.ws ├── fibonacci.ws ├── hanoi.ws ├── hworld.ws ├── inputs │ ├── calc.txt │ ├── fact.txt │ ├── fibonacci.txt │ ├── hanoi.txt │ ├── name.txt │ └── sudoku.txt ├── name.ws └── sudoku.ws └── whitespace.c /.gitignore: -------------------------------------------------------------------------------- 1 | getopt/ 2 | msvcdbg/ 3 | *.exe 4 | *.lib 5 | *.o 6 | *.obj 7 | *.out 8 | *.pdb 9 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - gcc 4 | - clang 5 | script: make CC="$CC" && make test 6 | sudo: false 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 koturn 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(DEBUG),true) 2 | OPT_CFLAGS := -O0 -g3 -ftrapv -fstack-protector-all -D_FORTIFY_SOURCE=2 3 | OPT_LDLIBS := -lssp 4 | ifneq ($(shell echo $$OSTYPE),cygwin) 5 | OPT_CFLAGS += -fsanitize=address -fno-omit-frame-pointer 6 | OPT_LDLIBS += -fsanitize=address 7 | endif 8 | else 9 | ifeq ($(OPT),true) 10 | OPT_CFLAGS := -flto -Ofast -march=native -DNDEBUG 11 | OPT_LDFLAGS := -flto -s 12 | else 13 | ifeq ($(LTO),true) 14 | OPT_CFLAGS := -flto -DNDEBUG 15 | OPT_LDFLAGS := -flto 16 | else 17 | OPT_CFLAGS := -O3 -DNDEBUG 18 | OPT_LDFLAGS := -s 19 | endif 20 | endif 21 | endif 22 | 23 | WARNING_CFLAGS := \ 24 | -Wall \ 25 | -Wextra \ 26 | -Wabi \ 27 | -Wcast-align \ 28 | -Wcast-qual \ 29 | -Wconversion \ 30 | -Wdisabled-optimization \ 31 | -Wdouble-promotion \ 32 | -Wfloat-equal \ 33 | -Wformat=2 \ 34 | -Winit-self \ 35 | -Winline \ 36 | -Wlogical-op \ 37 | -Wmissing-declarations \ 38 | -Wpointer-arith \ 39 | -Wredundant-decls \ 40 | -Wstrict-aliasing=2 \ 41 | -Wsuggest-attribute=const \ 42 | -Wsuggest-attribute=noreturn \ 43 | -Wsuggest-attribute=pure \ 44 | -Wswitch-enum \ 45 | -Wundef \ 46 | -Wunsafe-loop-optimizations \ 47 | -Wunreachable-code \ 48 | -Wwrite-strings \ 49 | -Wc++-compat \ 50 | -Wbad-function-cast \ 51 | -Wjump-misses-init \ 52 | -Wmissing-prototypes \ 53 | -Wunsuffixed-float-constants \ 54 | -Wno-unused-result \ 55 | -pedantic 56 | 57 | 58 | MAX_SOURCE_SIZE ?= 65536 59 | MAX_BYTECODE_SIZE ?= 1048576 60 | MAX_LABEL_LENGTH ?= 65536 61 | MAX_N_LABEL ?= 1024 62 | UNDEF_LIST_SIZE ?= 256 63 | STACK_SIZE ?= 65536 64 | HEAP_SIZE ?= 65536 65 | CALL_STACK_SIZE ?= 65536 66 | WS_INT ?= int 67 | WS_ADDR_INT ?= 'unsigned int' 68 | INDENT_STR ?= '" "' 69 | MACROS ?= -DMAX_SOURCE_SIZE=$(MAX_SOURCE_SIZE) \ 70 | -DMAX_BYTECODE_SIZE=$(MAX_BYTECODE_SIZE) \ 71 | -DMAX_LABEL_LENGTH=$(MAX_LABEL_LENGTH) \ 72 | -DMAX_N_LABEL=$(MAX_N_LABEL) \ 73 | -DUNDEF_LIST_SIZE=$(UNDEF_LIST_SIZE) \ 74 | -DSTACK_SIZE=$(STACK_SIZE) \ 75 | -DHEAP_SIZE=$(HEAP_SIZE) \ 76 | -DCALL_STACK_SIZE=$(CALL_STACK_SIZE) \ 77 | -DWS_INT=$(WS_INT) \ 78 | -DWS_ADDR_INT=$(WS_ADDR_INT) \ 79 | -DINDENT_STR=$(INDENT_STR) 80 | 81 | CC := gcc $(if $(STDC), $(addprefix -std=, $(STDC)),) 82 | MAKE := make 83 | MKDIR := mkdir -p 84 | CP := cp 85 | RM := rm -f 86 | CTAGS := ctags 87 | CFLAGS := -pipe $(WARNING_CFLAGS) $(OPT_CFLAGS) 88 | CPPFLAGS := $(MACROS) 89 | LDFLAGS := -pipe $(OPT_LDFLAGS) 90 | CTAGSFLAGS := -R --languages=c 91 | LDLIBS := $(OPT_LDLIBS) 92 | TARGET := whitespace 93 | OBJS := $(addsuffix .o, $(basename $(TARGET))) 94 | SRCS := $(OBJS:.o=.c) 95 | DEPENDS := depends.mk 96 | 97 | ifeq ($(OS),Windows_NT) 98 | TARGET := $(addsuffix .exe, $(TARGET)) 99 | else 100 | TARGET := $(addsuffix .out, $(TARGET)) 101 | endif 102 | INSTALLED_TARGET := $(if $(PREFIX), $(PREFIX),/usr/local)/bin/$(TARGET) 103 | 104 | %.exe: 105 | $(CC) $(LDFLAGS) $(filter %.c %.o, $^) $(LDLIBS) -o $@ 106 | %.out: 107 | $(CC) $(LDFLAGS) $(filter %.c %.o, $^) $(LDLIBS) -o $@ 108 | 109 | 110 | .PHONY: all test depends syntax ctags install uninstall clean cleanobj 111 | all: $(TARGET) 112 | $(TARGET): $(OBJS) 113 | 114 | $(foreach SRC,$(SRCS),$(eval $(filter-out \,$(shell $(CC) -MM $(SRC))))) 115 | 116 | test: $(TARGET) 117 | $(MAKE) -C t/ 118 | 119 | depends: 120 | $(CC) -MM $(SRCS) > $(DEPENDS) 121 | 122 | syntax: 123 | $(CC) $(SRCS) $(STD_CFLAGS) -fsyntax-only $(WARNING_CFLAGS) $(INCS) $(MACROS) 124 | 125 | ctags: 126 | $(CTAGS) $(CTAGSFLAGS) 127 | 128 | install: $(INSTALLED_TARGET) 129 | $(INSTALLED_TARGET): $(TARGET) 130 | @[ ! -d $(@D) ] && $(MKDIR) $(@D) || : 131 | $(CP) $< $@ 132 | 133 | uninstall: 134 | $(RM) $(INSTALLED_TARGET) 135 | 136 | clean: 137 | $(RM) $(TARGET) $(OBJS) 138 | 139 | cleanobj: 140 | $(RM) $(OBJS) 141 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Whitespace 2 | ========== 3 | 4 | [![Build Status](https://travis-ci.org/koturn/Whitespace.png)](https://travis-ci.org/koturn/Whitespace) 5 | 6 | Whitespace interpreter and C-translator. 7 | 8 | 9 | ## Usage 10 | 11 | ### Run Whitespace program 12 | 13 | ```sh 14 | $ ./whitespace [Whitespace source file] 15 | ``` 16 | 17 | ### Tanslate Whitespace to C 18 | 19 | Specify ```-t``` flag and ```-o``` flag. 20 | 21 | ```sh 22 | $ ./whitespace [Whitespace source file] -t -o out.c 23 | ``` 24 | 25 | If you don't specify output file with ```-o```, C source code will output 26 | stdout. 27 | 28 | ### Options 29 | 30 | Options | Function 31 | -----------------------------------|------------------------------------ 32 | ```-b```, ```--bytecode``` | Show code in hexadecimal 33 | ```-f```, ```--filter``` | Visualize whitespace source code 34 | ```-h```, ```--help``` | Show help and exit 35 | ```-m```, ```--mnemonic``` | Show byte code in mnemonic format 36 | ```-o FILE```, ```--output=FILE``` | Specify output filename 37 | ```-t```, ```--translate``` | Translate brainfuck to C source code 38 | 39 | 40 | ## Build 41 | 42 | Use [Makefile](Makefile). 43 | 44 | ```sh 45 | $ make 46 | ``` 47 | 48 | If you want to build with MSVC, use [msvc.mk](msvc.mk). 49 | [msvc.mk](msvc.mk) is written for nmake. 50 | 51 | ```sh 52 | > nmake /f msvc.mk 53 | ``` 54 | 55 | 56 | ## Dependent libraries 57 | 58 | #### MSVC only 59 | 60 | - [getopt clone](https://github.com/koturn/getopt) 61 | 62 | 63 | ## References 64 | 65 | - [http://compsoc.dur.ac.uk/whitespace/](http://compsoc.dur.ac.uk/whitespace/) 66 | 67 | 68 | ## LICENSE 69 | 70 | This software is released under the MIT License, see [LICENSE](LICENSE). 71 | -------------------------------------------------------------------------------- /msvc.mk: -------------------------------------------------------------------------------- 1 | ### This Makefile was written for nmake. ### 2 | GETOPT_DIR = getopt 3 | GETOPT_REPOSITORY = https://github.com/koturn/$(GETOPT_DIR).git 4 | GETOPT_LIBS_DIR = $(GETOPT_DIR)/lib 5 | GETOPT_LIB = getopt$(DBG_SUFFIX).lib 6 | GETOPT_LDLIBS = /LIBPATH:$(GETOPT_LIBS_DIR) $(GETOPT_LIB) 7 | GETOPT_INCS = /Igetopt/include/ 8 | 9 | !if "$(CRTDLL)" == "true" 10 | CRTLIB = /MD$(DBG_SUFFIX) 11 | !else 12 | CRTLIB = /MT$(DBG_SUFFIX) 13 | !endif 14 | 15 | !if "$(DEBUG)" == "true" 16 | MSVCDBG_DIR = msvcdbg 17 | MSVCDBG_REPOSITORY = https://github.com/koturn/$(MSVCDBG_DIR).git 18 | MSVCDBG_INCS = /Imsvcdbg/ 19 | 20 | DBG_SUFFIX = d 21 | COPTFLAGS = /Od /GS /Zi $(CRTLIB) 22 | LDOPTFLAGS = /Od /GS /Zi $(CRTLIB) 23 | MSVC_MACROS = /D_CRTDBG_MAP_ALLOC /D_USE_MATH_DEFINES 24 | !else 25 | DBG_SUFFIX = 26 | COPTFLAGS = /Ox /GL $(CRTLIB) 27 | LDOPTFLAGS = /Ox /GL $(CRTLIB) 28 | MSVC_MACROS = /DNDEBUG /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS \ 29 | /D_USE_MATH_DEFINES 30 | !endif 31 | 32 | MAX_SOURCE_SIZE = 65536 33 | MAX_BYTECODE_SIZE = 1048576 34 | MAX_LABEL_LENGTH = 65536 35 | MAX_N_LABEL = 1024 36 | UNDEF_LIST_SIZE = 256 37 | STACK_SIZE = 65536 38 | HEAP_SIZE = 65536 39 | CALL_STACK_SIZE = 65536 40 | WS_INT = int 41 | WS_ADDR_INT = "unsigned int" 42 | INDENT_STR = "\" \"" 43 | 44 | MACROS = $(MSVC_MACROS) \ 45 | /DMAX_SOURCE_SIZE=$(MAX_SOURCE_SIZE) \ 46 | /DMAX_BYTECODE_SIZE=$(MAX_BYTECODE_SIZE) \ 47 | /DMAX_LABEL_LENGTH=$(MAX_LABEL_LENGTH) \ 48 | /DMAX_N_LABEL=$(MAX_N_LABEL) \ 49 | /DUNDEF_LIST_SIZE=$(UNDEF_LIST_SIZE) \ 50 | /DSTACK_SIZE=$(STACK_SIZE) \ 51 | /DHEAP_SIZE=$(HEAP_SIZE) \ 52 | /DCALL_STACK_SIZE=$(CALL_STACK_SIZE) \ 53 | /DWS_INT=$(WS_INT) \ 54 | /DWS_ADDR_INT=$(WS_ADDR_INT) \ 55 | /DINDENT_STR=$(INDENT_STR) 56 | 57 | CC = cl 58 | RM = del /F 59 | MAKE = $(MAKE) /nologo 60 | GIT = git 61 | INCS = $(GETOPT_INCS) $(MSVCDBG_INCS) 62 | CFLAGS = /nologo $(COPTFLAGS) /W4 /c $(INCS) $(MACROS) 63 | LDFLAGS = /nologo $(LDOPTFLAGS) 64 | LDLIBS = /link $(GETOPT_LDLIBS) 65 | TARGET = whitespace.exe 66 | OBJ = $(TARGET:.exe=.obj) 67 | SRC = $(TARGET:.exe=.c) 68 | MAKEFILE = msvc.mk 69 | 70 | 71 | .SUFFIXES: .c .obj .exe 72 | .obj.exe: 73 | $(CC) $(LDFLAGS) $** /Fe$@ $(LDLIBS) 74 | .c.obj: 75 | $(CC) $(CFLAGS) $** /Fo$@ 76 | 77 | 78 | all: $(GETOPT_LIBS_DIR)/$(GETOPT_LIB) $(MSVCDBG_DIR)/NUL $(TARGET) 79 | 80 | $(TARGET): $(OBJ) 81 | 82 | $(OBJ): $(SRC) 83 | 84 | $(GETOPT_LIBS_DIR)/$(GETOPT_LIB): 85 | @if not exist $(@D)/NUL \ 86 | $(GIT) clone $(GETOPT_REPOSITORY) 87 | cd $(GETOPT_DIR) & $(MAKE) /f $(MAKEFILE) & cd $(MAKEDIR) 88 | 89 | $(MSVCDBG_DIR)/NUL: 90 | @if not exist $(@D)/NUL \ 91 | $(GIT) clone $(MSVCDBG_REPOSITORY) 92 | 93 | 94 | test: 95 | $(TARGET) -h 96 | 97 | 98 | clean: 99 | $(RM) $(TARGET) $(OBJ) 100 | cleanobj: 101 | $(RM) $(OBJ) 102 | -------------------------------------------------------------------------------- /t/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(OS),Windows_NT) 2 | BIN_SUFFIX := .exe 3 | else 4 | BIN_SUFFIX := .out 5 | endif 6 | 7 | WHITESPACE := $(addsuffix $(BIN_SUFFIX),../whitespace) 8 | TESTS := $(basename $(sort $(wildcard *.ws))) 9 | INPUTS_DIR := inputs 10 | EXPECTS_DIR := expects 11 | TRANSPILED_DIR := transpiled 12 | MKDIR := mkdir 13 | ECHO := echo 14 | DIFF := diff -Z --strip-trailing-cr 15 | RM := rm -f 16 | CC := gcc 17 | CFLAGS := -pipe -O2 -Wno-unused-result 18 | 19 | 20 | define generate-interpreter-test 21 | $1: 22 | @$(ECHO) -n "Interpreter test: $2.ws ... " 23 | @([ -f $(INPUTS_DIR)/$2.txt ] \ 24 | && $(WHITESPACE) $2.ws < $(INPUTS_DIR)/$2.txt || $(WHITESPACE) $2.ws) \ 25 | | $(DIFF) - $(EXPECTS_DIR)/$2.txt > /dev/null 26 | @$(ECHO) 'Success' 27 | endef 28 | 29 | define generate-transpiler-test 30 | $1: $(TRANSPILED_DIR)/$2$(BIN_SUFFIX) 31 | @$(ECHO) -n "Transpiler test: $2.ws ... " 32 | @([ -f $(INPUTS_DIR)/$2.txt ] \ 33 | && $$< < $(INPUTS_DIR)/$2.txt || $$<) \ 34 | | $(DIFF) - $(EXPECTS_DIR)/$2.txt 35 | @$(ECHO) 'Success' 36 | 37 | $(TRANSPILED_DIR)/$2$(BIN_SUFFIX): $2.ws .FORCE 38 | @[ ! -d $$(@D) ] && $(MKDIR) $$(@D) || : 39 | @$(WHITESPACE) $$< -t | $(CC) $(CFLAGS) -xc - -o $$@ > /dev/null 40 | endef 41 | 42 | 43 | .PHONY: all interpreter binary clean $(TESTS) 44 | 45 | .FORCE: 46 | 47 | all: interpreter binary 48 | 49 | interpreter: $(foreach TEST,$(TESTS),interpreter_$(TEST)) 50 | 51 | $(foreach TEST,$(TESTS),$(eval $(call generate-interpreter-test,interpreter_$(TEST),$(TEST)))) 52 | 53 | binary: $(foreach TEST,$(TESTS),transpiler_$(TEST)) 54 | 55 | $(foreach TEST,$(TESTS),$(eval $(call generate-transpiler-test,transpiler_$(TEST),$(TEST)))) 56 | 57 | clean: 58 | $(RM) $(TRANSPILED_DIR)/*.exe 59 | -------------------------------------------------------------------------------- /t/calc.ws: -------------------------------------------------------------------------------- 1 | Ask the user to enter 2 | a list of numbers terminated by -1. 3 | 4 | When they've finished, tell 5 | them what the total is. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /t/count.ws: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /t/expects/calc.txt: -------------------------------------------------------------------------------- 1 | Enter some numbers, then -1 to finish 2 | Number:Number:Number:Number:Number:Number:Total is 15 3 | -------------------------------------------------------------------------------- /t/expects/count.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 10 | 10 11 | -------------------------------------------------------------------------------- /t/expects/fact.txt: -------------------------------------------------------------------------------- 1 | Enter a number: 10! = 3628800 2 | -------------------------------------------------------------------------------- /t/expects/fibonacci.txt: -------------------------------------------------------------------------------- 1 | How many? 1 2 | 1 3 | 2 4 | 3 5 | 5 6 | 8 7 | 13 8 | 21 9 | 34 10 | 55 11 | 89 12 | 144 13 | -------------------------------------------------------------------------------- /t/expects/hanoi.txt: -------------------------------------------------------------------------------- 1 | Enter a number: 1 -> 2 2 | 1 -> 3 3 | 2 -> 3 4 | 1 -> 2 5 | 3 -> 1 6 | 3 -> 2 7 | 1 -> 2 8 | 1 -> 3 9 | 2 -> 3 10 | 2 -> 1 11 | 3 -> 1 12 | 2 -> 3 13 | 1 -> 2 14 | 1 -> 3 15 | 2 -> 3 16 | 1 -> 2 17 | 3 -> 1 18 | 3 -> 2 19 | 1 -> 2 20 | 3 -> 1 21 | 2 -> 3 22 | 2 -> 1 23 | 3 -> 1 24 | 3 -> 2 25 | 1 -> 2 26 | 1 -> 3 27 | 2 -> 3 28 | 1 -> 2 29 | 3 -> 1 30 | 3 -> 2 31 | 1 -> 2 32 | 1 -> 3 33 | 2 -> 3 34 | 2 -> 1 35 | 3 -> 1 36 | 2 -> 3 37 | 1 -> 2 38 | 1 -> 3 39 | 2 -> 3 40 | 2 -> 1 41 | 3 -> 1 42 | 3 -> 2 43 | 1 -> 2 44 | 3 -> 1 45 | 2 -> 3 46 | 2 -> 1 47 | 3 -> 1 48 | 2 -> 3 49 | 1 -> 2 50 | 1 -> 3 51 | 2 -> 3 52 | 1 -> 2 53 | 3 -> 1 54 | 3 -> 2 55 | 1 -> 2 56 | 1 -> 3 57 | 2 -> 3 58 | 2 -> 1 59 | 3 -> 1 60 | 2 -> 3 61 | 1 -> 2 62 | 1 -> 3 63 | 2 -> 3 64 | 1 -> 2 65 | 3 -> 1 66 | 3 -> 2 67 | 1 -> 2 68 | 3 -> 1 69 | 2 -> 3 70 | 2 -> 1 71 | 3 -> 1 72 | 3 -> 2 73 | 1 -> 2 74 | 1 -> 3 75 | 2 -> 3 76 | 1 -> 2 77 | 3 -> 1 78 | 3 -> 2 79 | 1 -> 2 80 | 3 -> 1 81 | 2 -> 3 82 | 2 -> 1 83 | 3 -> 1 84 | 2 -> 3 85 | 1 -> 2 86 | 1 -> 3 87 | 2 -> 3 88 | 2 -> 1 89 | 3 -> 1 90 | 3 -> 2 91 | 1 -> 2 92 | 3 -> 1 93 | 2 -> 3 94 | 2 -> 1 95 | 3 -> 1 96 | 3 -> 2 97 | 1 -> 2 98 | 1 -> 3 99 | 2 -> 3 100 | 1 -> 2 101 | 3 -> 1 102 | 3 -> 2 103 | 1 -> 2 104 | 1 -> 3 105 | 2 -> 3 106 | 2 -> 1 107 | 3 -> 1 108 | 2 -> 3 109 | 1 -> 2 110 | 1 -> 3 111 | 2 -> 3 112 | 1 -> 2 113 | 3 -> 1 114 | 3 -> 2 115 | 1 -> 2 116 | 3 -> 1 117 | 2 -> 3 118 | 2 -> 1 119 | 3 -> 1 120 | 3 -> 2 121 | 1 -> 2 122 | 1 -> 3 123 | 2 -> 3 124 | 1 -> 2 125 | 3 -> 1 126 | 3 -> 2 127 | 1 -> 2 128 | 1 -> 3 129 | 2 -> 3 130 | 2 -> 1 131 | 3 -> 1 132 | 2 -> 3 133 | 1 -> 2 134 | 1 -> 3 135 | 2 -> 3 136 | 2 -> 1 137 | 3 -> 1 138 | 3 -> 2 139 | 1 -> 2 140 | 3 -> 1 141 | 2 -> 3 142 | 2 -> 1 143 | 3 -> 1 144 | 2 -> 3 145 | 1 -> 2 146 | 1 -> 3 147 | 2 -> 3 148 | 1 -> 2 149 | 3 -> 1 150 | 3 -> 2 151 | 1 -> 2 152 | 1 -> 3 153 | 2 -> 3 154 | 2 -> 1 155 | 3 -> 1 156 | 2 -> 3 157 | 1 -> 2 158 | 1 -> 3 159 | 2 -> 3 160 | 2 -> 1 161 | 3 -> 1 162 | 3 -> 2 163 | 1 -> 2 164 | 3 -> 1 165 | 2 -> 3 166 | 2 -> 1 167 | 3 -> 1 168 | 3 -> 2 169 | 1 -> 2 170 | 1 -> 3 171 | 2 -> 3 172 | 1 -> 2 173 | 3 -> 1 174 | 3 -> 2 175 | 1 -> 2 176 | 3 -> 1 177 | 2 -> 3 178 | 2 -> 1 179 | 3 -> 1 180 | 2 -> 3 181 | 1 -> 2 182 | 1 -> 3 183 | 2 -> 3 184 | 2 -> 1 185 | 3 -> 1 186 | 3 -> 2 187 | 1 -> 2 188 | 3 -> 1 189 | 2 -> 3 190 | 2 -> 1 191 | 3 -> 1 192 | 2 -> 3 193 | 1 -> 2 194 | 1 -> 3 195 | 2 -> 3 196 | 1 -> 2 197 | 3 -> 1 198 | 3 -> 2 199 | 1 -> 2 200 | 1 -> 3 201 | 2 -> 3 202 | 2 -> 1 203 | 3 -> 1 204 | 2 -> 3 205 | 1 -> 2 206 | 1 -> 3 207 | 2 -> 3 208 | 1 -> 2 209 | 3 -> 1 210 | 3 -> 2 211 | 1 -> 2 212 | 3 -> 1 213 | 2 -> 3 214 | 2 -> 1 215 | 3 -> 1 216 | 3 -> 2 217 | 1 -> 2 218 | 1 -> 3 219 | 2 -> 3 220 | 1 -> 2 221 | 3 -> 1 222 | 3 -> 2 223 | 1 -> 2 224 | 1 -> 3 225 | 2 -> 3 226 | 2 -> 1 227 | 3 -> 1 228 | 2 -> 3 229 | 1 -> 2 230 | 1 -> 3 231 | 2 -> 3 232 | 2 -> 1 233 | 3 -> 1 234 | 3 -> 2 235 | 1 -> 2 236 | 3 -> 1 237 | 2 -> 3 238 | 2 -> 1 239 | 3 -> 1 240 | 2 -> 3 241 | 1 -> 2 242 | 1 -> 3 243 | 2 -> 3 244 | 1 -> 2 245 | 3 -> 1 246 | 3 -> 2 247 | 1 -> 2 248 | 1 -> 3 249 | 2 -> 3 250 | 2 -> 1 251 | 3 -> 1 252 | 2 -> 3 253 | 1 -> 2 254 | 1 -> 3 255 | 2 -> 3 256 | 1 -> 2 257 | 3 -> 1 258 | 3 -> 2 259 | 1 -> 2 260 | 3 -> 1 261 | 2 -> 3 262 | 2 -> 1 263 | 3 -> 1 264 | 3 -> 2 265 | 1 -> 2 266 | 1 -> 3 267 | 2 -> 3 268 | 1 -> 2 269 | 3 -> 1 270 | 3 -> 2 271 | 1 -> 2 272 | 3 -> 1 273 | 2 -> 3 274 | 2 -> 1 275 | 3 -> 1 276 | 2 -> 3 277 | 1 -> 2 278 | 1 -> 3 279 | 2 -> 3 280 | 2 -> 1 281 | 3 -> 1 282 | 3 -> 2 283 | 1 -> 2 284 | 3 -> 1 285 | 2 -> 3 286 | 2 -> 1 287 | 3 -> 1 288 | 3 -> 2 289 | 1 -> 2 290 | 1 -> 3 291 | 2 -> 3 292 | 1 -> 2 293 | 3 -> 1 294 | 3 -> 2 295 | 1 -> 2 296 | 1 -> 3 297 | 2 -> 3 298 | 2 -> 1 299 | 3 -> 1 300 | 2 -> 3 301 | 1 -> 2 302 | 1 -> 3 303 | 2 -> 3 304 | 1 -> 2 305 | 3 -> 1 306 | 3 -> 2 307 | 1 -> 2 308 | 3 -> 1 309 | 2 -> 3 310 | 2 -> 1 311 | 3 -> 1 312 | 3 -> 2 313 | 1 -> 2 314 | 1 -> 3 315 | 2 -> 3 316 | 1 -> 2 317 | 3 -> 1 318 | 3 -> 2 319 | 1 -> 2 320 | 3 -> 1 321 | 2 -> 3 322 | 2 -> 1 323 | 3 -> 1 324 | 2 -> 3 325 | 1 -> 2 326 | 1 -> 3 327 | 2 -> 3 328 | 2 -> 1 329 | 3 -> 1 330 | 3 -> 2 331 | 1 -> 2 332 | 3 -> 1 333 | 2 -> 3 334 | 2 -> 1 335 | 3 -> 1 336 | 2 -> 3 337 | 1 -> 2 338 | 1 -> 3 339 | 2 -> 3 340 | 1 -> 2 341 | 3 -> 1 342 | 3 -> 2 343 | 1 -> 2 344 | 1 -> 3 345 | 2 -> 3 346 | 2 -> 1 347 | 3 -> 1 348 | 2 -> 3 349 | 1 -> 2 350 | 1 -> 3 351 | 2 -> 3 352 | 2 -> 1 353 | 3 -> 1 354 | 3 -> 2 355 | 1 -> 2 356 | 3 -> 1 357 | 2 -> 3 358 | 2 -> 1 359 | 3 -> 1 360 | 3 -> 2 361 | 1 -> 2 362 | 1 -> 3 363 | 2 -> 3 364 | 1 -> 2 365 | 3 -> 1 366 | 3 -> 2 367 | 1 -> 2 368 | 3 -> 1 369 | 2 -> 3 370 | 2 -> 1 371 | 3 -> 1 372 | 2 -> 3 373 | 1 -> 2 374 | 1 -> 3 375 | 2 -> 3 376 | 2 -> 1 377 | 3 -> 1 378 | 3 -> 2 379 | 1 -> 2 380 | 3 -> 1 381 | 2 -> 3 382 | 2 -> 1 383 | 3 -> 1 384 | 3 -> 2 385 | 1 -> 2 386 | 1 -> 3 387 | 2 -> 3 388 | 1 -> 2 389 | 3 -> 1 390 | 3 -> 2 391 | 1 -> 2 392 | 1 -> 3 393 | 2 -> 3 394 | 2 -> 1 395 | 3 -> 1 396 | 2 -> 3 397 | 1 -> 2 398 | 1 -> 3 399 | 2 -> 3 400 | 1 -> 2 401 | 3 -> 1 402 | 3 -> 2 403 | 1 -> 2 404 | 3 -> 1 405 | 2 -> 3 406 | 2 -> 1 407 | 3 -> 1 408 | 3 -> 2 409 | 1 -> 2 410 | 1 -> 3 411 | 2 -> 3 412 | 1 -> 2 413 | 3 -> 1 414 | 3 -> 2 415 | 1 -> 2 416 | 1 -> 3 417 | 2 -> 3 418 | 2 -> 1 419 | 3 -> 1 420 | 2 -> 3 421 | 1 -> 2 422 | 1 -> 3 423 | 2 -> 3 424 | 2 -> 1 425 | 3 -> 1 426 | 3 -> 2 427 | 1 -> 2 428 | 3 -> 1 429 | 2 -> 3 430 | 2 -> 1 431 | 3 -> 1 432 | 2 -> 3 433 | 1 -> 2 434 | 1 -> 3 435 | 2 -> 3 436 | 1 -> 2 437 | 3 -> 1 438 | 3 -> 2 439 | 1 -> 2 440 | 1 -> 3 441 | 2 -> 3 442 | 2 -> 1 443 | 3 -> 1 444 | 2 -> 3 445 | 1 -> 2 446 | 1 -> 3 447 | 2 -> 3 448 | 1 -> 2 449 | 3 -> 1 450 | 3 -> 2 451 | 1 -> 2 452 | 3 -> 1 453 | 2 -> 3 454 | 2 -> 1 455 | 3 -> 1 456 | 3 -> 2 457 | 1 -> 2 458 | 1 -> 3 459 | 2 -> 3 460 | 1 -> 2 461 | 3 -> 1 462 | 3 -> 2 463 | 1 -> 2 464 | 3 -> 1 465 | 2 -> 3 466 | 2 -> 1 467 | 3 -> 1 468 | 2 -> 3 469 | 1 -> 2 470 | 1 -> 3 471 | 2 -> 3 472 | 2 -> 1 473 | 3 -> 1 474 | 3 -> 2 475 | 1 -> 2 476 | 3 -> 1 477 | 2 -> 3 478 | 2 -> 1 479 | 3 -> 1 480 | 3 -> 2 481 | 1 -> 2 482 | 1 -> 3 483 | 2 -> 3 484 | 1 -> 2 485 | 3 -> 1 486 | 3 -> 2 487 | 1 -> 2 488 | 1 -> 3 489 | 2 -> 3 490 | 2 -> 1 491 | 3 -> 1 492 | 2 -> 3 493 | 1 -> 2 494 | 1 -> 3 495 | 2 -> 3 496 | 1 -> 2 497 | 3 -> 1 498 | 3 -> 2 499 | 1 -> 2 500 | 3 -> 1 501 | 2 -> 3 502 | 2 -> 1 503 | 3 -> 1 504 | 3 -> 2 505 | 1 -> 2 506 | 1 -> 3 507 | 2 -> 3 508 | 1 -> 2 509 | 3 -> 1 510 | 3 -> 2 511 | 1 -> 2 512 | 1 -> 3 513 | 2 -> 3 514 | 2 -> 1 515 | 3 -> 1 516 | 2 -> 3 517 | 1 -> 2 518 | 1 -> 3 519 | 2 -> 3 520 | 2 -> 1 521 | 3 -> 1 522 | 3 -> 2 523 | 1 -> 2 524 | 3 -> 1 525 | 2 -> 3 526 | 2 -> 1 527 | 3 -> 1 528 | 2 -> 3 529 | 1 -> 2 530 | 1 -> 3 531 | 2 -> 3 532 | 1 -> 2 533 | 3 -> 1 534 | 3 -> 2 535 | 1 -> 2 536 | 1 -> 3 537 | 2 -> 3 538 | 2 -> 1 539 | 3 -> 1 540 | 2 -> 3 541 | 1 -> 2 542 | 1 -> 3 543 | 2 -> 3 544 | 2 -> 1 545 | 3 -> 1 546 | 3 -> 2 547 | 1 -> 2 548 | 3 -> 1 549 | 2 -> 3 550 | 2 -> 1 551 | 3 -> 1 552 | 3 -> 2 553 | 1 -> 2 554 | 1 -> 3 555 | 2 -> 3 556 | 1 -> 2 557 | 3 -> 1 558 | 3 -> 2 559 | 1 -> 2 560 | 3 -> 1 561 | 2 -> 3 562 | 2 -> 1 563 | 3 -> 1 564 | 2 -> 3 565 | 1 -> 2 566 | 1 -> 3 567 | 2 -> 3 568 | 2 -> 1 569 | 3 -> 1 570 | 3 -> 2 571 | 1 -> 2 572 | 3 -> 1 573 | 2 -> 3 574 | 2 -> 1 575 | 3 -> 1 576 | 2 -> 3 577 | 1 -> 2 578 | 1 -> 3 579 | 2 -> 3 580 | 1 -> 2 581 | 3 -> 1 582 | 3 -> 2 583 | 1 -> 2 584 | 1 -> 3 585 | 2 -> 3 586 | 2 -> 1 587 | 3 -> 1 588 | 2 -> 3 589 | 1 -> 2 590 | 1 -> 3 591 | 2 -> 3 592 | 1 -> 2 593 | 3 -> 1 594 | 3 -> 2 595 | 1 -> 2 596 | 3 -> 1 597 | 2 -> 3 598 | 2 -> 1 599 | 3 -> 1 600 | 3 -> 2 601 | 1 -> 2 602 | 1 -> 3 603 | 2 -> 3 604 | 1 -> 2 605 | 3 -> 1 606 | 3 -> 2 607 | 1 -> 2 608 | 1 -> 3 609 | 2 -> 3 610 | 2 -> 1 611 | 3 -> 1 612 | 2 -> 3 613 | 1 -> 2 614 | 1 -> 3 615 | 2 -> 3 616 | 2 -> 1 617 | 3 -> 1 618 | 3 -> 2 619 | 1 -> 2 620 | 3 -> 1 621 | 2 -> 3 622 | 2 -> 1 623 | 3 -> 1 624 | 2 -> 3 625 | 1 -> 2 626 | 1 -> 3 627 | 2 -> 3 628 | 1 -> 2 629 | 3 -> 1 630 | 3 -> 2 631 | 1 -> 2 632 | 1 -> 3 633 | 2 -> 3 634 | 2 -> 1 635 | 3 -> 1 636 | 2 -> 3 637 | 1 -> 2 638 | 1 -> 3 639 | 2 -> 3 640 | 2 -> 1 641 | 3 -> 1 642 | 3 -> 2 643 | 1 -> 2 644 | 3 -> 1 645 | 2 -> 3 646 | 2 -> 1 647 | 3 -> 1 648 | 3 -> 2 649 | 1 -> 2 650 | 1 -> 3 651 | 2 -> 3 652 | 1 -> 2 653 | 3 -> 1 654 | 3 -> 2 655 | 1 -> 2 656 | 3 -> 1 657 | 2 -> 3 658 | 2 -> 1 659 | 3 -> 1 660 | 2 -> 3 661 | 1 -> 2 662 | 1 -> 3 663 | 2 -> 3 664 | 2 -> 1 665 | 3 -> 1 666 | 3 -> 2 667 | 1 -> 2 668 | 3 -> 1 669 | 2 -> 3 670 | 2 -> 1 671 | 3 -> 1 672 | 3 -> 2 673 | 1 -> 2 674 | 1 -> 3 675 | 2 -> 3 676 | 1 -> 2 677 | 3 -> 1 678 | 3 -> 2 679 | 1 -> 2 680 | 1 -> 3 681 | 2 -> 3 682 | 2 -> 1 683 | 3 -> 1 684 | 2 -> 3 685 | 1 -> 2 686 | 1 -> 3 687 | 2 -> 3 688 | 1 -> 2 689 | 3 -> 1 690 | 3 -> 2 691 | 1 -> 2 692 | 3 -> 1 693 | 2 -> 3 694 | 2 -> 1 695 | 3 -> 1 696 | 3 -> 2 697 | 1 -> 2 698 | 1 -> 3 699 | 2 -> 3 700 | 1 -> 2 701 | 3 -> 1 702 | 3 -> 2 703 | 1 -> 2 704 | 3 -> 1 705 | 2 -> 3 706 | 2 -> 1 707 | 3 -> 1 708 | 2 -> 3 709 | 1 -> 2 710 | 1 -> 3 711 | 2 -> 3 712 | 2 -> 1 713 | 3 -> 1 714 | 3 -> 2 715 | 1 -> 2 716 | 3 -> 1 717 | 2 -> 3 718 | 2 -> 1 719 | 3 -> 1 720 | 2 -> 3 721 | 1 -> 2 722 | 1 -> 3 723 | 2 -> 3 724 | 1 -> 2 725 | 3 -> 1 726 | 3 -> 2 727 | 1 -> 2 728 | 1 -> 3 729 | 2 -> 3 730 | 2 -> 1 731 | 3 -> 1 732 | 2 -> 3 733 | 1 -> 2 734 | 1 -> 3 735 | 2 -> 3 736 | 2 -> 1 737 | 3 -> 1 738 | 3 -> 2 739 | 1 -> 2 740 | 3 -> 1 741 | 2 -> 3 742 | 2 -> 1 743 | 3 -> 1 744 | 3 -> 2 745 | 1 -> 2 746 | 1 -> 3 747 | 2 -> 3 748 | 1 -> 2 749 | 3 -> 1 750 | 3 -> 2 751 | 1 -> 2 752 | 3 -> 1 753 | 2 -> 3 754 | 2 -> 1 755 | 3 -> 1 756 | 2 -> 3 757 | 1 -> 2 758 | 1 -> 3 759 | 2 -> 3 760 | 2 -> 1 761 | 3 -> 1 762 | 3 -> 2 763 | 1 -> 2 764 | 3 -> 1 765 | 2 -> 3 766 | 2 -> 1 767 | 3 -> 1 768 | 2 -> 3 769 | 1 -> 2 770 | 1 -> 3 771 | 2 -> 3 772 | 1 -> 2 773 | 3 -> 1 774 | 3 -> 2 775 | 1 -> 2 776 | 1 -> 3 777 | 2 -> 3 778 | 2 -> 1 779 | 3 -> 1 780 | 2 -> 3 781 | 1 -> 2 782 | 1 -> 3 783 | 2 -> 3 784 | 1 -> 2 785 | 3 -> 1 786 | 3 -> 2 787 | 1 -> 2 788 | 3 -> 1 789 | 2 -> 3 790 | 2 -> 1 791 | 3 -> 1 792 | 3 -> 2 793 | 1 -> 2 794 | 1 -> 3 795 | 2 -> 3 796 | 1 -> 2 797 | 3 -> 1 798 | 3 -> 2 799 | 1 -> 2 800 | 1 -> 3 801 | 2 -> 3 802 | 2 -> 1 803 | 3 -> 1 804 | 2 -> 3 805 | 1 -> 2 806 | 1 -> 3 807 | 2 -> 3 808 | 2 -> 1 809 | 3 -> 1 810 | 3 -> 2 811 | 1 -> 2 812 | 3 -> 1 813 | 2 -> 3 814 | 2 -> 1 815 | 3 -> 1 816 | 2 -> 3 817 | 1 -> 2 818 | 1 -> 3 819 | 2 -> 3 820 | 1 -> 2 821 | 3 -> 1 822 | 3 -> 2 823 | 1 -> 2 824 | 1 -> 3 825 | 2 -> 3 826 | 2 -> 1 827 | 3 -> 1 828 | 2 -> 3 829 | 1 -> 2 830 | 1 -> 3 831 | 2 -> 3 832 | 1 -> 2 833 | 3 -> 1 834 | 3 -> 2 835 | 1 -> 2 836 | 3 -> 1 837 | 2 -> 3 838 | 2 -> 1 839 | 3 -> 1 840 | 3 -> 2 841 | 1 -> 2 842 | 1 -> 3 843 | 2 -> 3 844 | 1 -> 2 845 | 3 -> 1 846 | 3 -> 2 847 | 1 -> 2 848 | 3 -> 1 849 | 2 -> 3 850 | 2 -> 1 851 | 3 -> 1 852 | 2 -> 3 853 | 1 -> 2 854 | 1 -> 3 855 | 2 -> 3 856 | 2 -> 1 857 | 3 -> 1 858 | 3 -> 2 859 | 1 -> 2 860 | 3 -> 1 861 | 2 -> 3 862 | 2 -> 1 863 | 3 -> 1 864 | 3 -> 2 865 | 1 -> 2 866 | 1 -> 3 867 | 2 -> 3 868 | 1 -> 2 869 | 3 -> 1 870 | 3 -> 2 871 | 1 -> 2 872 | 1 -> 3 873 | 2 -> 3 874 | 2 -> 1 875 | 3 -> 1 876 | 2 -> 3 877 | 1 -> 2 878 | 1 -> 3 879 | 2 -> 3 880 | 1 -> 2 881 | 3 -> 1 882 | 3 -> 2 883 | 1 -> 2 884 | 3 -> 1 885 | 2 -> 3 886 | 2 -> 1 887 | 3 -> 1 888 | 3 -> 2 889 | 1 -> 2 890 | 1 -> 3 891 | 2 -> 3 892 | 1 -> 2 893 | 3 -> 1 894 | 3 -> 2 895 | 1 -> 2 896 | 1 -> 3 897 | 2 -> 3 898 | 2 -> 1 899 | 3 -> 1 900 | 2 -> 3 901 | 1 -> 2 902 | 1 -> 3 903 | 2 -> 3 904 | 2 -> 1 905 | 3 -> 1 906 | 3 -> 2 907 | 1 -> 2 908 | 3 -> 1 909 | 2 -> 3 910 | 2 -> 1 911 | 3 -> 1 912 | 2 -> 3 913 | 1 -> 2 914 | 1 -> 3 915 | 2 -> 3 916 | 1 -> 2 917 | 3 -> 1 918 | 3 -> 2 919 | 1 -> 2 920 | 1 -> 3 921 | 2 -> 3 922 | 2 -> 1 923 | 3 -> 1 924 | 2 -> 3 925 | 1 -> 2 926 | 1 -> 3 927 | 2 -> 3 928 | 2 -> 1 929 | 3 -> 1 930 | 3 -> 2 931 | 1 -> 2 932 | 3 -> 1 933 | 2 -> 3 934 | 2 -> 1 935 | 3 -> 1 936 | 3 -> 2 937 | 1 -> 2 938 | 1 -> 3 939 | 2 -> 3 940 | 1 -> 2 941 | 3 -> 1 942 | 3 -> 2 943 | 1 -> 2 944 | 3 -> 1 945 | 2 -> 3 946 | 2 -> 1 947 | 3 -> 1 948 | 2 -> 3 949 | 1 -> 2 950 | 1 -> 3 951 | 2 -> 3 952 | 2 -> 1 953 | 3 -> 1 954 | 3 -> 2 955 | 1 -> 2 956 | 3 -> 1 957 | 2 -> 3 958 | 2 -> 1 959 | 3 -> 1 960 | 2 -> 3 961 | 1 -> 2 962 | 1 -> 3 963 | 2 -> 3 964 | 1 -> 2 965 | 3 -> 1 966 | 3 -> 2 967 | 1 -> 2 968 | 1 -> 3 969 | 2 -> 3 970 | 2 -> 1 971 | 3 -> 1 972 | 2 -> 3 973 | 1 -> 2 974 | 1 -> 3 975 | 2 -> 3 976 | 1 -> 2 977 | 3 -> 1 978 | 3 -> 2 979 | 1 -> 2 980 | 3 -> 1 981 | 2 -> 3 982 | 2 -> 1 983 | 3 -> 1 984 | 3 -> 2 985 | 1 -> 2 986 | 1 -> 3 987 | 2 -> 3 988 | 1 -> 2 989 | 3 -> 1 990 | 3 -> 2 991 | 1 -> 2 992 | 1 -> 3 993 | 2 -> 3 994 | 2 -> 1 995 | 3 -> 1 996 | 2 -> 3 997 | 1 -> 2 998 | 1 -> 3 999 | 2 -> 3 1000 | 2 -> 1 1001 | 3 -> 1 1002 | 3 -> 2 1003 | 1 -> 2 1004 | 3 -> 1 1005 | 2 -> 3 1006 | 2 -> 1 1007 | 3 -> 1 1008 | 2 -> 3 1009 | 1 -> 2 1010 | 1 -> 3 1011 | 2 -> 3 1012 | 1 -> 2 1013 | 3 -> 1 1014 | 3 -> 2 1015 | 1 -> 2 1016 | 1 -> 3 1017 | 2 -> 3 1018 | 2 -> 1 1019 | 3 -> 1 1020 | 2 -> 3 1021 | 1 -> 2 1022 | 1 -> 3 1023 | 2 -> 3 1024 | -------------------------------------------------------------------------------- /t/expects/hworld.txt: -------------------------------------------------------------------------------- 1 | Hello, world of spaces! 2 | -------------------------------------------------------------------------------- /t/expects/name.txt: -------------------------------------------------------------------------------- 1 | Please enter your name: Hello test 2 | 3 | -------------------------------------------------------------------------------- /t/expects/sudoku.txt: -------------------------------------------------------------------------------- 1 | 2 | Sudoku Solver - written in Whitespace! 3 | 4 | Instructions: 5 | 6 | Please enter a 9x9 grid of numbers (0-9). 7 | Do not put spaces between the numbers. 8 | '0' represents an empty cell: 9 | 10 | 11 | Please be patient. 12 | Easy sudokus typically take a minute or two on my Core 2 Duo. 13 | 14 | 15 | 534 678 912 16 | 672 195 348 17 | 198 342 567 18 | 19 | 859 761 423 20 | 426 853 791 21 | 713 924 856 22 | 23 | 961 537 284 24 | 287 419 635 25 | 345 286 179 26 | 27 | Success! 28 | -------------------------------------------------------------------------------- /t/fact.ws: -------------------------------------------------------------------------------- 1 | Ask the user for a 2 | number, then calculate its 3 | factorial. 4 | 5 | This program shows how we can handle recursion 6 | and arbitrarily big numbers. 7 | 8 | Try giving 10000 as 9 | input... 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /t/fibonacci.ws: -------------------------------------------------------------------------------- 1 | Ask the user how many 2 | fibonacci numbers 3 | they want from the sequence 4 | and print 5 | that many one number per line. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /t/hanoi.ws: -------------------------------------------------------------------------------- 1 | Towers of Hanoi solver. 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | -------------------------------------------------------------------------------- /t/hworld.ws: -------------------------------------------------------------------------------- 1 | Say hello. 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /t/inputs/calc.txt: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | -1 7 | -------------------------------------------------------------------------------- /t/inputs/fact.txt: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /t/inputs/fibonacci.txt: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /t/inputs/hanoi.txt: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /t/inputs/name.txt: -------------------------------------------------------------------------------- 1 | test 2 | -------------------------------------------------------------------------------- /t/inputs/sudoku.txt: -------------------------------------------------------------------------------- 1 | 530070000 2 | 600195000 3 | 098000060 4 | 800060003 5 | 400803001 6 | 700020006 7 | 060000280 8 | 000419005 9 | 000080079 10 | -------------------------------------------------------------------------------- /t/name.ws: -------------------------------------------------------------------------------- 1 | Ask the user for their 2 | name. Then say hello. 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /t/sudoku.ws: -------------------------------------------------------------------------------- 1 | http://forums.thedailywtf.com/forums/t/11787.aspx 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 821 | 822 | 823 | 824 | 825 | 826 | 827 | 828 | 829 | 830 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 | 943 | 944 | 945 | 946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 | 954 | 955 | 956 | 957 | 958 | 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 967 | 968 | 969 | 970 | 971 | 972 | 973 | 974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 | 984 | 985 | 986 | 987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 | 995 | 996 | 997 | 998 | 999 | 1000 | 1001 | 1002 | 1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | 1012 | 1013 | 1014 | 1015 | 1016 | 1017 | 1018 | 1019 | 1020 | 1021 | 1022 | 1023 | 1024 | 1025 | 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | 1034 | 1035 | 1036 | 1037 | 1038 | 1039 | 1040 | 1041 | 1042 | 1043 | 1044 | 1045 | 1046 | 1047 | 1048 | 1049 | 1050 | 1051 | 1052 | 1053 | 1054 | 1055 | 1056 | 1057 | 1058 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1128 | 1129 | 1130 | 1131 | 1132 | 1133 | 1134 | 1135 | 1136 | 1137 | 1138 | 1139 | 1140 | 1141 | 1142 | 1143 | 1144 | 1145 | 1146 | 1147 | 1148 | 1149 | 1150 | 1151 | 1152 | 1153 | 1154 | 1155 | 1156 | 1157 | 1158 | 1159 | 1160 | 1161 | 1162 | 1163 | 1164 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | 1252 | 1253 | 1254 | 1255 | 1256 | 1257 | 1258 | 1259 | 1260 | 1261 | 1262 | 1263 | 1264 | 1265 | 1266 | 1267 | 1268 | 1269 | 1270 | 1271 | 1272 | 1273 | 1274 | 1275 | 1276 | 1277 | 1278 | 1279 | 1280 | 1281 | 1282 | 1283 | 1284 | 1285 | 1286 | 1287 | 1288 | 1289 | 1290 | 1291 | 1292 | 1293 | 1294 | 1295 | 1296 | 1297 | 1298 | 1299 | 1300 | 1301 | 1302 | 1303 | 1304 | 1305 | 1306 | 1307 | 1308 | 1309 | 1310 | 1311 | 1312 | 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | 1321 | 1322 | 1323 | 1324 | 1325 | 1326 | 1327 | 1328 | 1329 | 1330 | 1331 | 1332 | 1333 | 1334 | 1335 | 1336 | 1337 | 1338 | 1339 | 1340 | 1341 | 1342 | 1343 | 1344 | 1345 | 1346 | 1347 | 1348 | 1349 | 1350 | 1351 | 1352 | 1353 | 1354 | 1355 | 1356 | 1357 | 1358 | 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 1367 | 1368 | 1369 | 1370 | 1371 | 1372 | 1373 | 1374 | 1375 | 1376 | 1377 | 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 1384 | 1385 | 1386 | 1387 | 1388 | 1389 | 1390 | 1391 | 1392 | 1393 | 1394 | 1395 | 1396 | 1397 | 1398 | 1399 | 1400 | 1401 | 1402 | 1403 | 1404 | 1405 | 1406 | 1407 | 1408 | 1409 | 1410 | 1411 | 1412 | 1413 | 1414 | 1415 | 1416 | 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 1427 | 1428 | 1429 | 1430 | 1431 | 1432 | 1433 | 1434 | 1435 | 1436 | 1437 | 1438 | 1439 | 1440 | 1441 | 1442 | 1443 | 1444 | 1445 | 1446 | 1447 | 1448 | 1449 | 1450 | 1451 | 1452 | 1453 | 1454 | 1455 | 1456 | 1457 | 1458 | 1459 | 1460 | 1461 | 1462 | 1463 | 1464 | 1465 | 1466 | 1467 | 1468 | 1469 | 1470 | 1471 | 1472 | 1473 | 1474 | 1475 | 1476 | 1477 | 1478 | 1479 | 1480 | 1481 | 1482 | 1483 | 1484 | 1485 | 1486 | 1487 | 1488 | 1489 | 1490 | 1491 | 1492 | 1493 | 1494 | 1495 | 1496 | 1497 | 1498 | 1499 | 1500 | 1501 | 1502 | 1503 | 1504 | 1505 | 1506 | 1507 | 1508 | 1509 | 1510 | 1511 | 1512 | 1513 | -------------------------------------------------------------------------------- /whitespace.c: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file whitespace.c 3 | * @brief An interpreter and C-translator of Whitespace 4 | * @author koturn 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #if defined(_MSC_VER) && defined(_DEBUG) 13 | # include 14 | #endif 15 | 16 | #ifndef MAX_SOURCE_SIZE 17 | # define MAX_SOURCE_SIZE 65536 18 | #endif 19 | #ifndef MAX_BYTECODE_SIZE 20 | # define MAX_BYTECODE_SIZE 1048576 21 | #endif 22 | #ifndef MAX_LABEL_LENGTH 23 | # define MAX_LABEL_LENGTH 65536 24 | #endif 25 | #ifndef MAX_N_LABEL 26 | # define MAX_N_LABEL 1024 27 | #endif 28 | #ifndef UNDEF_LIST_SIZE 29 | # define UNDEF_LIST_SIZE 256 30 | #endif 31 | #ifndef STACK_SIZE 32 | # define STACK_SIZE 65536 33 | #endif 34 | #ifndef HEAP_SIZE 35 | # define HEAP_SIZE 65536 36 | #endif 37 | #ifndef CALL_STACK_SIZE 38 | # define CALL_STACK_SIZE 65536 39 | #endif 40 | #ifndef WS_INT 41 | # define WS_INT int 42 | #endif 43 | #ifndef WS_ADDR_INT 44 | # define WS_ADDR_INT unsigned int 45 | #endif 46 | #ifndef INDENT_STR 47 | # define INDENT_STR " " 48 | #endif 49 | 50 | #define TRUE 1 51 | #define FALSE 0 52 | #define UNDEF_ADDR ((WsAddrInt) -1) 53 | #define LENGTHOF(array) (sizeof(array) / sizeof((array)[0])) 54 | #define ADDR_DIFF(a, b) \ 55 | ((const unsigned char *) (a) - (const unsigned char *) (b)) 56 | #define SWAP(type, a, b) \ 57 | do { \ 58 | type __tmp_swap_var__ = *(a); \ 59 | *(a) = *(b); \ 60 | *(b) = __tmp_swap_var__; \ 61 | } while (0) 62 | 63 | 64 | enum OpCode { 65 | FLOW_HALT = 0x00, 66 | STACK_PUSH, STACK_DUP_N, STACK_DUP, STACK_SLIDE, STACK_SWAP, STACK_DISCARD, 67 | ARITH_ADD, ARITH_SUB, ARITH_MUL, ARITH_DIV, ARITH_MOD, 68 | HEAP_STORE, HEAP_LOAD, 69 | FLOW_LABEL, FLOW_GOSUB, FLOW_JUMP, FLOW_BEZ, FLOW_BLTZ, FLOW_ENDSUB, 70 | IO_PUT_CHAR, IO_PUT_NUM, IO_READ_CHAR, IO_READ_NUM 71 | }; 72 | 73 | 74 | typedef WS_INT WsInt; 75 | typedef WS_ADDR_INT WsAddrInt; 76 | 77 | typedef struct { 78 | const char *in_filename; 79 | const char *out_filename; 80 | int mode; 81 | } Param; 82 | 83 | typedef struct { 84 | WsAddrInt addr; 85 | int n_undef; 86 | char *label; 87 | WsAddrInt *undef_list; 88 | } LabelInfo; 89 | 90 | 91 | static void 92 | parse_arguments(Param *param, int argc, char *argv[]); 93 | 94 | static void 95 | show_usage(const char *progname); 96 | 97 | static int 98 | read_file(FILE *fp, char *code, size_t length); 99 | 100 | 101 | static void 102 | execute(const unsigned char *bytecode); 103 | 104 | static void 105 | compile(unsigned char *bytecode, size_t *bytecode_size, const char *code); 106 | 107 | static void 108 | gen_stack_code(unsigned char **bytecode_ptr, const char **code_ptr); 109 | 110 | static void 111 | gen_arith_code(unsigned char **bytecode_ptr, const char **code_ptr); 112 | 113 | static void 114 | gen_heap_code(unsigned char **bytecode_ptr, const char **code_ptr); 115 | 116 | static void 117 | gen_io_code(unsigned char **bytecode_ptr, const char **code_ptr); 118 | 119 | static void 120 | gen_flow_code(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base); 121 | 122 | 123 | static void 124 | process_label_define(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base); 125 | 126 | static void 127 | process_label_jump(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base); 128 | 129 | static LabelInfo * 130 | search_label(const char *label); 131 | 132 | static void 133 | add_label(const char *_label, WsAddrInt addr); 134 | 135 | static void 136 | add_undef_label(const char *_label, WsAddrInt pos); 137 | 138 | static void 139 | free_label_info_list(LabelInfo *label_info_list[]); 140 | 141 | 142 | static void 143 | stack_push(WsInt e); 144 | 145 | static WsInt 146 | stack_pop(void); 147 | 148 | static void 149 | stack_dup_n(size_t n); 150 | 151 | static void 152 | stack_slide(size_t n); 153 | 154 | static void 155 | stack_swap(void); 156 | 157 | 158 | static int 159 | read_nstr(const char **code_ptr); 160 | 161 | static char * 162 | read_label(const char **code_ptr); 163 | 164 | 165 | static int 166 | translate(FILE *fp, const char *code); 167 | 168 | static void 169 | print_stack_code(FILE *fp, const char **code_ptr); 170 | 171 | static void 172 | print_arith_code(FILE *fp, const char **code_ptr); 173 | 174 | static void 175 | print_heap_code(FILE *fp, const char **code_ptr); 176 | 177 | static void 178 | print_io_code(FILE *fp, const char **code_ptr); 179 | 180 | static void 181 | print_flow_code(FILE *fp, const char **code_ptr); 182 | 183 | static void 184 | print_code_header(FILE *fp); 185 | 186 | static void 187 | print_code_footer(FILE *fp); 188 | 189 | 190 | static void 191 | show_bytecode(const unsigned char *bytecode, size_t bytecode_size); 192 | 193 | static void 194 | show_mnemonic(FILE *fp, const unsigned char *bytecode, size_t bytecode_size); 195 | 196 | static void 197 | filter(FILE *fp, const char *code); 198 | 199 | 200 | static WsInt stack[STACK_SIZE] = {0}; 201 | static size_t stack_idx = 0; 202 | 203 | static LabelInfo *label_info_list[MAX_N_LABEL] = {NULL}; 204 | static size_t n_label_info = 0; 205 | 206 | 207 | 208 | 209 | /*! 210 | * @brief Entry point of thie program 211 | * @param [in] argc The number of argument (include this program name) 212 | * @param [in] argv The array off argument strings 213 | * @return Status-code 214 | */ 215 | int 216 | main(int argc, char *argv[]) 217 | { 218 | static char code[MAX_SOURCE_SIZE] = {0}; 219 | static unsigned char bytecode[MAX_BYTECODE_SIZE] = {0}; 220 | Param param = {NULL, NULL, '*'}; 221 | FILE *ifp, *ofp; 222 | size_t bytecode_size; 223 | 224 | parse_arguments(¶m, argc, argv); 225 | if (param.in_filename == NULL) { 226 | fprintf(stderr, "Invalid arguments\n"); 227 | return EXIT_FAILURE; 228 | } 229 | if (!strcmp(param.in_filename, "-")) { 230 | ifp = stdin; 231 | } else if ((ifp = fopen(param.in_filename, "r")) == NULL) { 232 | fprintf(stderr, "Unable to open file: %s\n", argv[1]); 233 | return EXIT_FAILURE; 234 | } 235 | if (!read_file(ifp, code, LENGTHOF(code))) { 236 | return EXIT_FAILURE; 237 | } 238 | if (ifp != stdin) { 239 | fclose(ifp); 240 | } 241 | 242 | switch (param.mode) { 243 | case 'b': 244 | compile(bytecode, &bytecode_size, code); 245 | show_bytecode(bytecode, bytecode_size); 246 | break; 247 | case 'f': 248 | if (param.out_filename == NULL) { 249 | filter(stdout, code); 250 | } else { 251 | if ((ofp = fopen(param.out_filename, "w")) == NULL) { 252 | fprintf(stderr, "Unable to open file: %s\n", param.out_filename); 253 | return EXIT_FAILURE; 254 | } 255 | filter(ofp, code); 256 | fclose(ofp); 257 | } 258 | break; 259 | case 'm': 260 | compile(bytecode, &bytecode_size, code); 261 | show_mnemonic(stdout, bytecode, bytecode_size); 262 | break; 263 | case 't': 264 | if (param.out_filename == NULL) { 265 | translate(stdout, code); 266 | } else { 267 | if ((ofp = fopen(param.out_filename, "w")) == NULL) { 268 | fprintf(stderr, "Unable to open file: %s\n", param.out_filename); 269 | return EXIT_FAILURE; 270 | } 271 | translate(ofp, code); 272 | fclose(ofp); 273 | } 274 | break; 275 | default: 276 | compile(bytecode, &bytecode_size, code); 277 | execute(bytecode); 278 | break; 279 | } 280 | return EXIT_SUCCESS; 281 | } 282 | 283 | 284 | /*! 285 | * @brief Parse comamnd-line arguments and set parameters. 286 | * 287 | * 'argv' is sorted after called getopt_long(). 288 | * @param [out] param Parameters of this program 289 | * @param [in] argc A number of command-line arguments 290 | * @param [in,out] argv Coomand-line arguments 291 | */ 292 | static void 293 | parse_arguments(Param *param, int argc, char *argv[]) 294 | { 295 | static const struct option opts[] = { 296 | {"bytecode", no_argument, NULL, 'b'}, 297 | {"filter", no_argument, NULL, 'f'}, 298 | {"help", no_argument, NULL, 'h'}, 299 | {"mnemonic", no_argument, NULL, 'm'}, 300 | {"output", required_argument, NULL, 'o'}, 301 | {"translate", no_argument, NULL, 't'}, 302 | {0, 0, 0, 0} /* must be filled with zero */ 303 | }; 304 | int ret; 305 | int optidx = 0; 306 | while ((ret = getopt_long(argc, argv, "bfhmo:t", opts, &optidx)) != -1) { 307 | switch (ret) { 308 | case 'b': /* -b, --bytecode */ 309 | case 'f': /* -f, --filter */ 310 | case 'm': /* -n or --nocompile */ 311 | case 't': /* -t or --translate */ 312 | param->mode = ret; 313 | break; 314 | case 'h': /* -h, --help */ 315 | show_usage(argv[0]); 316 | exit(EXIT_SUCCESS); 317 | case 'o': /* -o or --output */ 318 | param->out_filename = optarg; 319 | break; 320 | case '?': /* unknown option */ 321 | show_usage(argv[0]); 322 | exit(EXIT_FAILURE); 323 | } 324 | } 325 | if (optind != argc - 1) { 326 | fputs("Please specify one whitespace source code\n", stderr); 327 | show_usage(argv[0]); 328 | exit(EXIT_FAILURE); 329 | } 330 | param->in_filename = argv[optind]; 331 | } 332 | 333 | 334 | /*! 335 | * @brief Show usage of this program and exit 336 | * @param [in] progname A name of this program 337 | */ 338 | static void 339 | show_usage(const char *progname) 340 | { 341 | printf( 342 | "[Usage]\n" 343 | " $ %s FILE [options]\n" 344 | "[Options]\n" 345 | " -b, --bytecode\n" 346 | " Show code in hexadecimal\n" 347 | " -f, --filter\n" 348 | " Visualize whitespace source code\n" 349 | " -h, --help\n" 350 | " Show help and exit\n" 351 | " -m, --mnemonic\n" 352 | " Show byte code in mnemonic format\n" 353 | " -o FILE, --output=FILE\n" 354 | " Specify output filename\n" 355 | " -t, --translate\n" 356 | " Translate brainfuck to C source code\n", progname); 357 | } 358 | 359 | 360 | 361 | 362 | /* ------------------------------------------------------------------------- * 363 | * Interpretor * 364 | * ------------------------------------------------------------------------- */ 365 | /*! 366 | * @brief Execute whitespace 367 | * @param [in] bytecode Bytecode of whitespace 368 | */ 369 | static void 370 | execute(const unsigned char *bytecode) 371 | { 372 | static int heap[HEAP_SIZE] = {0}; 373 | static size_t call_stack[CALL_STACK_SIZE] = {0}; 374 | size_t call_stack_idx = 0; 375 | const unsigned char *base = bytecode; 376 | int a = 0, b = 0; 377 | for (; *bytecode; bytecode++) { 378 | switch (*bytecode) { 379 | case STACK_PUSH: 380 | bytecode++; 381 | stack_push(*((const WsInt *) bytecode)); 382 | bytecode += sizeof(WsInt) - 1; 383 | break; 384 | case STACK_DUP_N: 385 | bytecode++; 386 | stack_dup_n((size_t) *((const WsInt *) bytecode)); 387 | bytecode += sizeof(WsInt) - 1; 388 | break; 389 | case STACK_DUP: 390 | stack_dup_n(0); 391 | break; 392 | case STACK_SLIDE: 393 | bytecode++; 394 | stack_slide((size_t) *((const WsInt *) bytecode)); 395 | bytecode += sizeof(WsInt) - 1; 396 | break; 397 | case STACK_SWAP: 398 | stack_swap(); 399 | break; 400 | case STACK_DISCARD: 401 | stack_pop(); 402 | break; 403 | case ARITH_ADD: 404 | a = stack_pop(); 405 | b = stack_pop(); 406 | stack_push(b + a); 407 | break; 408 | case ARITH_SUB: 409 | a = stack_pop(); 410 | b = stack_pop(); 411 | stack_push(b - a); 412 | break; 413 | case ARITH_MUL: 414 | a = stack_pop(); 415 | b = stack_pop(); 416 | stack_push(b * a); 417 | break; 418 | case ARITH_DIV: 419 | a = stack_pop(); 420 | b = stack_pop(); 421 | assert(b != 0); 422 | stack_push(b / a); 423 | break; 424 | case ARITH_MOD: 425 | a = stack_pop(); 426 | b = stack_pop(); 427 | assert(b != 0); 428 | stack_push(b % a); 429 | break; 430 | case HEAP_STORE: 431 | a = stack_pop(); 432 | b = stack_pop(); 433 | assert(0 <= b && b < (int) LENGTHOF(heap)); 434 | heap[b] = a; 435 | break; 436 | case HEAP_LOAD: 437 | a = stack_pop(); 438 | assert(0 <= a && a < (int) LENGTHOF(heap)); 439 | stack_push(heap[a]); 440 | break; 441 | case FLOW_GOSUB: 442 | call_stack[call_stack_idx++] = (size_t) (ADDR_DIFF(bytecode, base)) + sizeof(WsAddrInt); 443 | bytecode++; 444 | bytecode = &base[*((const WsAddrInt *) bytecode)] - 1; 445 | break; 446 | case FLOW_JUMP: 447 | bytecode++; 448 | bytecode = &base[*((const WsAddrInt *) bytecode)] - 1; 449 | break; 450 | case FLOW_BEZ: 451 | if (!stack_pop()) { 452 | bytecode++; 453 | bytecode = &base[*((const WsAddrInt *) bytecode)] - 1; 454 | } else { 455 | bytecode += sizeof(WsAddrInt); 456 | } 457 | break; 458 | case FLOW_BLTZ: 459 | if (stack_pop() < 0) { 460 | bytecode++; 461 | bytecode = &base[*((const WsAddrInt *) bytecode)] - 1; 462 | } else { 463 | bytecode += sizeof(WsAddrInt); 464 | } 465 | break; 466 | case FLOW_ENDSUB: 467 | bytecode = &base[call_stack[--call_stack_idx]]; 468 | break; 469 | case IO_PUT_CHAR: 470 | putchar(stack_pop()); 471 | break; 472 | case IO_PUT_NUM: 473 | printf("%d", stack_pop()); 474 | break; 475 | case IO_READ_CHAR: 476 | a = stack_pop(); 477 | assert(0 <= a && a < (int) LENGTHOF(heap)); 478 | fflush(stdout); 479 | heap[a] = getchar(); 480 | break; 481 | case IO_READ_NUM: 482 | a = stack_pop(); 483 | assert(0 <= a && a < (int) LENGTHOF(heap)); 484 | fflush(stdout); 485 | scanf("%d", &heap[a]); 486 | break; 487 | case FLOW_HALT: 488 | printf("HALT\n"); 489 | break; 490 | default: 491 | fprintf(stderr, "Undefined instruction is detected [%02x]\n", *bytecode); 492 | } 493 | } 494 | } 495 | 496 | 497 | /*! 498 | * @brief Compile whitespace source code into bytecode 499 | * @param [out] bytecode Bytecode buffer 500 | * @param [in] code Brainfuck source code 501 | */ 502 | static void 503 | compile(unsigned char *bytecode, size_t *bytecode_size, const char *code) 504 | { 505 | unsigned char *base = bytecode; 506 | for (; *code != '\0'; code++) { 507 | switch (*code) { 508 | case ' ': /* Stack Manipulation */ 509 | gen_stack_code(&bytecode, &code); 510 | break; 511 | case '\t': /* Arithmetic, Heap Access or I/O */ 512 | switch (*++code) { 513 | case ' ': /* Arithmetic */ 514 | gen_arith_code(&bytecode, &code); 515 | break; 516 | case '\t': /* Heap Access */ 517 | gen_heap_code(&bytecode, &code); 518 | break; 519 | case '\n': /* I/O */ 520 | gen_io_code(&bytecode, &code); 521 | break; 522 | } 523 | break; 524 | case '\n': /* Flow Control */ 525 | gen_flow_code(&bytecode, &code, base); 526 | break; 527 | } 528 | } 529 | *bytecode_size = (size_t) ADDR_DIFF(bytecode, base); 530 | free_label_info_list(label_info_list); 531 | } 532 | 533 | 534 | /*! 535 | * @brief Generate bytecode about stack manipulation 536 | * @param [out] bytecode_ptr Pointer to bytecode buffer 537 | * @param [in,out] code_ptr pointer to whitespace source code 538 | */ 539 | static void 540 | gen_stack_code(unsigned char **bytecode_ptr, const char **code_ptr) 541 | { 542 | unsigned char *bytecode = *bytecode_ptr; 543 | const char *code = *code_ptr; 544 | switch (*++code) { 545 | case ' ': 546 | *bytecode++ = STACK_PUSH; 547 | *((WsInt *) bytecode) = read_nstr(&code); 548 | bytecode += sizeof(WsInt); 549 | break; 550 | case '\t': 551 | switch (*++code) { 552 | case ' ': 553 | *bytecode++ = STACK_DUP_N; 554 | *((WsInt *) bytecode) = read_nstr(&code); 555 | bytecode += sizeof(WsInt); 556 | break; 557 | case '\t': 558 | fputs("Undefined Stack manipulation command is detected: [S][TT]\n", stderr); 559 | break; 560 | case '\n': 561 | *bytecode++ = STACK_SLIDE; 562 | *((WsInt *) bytecode) = read_nstr(&code); 563 | bytecode += sizeof(WsInt); 564 | break; 565 | } 566 | break; 567 | case '\n': 568 | switch (*++code) { 569 | case ' ': 570 | *bytecode++ = STACK_DUP_N; 571 | *((WsInt *) bytecode) = 0; 572 | bytecode += sizeof(WsInt); 573 | break; 574 | case '\t': 575 | *bytecode++ = STACK_SWAP; 576 | break; 577 | case '\n': 578 | *bytecode++ = STACK_DISCARD; 579 | break; 580 | } 581 | break; 582 | } 583 | *bytecode_ptr = bytecode; 584 | *code_ptr = code; 585 | } 586 | 587 | 588 | /*! 589 | * @brief Generate bytecode about arithmetic 590 | * @param [out] bytecode_ptr Pointer to bytecode buffer 591 | * @param [in,out] code_ptr pointer to whitespace source code 592 | */ 593 | static void 594 | gen_arith_code(unsigned char **bytecode_ptr, const char **code_ptr) 595 | { 596 | unsigned char *bytecode = *bytecode_ptr; 597 | const char *code = *code_ptr; 598 | switch (*++code) { 599 | case ' ': 600 | switch (*++code) { 601 | case ' ': 602 | *bytecode++ = ARITH_ADD; 603 | break; 604 | case '\t': 605 | *bytecode++ = ARITH_SUB; 606 | break; 607 | case '\n': 608 | *bytecode++ = ARITH_MUL; 609 | break; 610 | } 611 | break; 612 | case '\t': 613 | switch (*++code) { 614 | case ' ': 615 | *bytecode++ = ARITH_DIV; 616 | break; 617 | case '\t': 618 | *bytecode++ = ARITH_MOD; 619 | break; 620 | case '\n': 621 | fputs("Undefined arithmetic command is detected: [TS][TN]\n", stderr); 622 | break; 623 | } 624 | break; 625 | case '\n': 626 | fputs("Undefined arithmetic command is detected: [TS][N]\n", stderr); 627 | break; 628 | } 629 | *bytecode_ptr = bytecode; 630 | *code_ptr = code; 631 | } 632 | 633 | 634 | /*! 635 | * @brief Generate bytecode about heap access 636 | * @param [out] bytecode_ptr Pointer to bytecode buffer 637 | * @param [in,out] code_ptr pointer to whitespace source code 638 | */ 639 | static void 640 | gen_heap_code(unsigned char **bytecode_ptr, const char **code_ptr) 641 | { 642 | unsigned char *bytecode = *bytecode_ptr; 643 | const char *code = *code_ptr; 644 | switch (*++code) { 645 | case ' ': 646 | *bytecode++ = HEAP_STORE; 647 | break; 648 | case '\t': 649 | *bytecode++ = HEAP_LOAD; 650 | break; 651 | case '\n': 652 | fputs("Undefined heap access command is detected: [TT][N]\n", stderr); 653 | break; 654 | } 655 | *bytecode_ptr = bytecode; 656 | *code_ptr = code; 657 | } 658 | 659 | 660 | /*! 661 | * @brief Generate bytecode about flow control 662 | * @param [out] bytecode_ptr Pointer to bytecode buffer 663 | * @param [in,out] code_ptr pointer to whitespace source code 664 | * @param [in] base Base address of the bytecode buffer 665 | */ 666 | static void 667 | gen_flow_code(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base) 668 | { 669 | unsigned char *bytecode = *bytecode_ptr; 670 | const char *code = *code_ptr; 671 | switch (*++code) { 672 | case ' ': 673 | switch (*++code) { 674 | case ' ': 675 | process_label_define(&bytecode, &code, base); 676 | break; 677 | case '\t': 678 | *bytecode++ = FLOW_GOSUB; 679 | process_label_jump(&bytecode, &code, base); 680 | break; 681 | case '\n': 682 | *bytecode++ = FLOW_JUMP; 683 | process_label_jump(&bytecode, &code, base); 684 | break; 685 | } 686 | break; 687 | case '\t': 688 | switch (*++code) { 689 | case ' ': 690 | *bytecode++ = FLOW_BEZ; 691 | process_label_jump(&bytecode, &code, base); 692 | break; 693 | case '\t': 694 | *bytecode++ = FLOW_BLTZ; 695 | process_label_jump(&bytecode, &code, base); 696 | break; 697 | case '\n': 698 | *bytecode++ = FLOW_ENDSUB; 699 | break; 700 | } 701 | break; 702 | case '\n': 703 | if (*++code == '\n') { 704 | *bytecode++ = FLOW_HALT; 705 | } else { 706 | fputs("Undefined flow control command is detected: [N][S/T]\n", stderr); 707 | } 708 | break; 709 | } 710 | *bytecode_ptr = bytecode; 711 | *code_ptr = code; 712 | } 713 | 714 | 715 | /*! 716 | * @brief Generate bytecode about I/O 717 | * @param [out] bytecode_ptr Pointer to bytecode buffer 718 | * @param [in,out] code_ptr pointer to whitespace source code 719 | */ 720 | static void 721 | gen_io_code(unsigned char **bytecode_ptr, const char **code_ptr) 722 | { 723 | unsigned char *bytecode = *bytecode_ptr; 724 | const char *code = *code_ptr; 725 | switch (*++code) { 726 | case ' ': 727 | switch (*++code) { 728 | case ' ': 729 | *bytecode++ = IO_PUT_CHAR; 730 | break; 731 | case '\t': 732 | *bytecode++ = IO_PUT_NUM; 733 | break; 734 | case '\n': 735 | fputs("Undefined I/O command is detected: [TN][SN]\n", stderr); 736 | break; 737 | } 738 | break; 739 | case '\t': 740 | switch (*++code) { 741 | case ' ': 742 | *bytecode++ = IO_READ_CHAR; 743 | break; 744 | case '\t': 745 | *bytecode++ = IO_READ_NUM; 746 | break; 747 | case '\n': 748 | fputs("Undefined I/O command is detected: [TN][TN]\n", stderr); 749 | break; 750 | } 751 | break; 752 | case '\n': 753 | fputs("Undefined I/O command is detected: [TN][N]\n", stderr); 754 | break; 755 | } 756 | *bytecode_ptr = bytecode; 757 | *code_ptr = code; 758 | } 759 | 760 | 761 | /*! 762 | * @brief Check given label is already defined or not 763 | * 764 | * If label is already defined, return the label information 765 | * @param [in] label Label you want to check 766 | * @return Label information 767 | */ 768 | static LabelInfo * 769 | search_label(const char *label) 770 | { 771 | size_t i; 772 | for (i = 0; i < n_label_info; i++) { 773 | if (!strcmp(label, label_info_list[i]->label)) { 774 | return label_info_list[i]; 775 | } 776 | } 777 | return NULL; 778 | } 779 | 780 | 781 | /*! 782 | * @brief Write where to jump to the bytecode 783 | * @param [out] bytecode_ptr Pointer to bytecode buffer 784 | * @param [in,out] code_ptr pointer to whitespace source code 785 | * @param [in] base Base address of the bytecode buffer 786 | */ 787 | static void 788 | process_label_define(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base) 789 | { 790 | const char *code = *code_ptr; 791 | unsigned char *bytecode = *bytecode_ptr; 792 | char *label = read_label(&code); 793 | LabelInfo *label_info = search_label(label); 794 | 795 | if (label_info == NULL) { 796 | add_label(label, (WsAddrInt) ADDR_DIFF(bytecode, base)); 797 | } else { 798 | if (label_info->addr == UNDEF_ADDR) { 799 | int i; 800 | for (i = 0; i < label_info->n_undef; i++) { 801 | *((WsAddrInt *) &base[label_info->undef_list[i]]) = (WsAddrInt) ADDR_DIFF(bytecode, base); 802 | } 803 | label_info->addr = (WsAddrInt) ADDR_DIFF(bytecode, base); 804 | free(label_info->undef_list); 805 | label_info->undef_list = NULL; 806 | } else { 807 | fputs("Duplicate label definition\n", stderr); 808 | } 809 | } 810 | *code_ptr = code; 811 | *bytecode_ptr = bytecode; 812 | } 813 | 814 | 815 | /*! 816 | * @brief Write where to jump to the bytecode 817 | * 818 | * If label is not defined yet, write it after label is defined. 819 | * @param [out] bytecode_ptr Pointer to bytecode buffer 820 | * @param [in,out] code_ptr pointer to whitespace source code 821 | * @param [in] base Base address of the bytecode buffer 822 | */ 823 | static void 824 | process_label_jump(unsigned char **bytecode_ptr, const char **code_ptr, unsigned char *base) 825 | { 826 | const char *code = *code_ptr; 827 | unsigned char *bytecode = *bytecode_ptr; 828 | char *label = read_label(&code); 829 | LabelInfo *label_info = search_label(label); 830 | 831 | if (label_info == NULL) { 832 | add_undef_label(label, (WsAddrInt) ADDR_DIFF(bytecode, base)); 833 | } else if (label_info->addr == UNDEF_ADDR) { 834 | label_info->undef_list[label_info->n_undef++] = (WsAddrInt) ADDR_DIFF(bytecode, base); 835 | } else { 836 | *((WsAddrInt *) bytecode) = label_info->addr; 837 | } 838 | bytecode += sizeof(WsAddrInt); 839 | *code_ptr = code; 840 | *bytecode_ptr = bytecode; 841 | } 842 | 843 | 844 | /*! 845 | * @brief Add label information to the label list 846 | * @param [in] _label Label name 847 | * @param [in] addr Label position 848 | */ 849 | static void 850 | add_label(const char *_label, WsAddrInt addr) 851 | { 852 | char *label = (char *) calloc(strlen(_label) + 1, sizeof(char)); 853 | LabelInfo *label_info = (LabelInfo *) calloc(1, sizeof(LabelInfo)); 854 | 855 | if (label == NULL || label_info == NULL) { 856 | fprintf(stderr, "Failed to allocate heap for label\n"); 857 | exit(EXIT_FAILURE); 858 | } 859 | strcpy(label, _label); 860 | 861 | free(label_info->undef_list); 862 | label_info->undef_list = NULL; 863 | label_info->label = label; 864 | label_info->addr = addr; 865 | label_info->n_undef = 0; 866 | label_info_list[n_label_info++] = label_info; 867 | } 868 | 869 | 870 | /*! 871 | * @brief Add unseen/undefined label to the label list 872 | * @param [in] _label Label name 873 | * @param [in] pos The position given label was found 874 | */ 875 | static void 876 | add_undef_label(const char *_label, WsAddrInt pos) 877 | { 878 | char *label = (char *) calloc(strlen(_label) + 1, sizeof(char)); 879 | LabelInfo *label_info = (LabelInfo *) calloc(1, sizeof(LabelInfo)); 880 | label_info->undef_list = (WsAddrInt *) calloc(UNDEF_LIST_SIZE, sizeof(WsAddrInt)); 881 | 882 | if (label == NULL || label_info == NULL || label_info->undef_list == NULL) { 883 | fprintf(stderr, "Failed to allocate heap for label\n"); 884 | exit(EXIT_FAILURE); 885 | } 886 | strcpy(label, _label); 887 | 888 | label_info->undef_list[0] = pos; 889 | label_info->label = label; 890 | label_info->addr = UNDEF_ADDR; 891 | label_info->n_undef = 1; 892 | label_info_list[n_label_info++] = label_info; 893 | } 894 | 895 | 896 | /*! 897 | * @brief Free label informations 898 | * @param [in] label_info_list Label list 899 | */ 900 | static void 901 | free_label_info_list(LabelInfo *label_info_list[]) 902 | { 903 | size_t i = 0; 904 | for (i = 0; i < n_label_info; i++) { 905 | free(label_info_list[i]->label); 906 | free(label_info_list[i]->undef_list); 907 | free(label_info_list[i]); 908 | } 909 | } 910 | 911 | 912 | 913 | 914 | /* ------------------------------------------------------------------------- * 915 | * Stack Manipulation (IMP: [Space]) * 916 | * ------------------------------------------------------------------------- */ 917 | /*! 918 | * @brief Push given number onto the stack 919 | * @param [in] e A number you want to push onto the stack 920 | */ 921 | static void 922 | stack_push(WsInt e) 923 | { 924 | assert(stack_idx < LENGTHOF(stack)); 925 | stack[stack_idx++] = e; 926 | } 927 | 928 | 929 | /*! 930 | * @brief Pop out one element from the top of the stack 931 | * @return An element of the top of the stack 932 | */ 933 | static WsInt 934 | stack_pop(void) 935 | { 936 | assert(stack_idx > 0); 937 | return stack[--stack_idx]; 938 | } 939 | 940 | 941 | /*! 942 | * @brief Copy the nth item on the stack onto the top of the stack 943 | */ 944 | static void 945 | stack_dup_n(size_t n) 946 | { 947 | assert(n < stack_idx && stack_idx < LENGTHOF(stack) - 1); 948 | stack[stack_idx] = stack[stack_idx - (n + 1)]; 949 | stack_idx++; 950 | } 951 | 952 | 953 | /*! 954 | * @brief Slide n items off the stack, keeping the top item 955 | * @param [in] n The number of items you want to slide off the stack 956 | */ 957 | static void 958 | stack_slide(size_t n) 959 | { 960 | assert(stack_idx > n); 961 | stack[stack_idx - (n + 1)] = stack[stack_idx - 1]; 962 | stack_idx -= n; 963 | } 964 | 965 | 966 | /*! 967 | * @brief Swap the top two items on the stack 968 | */ 969 | static void 970 | stack_swap(void) 971 | { 972 | assert(stack_idx > 1); 973 | SWAP(int, &stack[stack_idx - 1], &stack[stack_idx - 2]); 974 | } 975 | 976 | 977 | /*! 978 | * @brief Read whitespace-source code characters and push into given array. 979 | * @param [in,out] fp File pointer to the whitespace source code 980 | * @param [out] code The array you want to store the source code 981 | * @param [in] length Max size of given array of code 982 | * @return Status-code 983 | */ 984 | static int 985 | read_file(FILE *fp, char *code, size_t length) 986 | { 987 | int ch; 988 | size_t cnt = 0; 989 | for (; (ch = fgetc(fp)) != EOF; cnt++) { 990 | if (cnt > length) { 991 | fprintf(stderr, "Buffer overflow!\n"); 992 | return FALSE; 993 | } 994 | switch (ch) { 995 | case ' ': 996 | case '\n': 997 | case '\t': 998 | *code++ = (char) ch; 999 | break; 1000 | } 1001 | } 1002 | return TRUE; 1003 | } 1004 | 1005 | 1006 | 1007 | 1008 | /* ------------------------------------------------------------------------- * 1009 | * Whitespace translator * 1010 | * ------------------------------------------------------------------------- */ 1011 | /*! 1012 | * @brief Translate whitespace source code into C source code 1013 | * @param [in,out] fp output file pointer 1014 | * @param [in] code Pointer to Whitespace source code buffer 1015 | * @return Status-code 1016 | */ 1017 | static int 1018 | translate(FILE *fp, const char *code) 1019 | { 1020 | print_code_header(fp); 1021 | for (; *code != '\0'; code++) { 1022 | switch (*code) { 1023 | case ' ': /* Stack Manipulation */ 1024 | print_stack_code(fp, &code); 1025 | break; 1026 | case '\t': /* Arithmetic, Heap Access or I/O */ 1027 | switch (*++code) { 1028 | case ' ': /* Arithmetic */ 1029 | print_arith_code(fp, &code); 1030 | break; 1031 | case '\t': /* Heap Access */ 1032 | print_heap_code(fp, &code); 1033 | break; 1034 | case '\n': /* I/O */ 1035 | print_io_code(fp, &code); 1036 | break; 1037 | } 1038 | break; 1039 | case '\n': /* Flow Control */ 1040 | print_flow_code(fp, &code); 1041 | break; 1042 | } 1043 | } 1044 | print_code_footer(fp); 1045 | return TRUE; 1046 | } 1047 | 1048 | 1049 | /*! 1050 | * @brief Print C source code about stack manipulation 1051 | * @param [in,out] fp output file pointer 1052 | * @param [in] code Pointer to Whitespace source code pointer 1053 | */ 1054 | static void 1055 | print_stack_code(FILE *fp, const char **code_ptr) 1056 | { 1057 | const char *code = *code_ptr; 1058 | switch (*++code) { 1059 | case ' ': 1060 | fprintf(fp, INDENT_STR "push(%d);\n", read_nstr(&code)); 1061 | break; 1062 | case '\t': 1063 | switch (*++code) { 1064 | case ' ': 1065 | fprintf(fp, INDENT_STR "dup_n(%d);\n", read_nstr(&code)); 1066 | break; 1067 | case '\t': 1068 | fputs("Undefined Stack manipulation command is detected: [S][TT]\n", stderr); 1069 | break; 1070 | case '\n': 1071 | fprintf(fp, INDENT_STR "slide(%d);\n", read_nstr(&code)); 1072 | break; 1073 | } 1074 | break; 1075 | case '\n': 1076 | switch (*++code) { 1077 | case ' ': 1078 | fputs(INDENT_STR "dup_n(0);\n", fp); 1079 | break; 1080 | case '\t': 1081 | fputs(INDENT_STR "swap();\n", fp); 1082 | break; 1083 | case '\n': 1084 | fputs(INDENT_STR "pop();\n", fp); 1085 | break; 1086 | } 1087 | break; 1088 | } 1089 | *code_ptr = code; 1090 | } 1091 | 1092 | 1093 | /*! 1094 | * @brief Print C source code about arithmetic 1095 | * @param [in,out] fp output file pointer 1096 | * @param [in] code Pointer to Whitespace source code pointer 1097 | */ 1098 | static void 1099 | print_arith_code(FILE *fp, const char **code_ptr) 1100 | { 1101 | const char *code = *code_ptr; 1102 | switch (*++code) { 1103 | case ' ': 1104 | switch (*++code) { 1105 | case ' ': 1106 | fputs(INDENT_STR "arith_add();\n", fp); 1107 | break; 1108 | case '\t': 1109 | fputs(INDENT_STR "arith_sub();\n", fp); 1110 | break; 1111 | case '\n': 1112 | fputs(INDENT_STR "arith_mul();\n", fp); 1113 | break; 1114 | } 1115 | break; 1116 | case '\t': 1117 | switch (*++code) { 1118 | case ' ': 1119 | fputs(INDENT_STR "arith_div();\n", fp); 1120 | break; 1121 | case '\t': 1122 | fputs(INDENT_STR "arith_mod();\n", fp); 1123 | break; 1124 | case '\n': 1125 | fputs("Undefined arithmetic command is detected: [TS][TN]\n", stderr); 1126 | break; 1127 | } 1128 | break; 1129 | case '\n': 1130 | fputs("Undefined arithmetic command is detected: [TS][N]\n", stderr); 1131 | break; 1132 | } 1133 | *code_ptr = code; 1134 | } 1135 | 1136 | 1137 | /*! 1138 | * @brief Print C source code about heap access 1139 | * @param [in,out] fp output file pointer 1140 | * @param [in] code Pointer to Whitespace source code pointer 1141 | */ 1142 | static void 1143 | print_heap_code(FILE *fp, const char **code_ptr) 1144 | { 1145 | const char *code = *code_ptr; 1146 | switch (*++code) { 1147 | case ' ': 1148 | fputs(INDENT_STR "heap_store();\n", fp); 1149 | break; 1150 | case '\t': 1151 | fputs(INDENT_STR "heap_read();\n", fp); 1152 | break; 1153 | case '\n': 1154 | fputs("Undefined heap access command is detected: [TT][N]\n", stderr); 1155 | break; 1156 | } 1157 | *code_ptr = code; 1158 | } 1159 | 1160 | 1161 | /*! 1162 | * @brief Print C source code about flow control 1163 | * @param [in,out] fp output file pointer 1164 | * @param [in] code Pointer to Whitespace source code pointer 1165 | */ 1166 | static void 1167 | print_flow_code(FILE *fp, const char **code_ptr) 1168 | { 1169 | const char *code = *code_ptr; 1170 | switch (*++code) { 1171 | case ' ': 1172 | switch (*++code) { 1173 | case ' ': 1174 | fprintf(fp, "\n%s:\n", read_label(&code)); 1175 | break; 1176 | case '\t': 1177 | fprintf(fp, 1178 | INDENT_STR "if (!setjmp(call_stack[call_stack_idx++])) {\n" 1179 | INDENT_STR INDENT_STR "goto %s;\n" 1180 | INDENT_STR "}\n", 1181 | read_label(&code)); 1182 | break; 1183 | case '\n': 1184 | fprintf(fp, INDENT_STR "goto %s;\n", read_label(&code)); 1185 | break; 1186 | } 1187 | break; 1188 | case '\t': 1189 | switch (*++code) { 1190 | case ' ': 1191 | fprintf(fp, 1192 | INDENT_STR "if (!pop()) {\n" 1193 | INDENT_STR INDENT_STR "goto %s;\n" 1194 | INDENT_STR "}\n", 1195 | read_label(&code)); 1196 | break; 1197 | case '\t': 1198 | fprintf(fp, 1199 | INDENT_STR "if (pop() < 0) {\n" 1200 | INDENT_STR INDENT_STR "goto %s;\n" 1201 | INDENT_STR "}\n", 1202 | read_label(&code)); 1203 | break; 1204 | case '\n': 1205 | fputs(INDENT_STR "longjmp(call_stack[--call_stack_idx], 1);\n", fp); 1206 | break; 1207 | } 1208 | break; 1209 | case '\n': 1210 | if (*++code == '\n') { 1211 | fputs(INDENT_STR "exit(EXIT_SUCCESS);\n", fp); 1212 | } else { 1213 | fputs("Undefined flow control command is detected: [N][S/T]\n", stderr); 1214 | } 1215 | break; 1216 | } 1217 | *code_ptr = code; 1218 | } 1219 | 1220 | 1221 | /*! 1222 | * @brief Print C source code about I/O 1223 | * @param [in,out] fp output file pointer 1224 | * @param [in] code Pointer to Whitespace source code pointer 1225 | */ 1226 | static void 1227 | print_io_code(FILE *fp, const char **code_ptr) 1228 | { 1229 | const char *code = *code_ptr; 1230 | switch (*++code) { 1231 | case ' ': 1232 | switch (*++code) { 1233 | case ' ': 1234 | fputs(INDENT_STR "putchar(pop());\n", fp); 1235 | break; 1236 | case '\t': 1237 | fputs(INDENT_STR "printf(\"%d\", pop());\n", fp); 1238 | break; 1239 | case '\n': 1240 | fputs("Undefined I/O command is detected: [TN][SN]\n", stderr); 1241 | break; 1242 | } 1243 | break; 1244 | case '\t': 1245 | switch (*++code) { 1246 | case ' ': 1247 | fputs( 1248 | INDENT_STR "fflush(stdout);\n" 1249 | INDENT_STR "heap[pop()] = getchar();\n", 1250 | fp); 1251 | break; 1252 | case '\t': 1253 | fputs( 1254 | INDENT_STR "fflush(stdout);\n" 1255 | INDENT_STR "scanf(\"%d\", &heap[pop()]);\n", 1256 | fp); 1257 | break; 1258 | case '\n': 1259 | fputs("Undefined I/O command is detected: [TN][TN]\n", stderr); 1260 | break; 1261 | } 1262 | break; 1263 | case '\n': 1264 | fputs("Undefined I/O command is detected: [TN][N]\n", stderr); 1265 | break; 1266 | } 1267 | *code_ptr = code; 1268 | } 1269 | 1270 | 1271 | /*! 1272 | * @brief Print the header of translated C-source code 1273 | * @param [in,out] fp Output file pointer 1274 | */ 1275 | static void 1276 | print_code_header(FILE *fp) 1277 | { 1278 | fputs( 1279 | "#include \n" 1280 | "#include \n" 1281 | "#include \n" 1282 | "#include \n\n", fp); 1283 | fputs( 1284 | "#ifndef __cplusplus\n" 1285 | "# if defined(_MSC_VER)\n" 1286 | "# define inline __inline\n" 1287 | "# define __inline__ __inline\n" 1288 | "# elif !defined(__GNUC__) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)\n" 1289 | "# define inline\n" 1290 | "# define __inline\n" 1291 | "# endif\n" 1292 | "#endif\n\n", fp); 1293 | fprintf(fp, 1294 | "#define STACK_SIZE %d\n" 1295 | "#define HEAP_SIZE %d\n" 1296 | "#define CALL_STACK_SIZE %d\n\n" 1297 | "#define LENGTHOF(array) (sizeof(array) / sizeof((array)[0]))\n" 1298 | "#define SWAP(type, a, b) \\\n" 1299 | INDENT_STR "do { \\\n" 1300 | INDENT_STR INDENT_STR "type __tmp_swap_var__ = *(a); \\\n" 1301 | INDENT_STR INDENT_STR "*(a) = *(b); \\\n" 1302 | INDENT_STR INDENT_STR "*(b) = __tmp_swap_var__; \\\n" 1303 | INDENT_STR "} while (0)\n\n", 1304 | STACK_SIZE, HEAP_SIZE, CALL_STACK_SIZE); 1305 | fputs( 1306 | "inline static int pop(void);\n" 1307 | "inline static void push(int e);\n" 1308 | "inline static void dup_n(size_t n);\n" 1309 | "inline static void slide(size_t n);\n" 1310 | "inline static void swap(void);\n", fp); 1311 | fputs( 1312 | "inline static void arith_add(void);\n" 1313 | "inline static void arith_sub(void);\n" 1314 | "inline static void arith_mul(void);\n" 1315 | "inline static void arith_div(void);\n" 1316 | "inline static void arith_mod(void);\n", fp); 1317 | fputs( 1318 | "inline static void heap_store(void);\n" 1319 | "inline static void heap_read(void);\n\n", fp); 1320 | fputs( 1321 | "static int stack[STACK_SIZE];\n" 1322 | "static int heap[HEAP_SIZE];\n" 1323 | "static jmp_buf call_stack[CALL_STACK_SIZE];\n" 1324 | "static size_t stack_idx = 0;\n" 1325 | "static size_t call_stack_idx = 0;\n\n\n", fp); 1326 | fputs( 1327 | "int main(void)\n" 1328 | "{\n", fp); 1329 | } 1330 | 1331 | 1332 | /*! 1333 | * @brief Print the footer of translated C-source code 1334 | * @param [in,out] fp Output file pointer 1335 | */ 1336 | static void 1337 | print_code_footer(FILE *fp) 1338 | { 1339 | fputs( 1340 | "\n" 1341 | INDENT_STR "return EXIT_SUCCESS;\n" 1342 | "}\n\n\n", fp); 1343 | fputs( 1344 | "inline static int pop(void)\n" 1345 | "{\n" 1346 | INDENT_STR "assert(stack_idx < LENGTHOF(stack));\n" 1347 | INDENT_STR "return stack[--stack_idx];\n" 1348 | "}\n\n\n", fp); 1349 | fputs( 1350 | "inline static void push(int e)\n" 1351 | "{\n" 1352 | INDENT_STR "assert(stack_idx < LENGTHOF(stack));\n" 1353 | INDENT_STR "stack[stack_idx++] = e;\n" 1354 | "}\n\n\n", fp); 1355 | fputs( 1356 | "inline static void dup_n(size_t n)\n" 1357 | "{\n" 1358 | INDENT_STR "assert(n < stack_idx && stack_idx < LENGTHOF(stack) - 1);\n" 1359 | INDENT_STR "stack[stack_idx] = stack[stack_idx - (n + 1)];\n" 1360 | INDENT_STR "stack_idx++;\n" 1361 | "}\n\n\n", fp); 1362 | fputs( 1363 | "inline static void slide(size_t n)\n" 1364 | "{\n" 1365 | INDENT_STR "assert(stack_idx > n);\n" 1366 | INDENT_STR "stack[stack_idx - (n + 1)] = stack[stack_idx - 1];\n" 1367 | INDENT_STR "stack_idx -= n;\n" 1368 | "}\n\n\n", fp); 1369 | fputs( 1370 | "inline static void swap(void)\n" 1371 | "{\n" 1372 | INDENT_STR "assert(stack_idx > 1);\n" 1373 | INDENT_STR "SWAP(int, &stack[stack_idx - 1], &stack[stack_idx - 2]);\n" 1374 | "}\n\n\n", fp); 1375 | fputs( 1376 | "inline static void arith_add(void)\n" 1377 | "{\n" 1378 | INDENT_STR "assert(stack_idx > 1);\n" 1379 | INDENT_STR "stack_idx--;\n" 1380 | INDENT_STR "stack[stack_idx - 1] += stack[stack_idx];\n" 1381 | "}\n\n\n", fp); 1382 | fputs( 1383 | "inline static void arith_sub(void)\n" 1384 | "{\n" 1385 | INDENT_STR "assert(stack_idx > 1);\n" 1386 | INDENT_STR "stack_idx--;\n" 1387 | INDENT_STR "stack[stack_idx - 1] -= stack[stack_idx];\n" 1388 | "}\n\n\n", fp); 1389 | fputs( 1390 | "inline static void arith_mul(void)\n" 1391 | "{\n" 1392 | INDENT_STR "assert(stack_idx > 1);\n" 1393 | INDENT_STR "stack_idx--;\n" 1394 | INDENT_STR "stack[stack_idx - 1] *= stack[stack_idx];\n" 1395 | "}\n\n\n", fp); 1396 | fputs( 1397 | "inline static void arith_div(void)\n" 1398 | "{\n" 1399 | INDENT_STR "assert(stack_idx > 1);\n" 1400 | INDENT_STR "stack_idx--;\n" 1401 | INDENT_STR "assert(stack[stack_idx] != 0);\n" 1402 | INDENT_STR "stack[stack_idx - 1] /= stack[stack_idx];\n" 1403 | "}\n\n\n", fp); 1404 | fputs( 1405 | "inline static void arith_mod(void)\n" 1406 | "{\n" 1407 | INDENT_STR "assert(stack_idx > 1);\n" 1408 | INDENT_STR "stack_idx--;\n" 1409 | INDENT_STR "assert(stack[stack_idx] != 0);\n" 1410 | INDENT_STR "stack[stack_idx - 1] %= stack[stack_idx];\n" 1411 | "}\n\n\n", fp); 1412 | fputs( 1413 | "inline static void heap_store(void)\n" 1414 | "{\n" 1415 | INDENT_STR "int value = pop();\n" 1416 | INDENT_STR "int addr = pop();\n" 1417 | INDENT_STR "assert(0 <= addr && addr < (int) LENGTHOF(heap));\n" 1418 | INDENT_STR "heap[addr] = value;\n" 1419 | "}\n\n\n", fp); 1420 | fputs( 1421 | "inline static void heap_read(void)\n" 1422 | "{\n" 1423 | INDENT_STR "int addr = pop();\n" 1424 | INDENT_STR "assert(0 <= addr && addr < (int) LENGTHOF(heap));\n" 1425 | INDENT_STR "push(heap[addr]);\n" 1426 | "}\n", fp); 1427 | } 1428 | 1429 | 1430 | /*! 1431 | * @brief Read integer and seek program pointer. 1432 | * @param [in,out] code_ptr Program pointer 1433 | * @return An integer parsed from source code 1434 | */ 1435 | static int 1436 | read_nstr(const char **code_ptr) 1437 | { 1438 | const char *code = *code_ptr; 1439 | int is_positive = 1; 1440 | int sum = 0; 1441 | switch (*++code) { 1442 | case '\t': 1443 | is_positive = 0; 1444 | break; 1445 | case '\n': 1446 | *code_ptr = code; 1447 | return 0; 1448 | } 1449 | while (*++code != '\n') { 1450 | sum <<= 1; 1451 | if (*code == '\t') { 1452 | sum++; 1453 | } 1454 | } 1455 | *code_ptr = code; 1456 | return is_positive ? sum : -sum; 1457 | } 1458 | 1459 | 1460 | /*! 1461 | * @brief Read label and convert it into strings. 1462 | * @param [in,out] code_ptr Program pointer 1463 | * @return Converted label 1464 | */ 1465 | static char * 1466 | read_label(const char **code_ptr) 1467 | { 1468 | static char label_name[MAX_LABEL_LENGTH]; 1469 | char *ptr = label_name; 1470 | const char *code = *code_ptr; 1471 | char ch; 1472 | 1473 | while ((ch = *++code) != '\n') { 1474 | switch (ch) { 1475 | case ' ': 1476 | *ptr++ = 'S'; 1477 | break; 1478 | case '\t': 1479 | *ptr++ = 'T'; 1480 | break; 1481 | } 1482 | } 1483 | *ptr = '\0'; 1484 | *code_ptr = code; 1485 | return label_name; 1486 | } 1487 | 1488 | 1489 | /*! 1490 | * @brief Show byte code in hexadecimal 1491 | * @param [in] bytecode Whitespace byte code 1492 | * @param [in] bytecode_size Size of whitespace byte code 1493 | */ 1494 | static void 1495 | show_bytecode(const unsigned char *bytecode, size_t bytecode_size) 1496 | { 1497 | size_t i, j; 1498 | size_t quot = bytecode_size / 16; 1499 | size_t rem = bytecode_size % 16; 1500 | int addr_cnt = 0; 1501 | 1502 | puts("ADDRESS 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"); 1503 | for (i = 0; i < quot; i++) { 1504 | printf("0x%04x: ", addr_cnt); 1505 | addr_cnt += 16; 1506 | for (j = 0; j < 16; j++) { 1507 | printf(" %02x", *bytecode++); 1508 | } 1509 | puts(""); 1510 | } 1511 | printf("0x%04x: ", addr_cnt); 1512 | for (i = 0; i < rem; i++) { 1513 | printf(" %02x", *bytecode++); 1514 | } 1515 | puts(""); 1516 | } 1517 | 1518 | 1519 | /*! 1520 | * @brief Show the byte code in mnemonic format. 1521 | * @param [in] fp Output file pointer 1522 | * @param [in] bytecode Whitespace byte code 1523 | * @param [in] bytecode_size Size of whitespace byte code 1524 | */ 1525 | static void 1526 | show_mnemonic(FILE *fp, const unsigned char *bytecode, size_t bytecode_size) 1527 | { 1528 | const unsigned char *end; 1529 | const unsigned char *base = bytecode; 1530 | for (end = bytecode + bytecode_size; bytecode < end; bytecode++) { 1531 | fprintf(fp, "%04d: ", (int) ADDR_DIFF(bytecode, base)); 1532 | switch (*bytecode) { 1533 | case STACK_PUSH: 1534 | bytecode++; 1535 | fprintf(fp, "STACK_PUSH %d\n", *((const WsInt *) bytecode)); 1536 | bytecode += sizeof(WsInt) - 1; 1537 | break; 1538 | case STACK_DUP_N: 1539 | bytecode++; 1540 | fprintf(fp, "STACK_DUP_N %d\n", *((const WsInt *) bytecode)); 1541 | bytecode += sizeof(WsInt) - 1; 1542 | break; 1543 | case STACK_DUP: 1544 | fprintf(fp, "STACK_DUP\n"); 1545 | break; 1546 | case STACK_SLIDE: 1547 | bytecode++; 1548 | fprintf(fp, "STACK_SLIDE %d\n", *((const WsInt *) bytecode)); 1549 | bytecode += sizeof(WsInt) - 1; 1550 | break; 1551 | case STACK_SWAP: 1552 | fputs("STACK_SWAP\n", fp); 1553 | break; 1554 | case STACK_DISCARD: 1555 | fputs("STACK_POP\n", fp); 1556 | break; 1557 | case ARITH_ADD: 1558 | fputs("ARITH_ADD\n", fp); 1559 | break; 1560 | case ARITH_SUB: 1561 | fputs("ARITH_SUB\n", fp); 1562 | break; 1563 | case ARITH_MUL: 1564 | fputs("ARITH_MUL\n", fp); 1565 | break; 1566 | case ARITH_DIV: 1567 | fputs("ARITH_DIV\n", fp); 1568 | break; 1569 | case ARITH_MOD: 1570 | fputs("ARITH_MOD\n", fp); 1571 | break; 1572 | case HEAP_STORE: 1573 | fputs("HEAP_STORE\n", fp); 1574 | break; 1575 | case HEAP_LOAD: 1576 | fputs("HEAP_LOAD\n", fp); 1577 | break; 1578 | case FLOW_GOSUB: 1579 | bytecode++; 1580 | fprintf(fp, "FLOW_GOSUB %u\n", *((const WsAddrInt *) bytecode)); 1581 | bytecode += sizeof(WsAddrInt) - 1; 1582 | break; 1583 | case FLOW_JUMP: 1584 | bytecode++; 1585 | fprintf(fp, "FLOW_JUMP %u\n", *((const WsAddrInt *) bytecode)); 1586 | bytecode += sizeof(WsAddrInt) - 1; 1587 | break; 1588 | case FLOW_BEZ: 1589 | bytecode++; 1590 | fprintf(fp, "FLOW_BEZ %u\n", *((const WsAddrInt *) bytecode)); 1591 | bytecode += sizeof(WsAddrInt) - 1; 1592 | break; 1593 | case FLOW_BLTZ: 1594 | bytecode++; 1595 | fprintf(fp, "FLOW_BLTZ %u\n", *((const WsAddrInt *) bytecode)); 1596 | bytecode += sizeof(WsAddrInt) - 1; 1597 | break; 1598 | case FLOW_HALT: 1599 | fputs("FLOW_HALT\n", fp); 1600 | break; 1601 | case FLOW_ENDSUB: 1602 | fputs("FLOW_ENDSUB\n", fp); 1603 | break; 1604 | case IO_PUT_CHAR: 1605 | fputs("IO_PUT_CHAR\n", fp); 1606 | break; 1607 | case IO_PUT_NUM: 1608 | fputs("IO_PUT_NUM\n", fp); 1609 | break; 1610 | case IO_READ_CHAR: 1611 | fputs("IO_READ_CHAR\n", fp); 1612 | break; 1613 | case IO_READ_NUM: 1614 | fputs("IO_READ_NUM\n", fp); 1615 | break; 1616 | default: 1617 | fprintf(fp, "UNDEFINED_INSTRUCTION [0x%02x]\n", *bytecode); 1618 | } 1619 | } 1620 | } 1621 | 1622 | 1623 | /*! 1624 | * @brief Visualize the source code using S and T instead of space or tab. 1625 | * @param [in,out] fp Output file pointer 1626 | * @param [in] code Whitespace source code 1627 | */ 1628 | static void 1629 | filter(FILE *fp, const char *code) 1630 | { 1631 | for (; *code != '\0'; code++) { 1632 | switch (*code) { 1633 | case ' ': 1634 | fputc('S', fp); 1635 | break; 1636 | case '\t': 1637 | fputc('T', fp); 1638 | break; 1639 | case '\n': 1640 | fputc('\n', fp); 1641 | break; 1642 | } 1643 | } 1644 | } 1645 | --------------------------------------------------------------------------------