diff --git a/.travis.yml b/.travis.yml index 2ead638..2b91594 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,8 @@ os: dist: bionic +sudo: required + compiler: - gcc - clang @@ -19,3 +21,6 @@ script: - ./configure - make - make check + - sudo make install + - command -v u6a u6ac +# - whatis u6a u6ac # broken on macOS... diff --git a/README.md b/README.md index aee4c92..935bdc3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # u6a -[![license](https://img.shields.io/badge/licence-GPLv3-blue.svg)](LICENSE) +[![Travis CI](https://travis-ci.com/CismonX/u6a.svg)](https://travis-ci.com/CismonX/u6a) +[![LICENSE](https://img.shields.io/badge/licence-GPLv3-blue.svg)](LICENSE) Implementation of Unlambda, an esoteric programming language. diff --git a/configure.ac b/configure.ac index 73a32ce..be0329d 100644 --- a/configure.ac +++ b/configure.ac @@ -1,19 +1,33 @@ AC_PREREQ([2.69]) -AC_INIT([u6a], [0.01], [https://cismon.net]) +AC_INIT([u6a], [0.01], [bug-report@cismon.net]) AM_INIT_AUTOMAKE([foreign]) AC_CONFIG_SRCDIR([src/u6a.c]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile src/Makefile man/Makefile]) +dnl Check for operating system +AC_CANONICAL_HOST +case "${host_os}" in + linux*) + AC_SUBST([MANPATH_CONF], [/etc/manpath.config]) + AC_SUBST([REBUILD_MANDB], [mandb]) + ;; + darwin*) + AC_SUBST([MANPATH_CONF], [/private/etc/man.conf]) + AC_SUBST([REBUILD_MANDB], [/usr/libexec/makewhatis]) + ;; + *) + AC_MSG_ERROR(["Unsupported OS: ${host_os}"]) + ;; +esac + dnl Checks for programs. AC_PROG_CC_C99 -dnl Checks for libraries. - dnl Checks for header files. AC_CHECK_HEADERS([arpa/inet.h inttypes.h stddef.h stdint.h stdlib.h string.h unistd.h], [], - [AC_MSG_ERROR("required header(s) not found")]) + [AC_MSG_ERROR(["required header(s) not found"])]) dnl Checks for typedefs, structures, and compiler characteristics. AC_CHECK_HEADER_STDBOOL diff --git a/man/Makefile.am b/man/Makefile.am index de60a62..7f10112 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -1,8 +1,10 @@ -MAN_DIR = $(prefix)/share/man/man1 -MAN_FILES = u6ac.1 u6a.1 +MANPATH_MAP = $(shell cat $(MANPATH_CONF) | grep -w -m1 $(prefix)) +MAN_DIR = $(word 3, $(MANPATH_MAP)) +MAN1_DIR = $(MAN_DIR)/man1 +MAN_FILES = u6ac.1 u6a.1 install: $(MAN_FILES) - mkdir -p $(MAN_DIR) && cp -t $(MAN_DIR) $^ + cp -t $(MAN1_DIR) $^ && $(REBUILD_MANDB) $(MAN_DIR) uninstall: $(MAN_FILES) - pushd $(MAN_DIR) && rm -f $^ && popd + pushd $(MAN1_DIR) && rm -f $^ && popd && $(REBUILD_MANDB) $(MAN_DIR) diff --git a/src/Makefile.am b/src/Makefile.am index 2a16ae7..f609009 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ bin_PROGRAMS = u6ac u6a u6ac_SOURCES = logging.c lexer.c parser.c codegen.c u6ac.c -u6a_SOURCES = logging.c vm_stack.c vm_pool.c runtime.c u6a.c +u6a_SOURCES = logging.c vm_stack.c vm_pool.c runtime.c u6a.c diff --git a/src/codegen.c b/src/codegen.c index c7af705..4f38f33 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -144,6 +144,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) { if (peek_ins.opcode == u6a_vo_app && operand_first.fn == u6a_tf_out && !operand_second.fn) { rodata_buffer[rodata_len++] = operand_first.ch; } else { + ++stack_top; break; } } @@ -178,7 +179,7 @@ u6a_codegen(struct u6a_ast_node* ast_arr, uint32_t ast_len) { struct ins_with_offset* top_elem = stack + stack_top--; if (top_elem->ins.opcode == u6a_vo_sa) { text_buffer[text_len].opcode = u6a_vo_sa; - stack[stack_top++] = (struct ins_with_offset) { + stack[++stack_top] = (struct ins_with_offset) { .ins.opcode = u6a_vo_la, .offset = text_len++ }; diff --git a/src/runtime.c b/src/runtime.c index 8679200..9473eb4 100644 --- a/src/runtime.c +++ b/src/runtime.c @@ -255,7 +255,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) { ins = text + func.ref; func = acc; // The `s2` function incremenets IP before pushing `j`, so decrement IP here - if (func.token.fn = u6a_vf_s2) { + if (func.token.fn == u6a_vf_s2) { --ins; } arg = STACK_POP(); @@ -279,7 +279,7 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) { case u6a_vf_d1_c: func = POOL_GET1(func.ref); goto do_apply; - case u6a_vf_d1_s: ; + case u6a_vf_d1_s: tuple = POOL_GET2(func.ref); STACK_PUSH1(tuple.v1.fn); acc = tuple.v2.fn; @@ -339,8 +339,8 @@ u6a_runtime_execute(FILE* restrict istream, FILE* restrict ostream) { break; case u6a_vo_del: delay: - acc = U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text); - ins = text + ins->operand.offset; + STACK_PUSH1(U6A_VM_VAR_FN_REF(u6a_vf_d1_d, ins + 1 - text)); + ins = text + text_subst_len + ins->operand.offset; continue; case u6a_vo_lc: switch (ins->opcode_ex) { diff --git a/src/vm_defs.h b/src/vm_defs.h index b19585d..585ad34 100644 --- a/src/vm_defs.h +++ b/src/vm_defs.h @@ -53,20 +53,20 @@ enum u6a_vm_opcode_ex { enum u6a_vm_fn { u6a_vf_placeholder_, u6a_vf_k, u6a_vf_s, u6a_vf_i, u6a_vf_v, u6a_vf_c, u6a_vf_d, u6a_vf_e, - u6a_vf_in, /* @ */ - u6a_vf_pipe, /* | */ - u6a_vf_out = U6A_VM_FN_CHAR, /* .X */ - u6a_vf_cmp, /* ?X */ - u6a_vf_k1 = U6A_VM_FN_REF, /* `kX */ - u6a_vf_s1, /* `sX */ - u6a_vf_s2, /* ``sXY */ - u6a_vf_c1, /* `cX */ - u6a_vf_d1_s = U6A_VM_FN_PROMISE, /* `d`XZ */ - u6a_vf_d1_c, /* `dX */ - u6a_vf_d1_d, /* `dF */ - u6a_vf_j = U6A_VM_FN_INTERNAL, /* (jump) */ - u6a_vf_f, /* (finalize) */ - u6a_vf_p /* (print) */ + u6a_vf_in, /* @ */ + u6a_vf_pipe, /* | */ + u6a_vf_out = U6A_VM_FN_CHAR, /* .X */ + u6a_vf_cmp, /* ?X */ + u6a_vf_k1 = U6A_VM_FN_REF, /* `kX */ + u6a_vf_s1, /* `sX */ + u6a_vf_s2, /* ``sXY */ + u6a_vf_c1, /* `cX */ + u6a_vf_d1_s = U6A_VM_FN_PROMISE, /* `d`XZ */ + u6a_vf_d1_c, /* `dX */ + u6a_vf_d1_d, /* `dF */ + u6a_vf_j = U6A_VM_FN_INTERNAL, /* (jump) */ + u6a_vf_f, /* (finalize) */ + u6a_vf_p /* (print) */ }; struct u6a_vm_ins { diff --git a/src/vm_pool.c b/src/vm_pool.c index e5273e8..fdba9b9 100644 --- a/src/vm_pool.c +++ b/src/vm_pool.c @@ -90,20 +90,20 @@ free_stack_pop() { bool u6a_vm_pool_init(uint32_t pool_len_, uint32_t ins_len) { - const uint32_t pool_size = sizeof(struct vm_pool) + pool_len * sizeof(struct vm_pool_elem); + const uint32_t pool_size = sizeof(struct vm_pool) + pool_len_ * sizeof(struct vm_pool_elem); active_pool = malloc(pool_size); if (UNLIKELY(active_pool == NULL)) { return false; } - const uint32_t holes_size = sizeof(struct vm_pool_elem_ptrs) + pool_len * sizeof(struct vm_pool_elem*); + const uint32_t holes_size = sizeof(struct vm_pool_elem_ptrs) + pool_len_ * sizeof(struct vm_pool_elem*); holes = malloc(holes_size); - if (UNLIKELY(active_pool == NULL)) { - free(active_pool); + if (UNLIKELY(holes == NULL)) { + free(holes); return false; } - const uint32_t free_stack_size = fstack_len * sizeof(struct vm_pool_elem*); + const uint32_t free_stack_size = ins_len * sizeof(struct vm_pool_elem*); fstack = malloc(free_stack_size); - if (UNLIKELY(active_pool == NULL)) { + if (UNLIKELY(fstack == NULL)) { free(active_pool); free(holes); return false; @@ -150,10 +150,8 @@ u6a_vm_pool_alloc2(struct u6a_vm_var_fn v1, struct u6a_vm_var_fn v2) { if (UNLIKELY(elem == NULL)) { return UINT32_MAX; } - elem = &(struct vm_pool_elem) { - .values = { .v1.fn = v1, .v2.fn = v2 }, - .flags = 0 - }; + elem->values = (struct u6a_vm_var_tuple) { .v1.fn = v1, .v2.fn = v2 }; + elem->flags = 0; return elem - active_pool->elems; } @@ -163,10 +161,8 @@ u6a_vm_pool_alloc2_ptr(void* v1, void* v2) { if (UNLIKELY(elem == NULL)) { return UINT32_MAX; } - elem = &(struct vm_pool_elem) { - .values = { .v1.ptr = v1, .v2.ptr = v2 }, - .flags = POOL_ELEM_HOLDS_PTR - }; + elem->values = (struct u6a_vm_var_tuple) { .v1.ptr = v1, .v2.ptr = v2 }; + elem->flags = POOL_ELEM_HOLDS_PTR; return elem - active_pool->elems; } @@ -186,7 +182,7 @@ u6a_vm_pool_free(uint32_t offset) { fstack_top = UINT32_MAX; do { if (--elem->refcnt == 0) { - holes->elems[holes->pos] = elem; + holes->elems[++holes->pos] = elem; if (elem->flags & POOL_ELEM_HOLDS_PTR) { // Continuation destroyed before used u6a_vm_stack_discard(elem->values.v1.ptr); @@ -195,7 +191,7 @@ u6a_vm_pool_free(uint32_t offset) { free_stack_push(elem->values.v2); } } - } while (elem = free_stack_pop()); + } while ((elem = free_stack_pop())); } void diff --git a/src/vm_stack.c b/src/vm_stack.c index 3d2448c..c39b27b 100644 --- a/src/vm_stack.c +++ b/src/vm_stack.c @@ -35,27 +35,26 @@ static uint32_t stack_seg_len; static inline struct vm_stack* vm_stack_create(struct vm_stack* prev, uint32_t top) { - const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(union u6a_vm_var); + const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn); struct vm_stack* vs = malloc(size); if (UNLIKELY(vs == NULL)) { return NULL; } - return vs = &(struct vm_stack) { - .prev = prev, - .top = top, - .refcnt = 1 - }; + vs->prev = prev; + vs->top = top; + vs->refcnt = 1; + return vs; } static inline struct vm_stack* vm_stack_dup() { struct vm_stack* vs = active_stack; - const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(union u6a_vm_var); + const uint32_t size = sizeof(struct vm_stack) + stack_seg_len * sizeof(struct u6a_vm_var_fn); struct vm_stack* dup_stack = malloc(size); if (UNLIKELY(dup_stack == NULL)) { return NULL; } - memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(union u6a_vm_var)); + memcpy(dup_stack, vs, sizeof(struct vm_stack) + (vs->top + 1) * sizeof(struct u6a_vm_var_fn)); dup_stack->refcnt = 1; return dup_stack; }