diff --git a/.gitignore b/.gitignore index 534a86a..34e3ef8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ /libg1m.so* /libg1m.dll /man + +.*.swp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a964037 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "tools/fontcharacter"] + path = tools/fontcharacter + url = https://forge.touhey.fr/casio/python3-modules/fontcharacter +[submodule "tools/fontcharacter_reference"] + path = tools/fontcharacter_reference + url = https://forge.touhey.fr/casio/casiowin/fontcharacter_reference diff --git a/Makefile b/Makefile index 0515d82..37c1c6b 100755 --- a/Makefile +++ b/Makefile @@ -4,6 +4,9 @@ #******************************************************************************# include Makefile.vars Makefile.msg +# Check if we're a git repository + ISGIT := $(shell test -e .git && echo y) + #******************************************************************************# # General targets # #******************************************************************************# @@ -22,6 +25,7 @@ clean: clean-lib clean-doc mrproper: clean $(call rmsg,Removing configuration.) $(call qcmd,$(RM) Makefile.cfg) + $(call qcmd,$(RM) -r lib$(NAME)-*) # Remake everything. (clean and build) re: clean all @@ -37,7 +41,7 @@ uninstall: uninstall-lib uninstall-doc uninstall-cfgtool reinstall: uninstall install # Make a distribution tarball -dist: mrproper +dist: mrproper $(if $(ISGIT),reinit-gitmodules) $(call bcmd,mkdir,lib$(NAME)-$(VERSION),\ $(MD) .dist) $(call bcmd,cp,* lib$(NAME)-$(VERSION),\ @@ -52,14 +56,27 @@ dist: mrproper .PHONY: all mostlyclean mclean clean fclean mrproper re .PHONY: dist install uninstall reinstall #******************************************************************************# -# Configuration (version) checking dependencies # +# Git submodules management # +#******************************************************************************# +# Main rule. + reinit-gitmodules: + $(call bcmd,Deinitializing git submodules.) + $(call qcmd,git submodule deinit -f --quiet -- \ + $(shell grep path .gitmodules | sed 's/.*= //')) + $(call bcmd,Reinitializing git submodules.) + $(call qcmd,git submodule update --init --recursive --quiet) + +.PHONY: reinit-gitmodules +#******************************************************************************# +# Checking dependencies # #******************************************************************************# # Define the dependencies. CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \ $(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \ check-config-version)) + CHECKFC := $(if $(ISGIT),check-gitmodules) -# Define the rules. +# Configuration checking. check-config: @echo -e "\033[1;31mNo configuration file found!" @echo -e "You should configure before re-running this target.\033[0m" @@ -69,7 +86,12 @@ dist: mrproper @echo -e "You should re-configure before re-running this target.\033[0m" @false -.PHONY: check-config check-config-version +# Git submodules checking. + check-gitmodules: + $(call bcmd,Checking git modules.) + $(call qcmd,git submodule update --init --recursive) + +.PHONY: check-config check-config-version check-gitmodules #******************************************************************************# # Information getting from the Makefile variables # #******************************************************************************# diff --git a/Makefile.vars b/Makefile.vars index 0a398ac..d0cefae 100755 --- a/Makefile.vars +++ b/Makefile.vars @@ -87,6 +87,10 @@ # Directory maker MD := mkdir -p +# Copier + CP := cp +# Mover + MV := mv # Symbolic link maker LN := ln -sf # File remover diff --git a/README.md b/README.md index f50baea..beb08f8 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ I took these as a reference because these are the ones I work with. | [binutils](https://www.gnu.org/software/binutils/) | >= 2.25 | | [asciidoc](http://asciidoc.org/) | >= 8.6.9 | | [gzip](https://www.gnu.org/software/gzip/) | >= 1.6 | +| [python3](https://www.python.org/) | >= 3.5 | ### Runtime dependencies | Name | Version | diff --git a/configure b/configure index 2edf88a..74f7c7d 100755 --- a/configure +++ b/configure @@ -10,9 +10,6 @@ version="$(make -s getversion)" # Maintainer maintainer="$(make -s getmaintainer)" -# Target -target="" - # Platform platform="$(command -v gcc 1>/dev/null && gcc --print-multiarch)" platform="$([ "$platform" ] && echo "/$platform")" @@ -21,7 +18,9 @@ platform="$([ "$platform" ] && echo "/$platform")" make_full_log= # Build options +target= loglevel=none # none, info, warn, error, fatal +fcset=$(tools/list-sets --default) # Installation directories root='' @@ -53,6 +52,7 @@ General options: --make-full-log display full commands while making Build options: + --set=SET the FONTCHARACTER set (if none, default one) --target=TARGET the target (if none, native) --loglevel=LOGLEVEL library log level [$loglevel] @@ -71,6 +71,11 @@ Fine tuning of the installation directories: --includedir=DIR include files for the compiler [$includedir] --mandir=DIR man root [$mandir] +Available FONTCHARACTER sets are: +EOF +./tools/list-sets --long +cat <&2 + fi ;; --noinstall-manpages) install_manpages= ;; --noinstall-devel) install_devel= ;; --root=*) root="${arg#*=}" ;; @@ -163,6 +175,7 @@ cat < |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/07 17:00:25 |___/ */ +/* */ +/* ************************************************************************** */ +#ifndef LIBG1M_BASIC_H +# define LIBG1M_BASIC_H +# define CBASIC_MAX_ARGUMENTS 3 + +/* libg1m has utilities for interacting with Basic programs! + * Everything is basically a statement, but when it's just a + * value/variable/..., it's instruction 0x00 with one argument. + * + * Here are the types an argument can take: */ + +enum g1m_argument_type { + g1m_argtype_value, + g1m_argtype_variable, + g1m_argtype_string, + g1m_argtype_list, + g1m_argtype_mat, +}; + +/* And here's the structure of a statement: */ + +typedef struct g1m_basic_statement_s { + FONTCHARACTER opcode; + int argtype, id; + + /* BCD values */ + struct bcd real; + struct bcd imgn; + + /* arguments */ + int nargs; + struct g1m_basic_statement_s *args; +} g1m_bst_t; + +/* And here is the function to fetch an instruction from a program content + * buffer: */ + +int g1m_fetch_instruction(const FONTCHARACTER *buf, size_t size, + size_t *isize, g1m_bst_t *statement); + +#endif /* LIBG1M_BASIC_H */ diff --git a/src/basic/instruction.c.draft b/src/basic/instruction.c.draft new file mode 100644 index 0000000..d6556b6 --- /dev/null +++ b/src/basic/instruction.c.draft @@ -0,0 +1,232 @@ +/* ************************************************************************** */ +/* _____ _ */ +/* basic/instruction.c |_ _|__ _ _| |__ ___ _ _ */ +/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */ +/* | | (_) | |_| | | | | __/ |_| | */ +/* By: thomas |_|\___/ \__,_|_| |_|\___|\__, |.fr */ +/* Last updated: 2017/01/07 14:55:53 |___/ */ +/* */ +/* ************************************************************************** */ +#include +#define go_forward(N) *buf += (N); *size -= (N) + +/* ************************************************************************** */ +/* Utilities */ +/* ************************************************************************** */ +/** + * parse_bcd: + * Parse a BCD. + * + * @arg buf the FONTCHARACTER buffer. + * @arg size the buffer size. + * @arg real the real part. + * @arg imgn the imaginary part. + * @return the error. + */ + +static int fetch_bcd(const FONTCHARACTER **buf, size_t *size, + struct bcd *real, struct bcd *imgn) +{ + /* TODO */ + return (g1m_error_eof); +} + +/** + * fetch_int: + * Decode an integer. + * + * @arg buf the FONTCHARACTER buffer. + * @arg size the buffer size. + * @arg num the integer to parse. + */ + +static int fetch_int(const FONTCHARACTER **buf, size_t *size, int *id) +{ + /* check the ans */ + if (**buf == 0xC0) { *id = g1m_ans; (*buf)++; (*size)--; return (0); } + + /* peek and get the size of the number */ + int i; for (i = 0; i < *size && (*buf)[i] >= '0' && (*buf)[i] <= '9'; i++); + + /* get the number */ + int numsize = i; + *id = 0; while (i-- >= 0) *id = *id * 10 + (*buf)[i] - '0'; + + /* go forward and ok */ + go_forward(numsize); + return (0); +} + +/** + * fetch_argument: + * Decode an argument. + * + * @arg buf the FONTCHARACTER buffer. + * @arg size the buffer size. + * @arg arg the argument structure. + * @return if there was an error + */ + +#define VAR(ID) (struct argument){.type = g1m_argtype_var, .id = (ID)} +static int fetch_argument(const FONTCHARACTER **buf, size_t *size, + struct argument *arg) +{ + /* check if we have at least one character */ + if (!*size) return (g1m_error_eof); + + /* check if is something special */ + FONTCHARACTER op = **buf; + if (opcode == 0xF93F) { arg->type = g1m_argtype_string; goto parse_id; } + if (opcode == 0x7F40) { arg->type = g1m_argtype_mat; goto parse_let; } + if (opcode == 0x7F51) { arg->type = g1m_argtype_list; goto parse_id; } + + /* check if it's a var */ + if (op == 0xC0) *arg = VAR(g1m_ans); + else if (op == 0xCE) *arg = VAR(g1m_theta); + else if (op == 0xCD) *arg = VAR(g1m_r); + else if (op >= 'A' && op <= 'Z') *arg = VAR(op - 'A'); + else { + int err = fetch_bcd(buf, size, &arg->real, &arg->imgn); + if (err) return (fetch_statement(buf, size, arg->statement)); + return (err); + } + + /* was a var */ + go_forward(1); + return (0); + + /* it's something with an ID! */ +parse_id: + go_forward(1); + return (fetch_int(buf, size, &arg->id)); + + /* it's something with a letter ID! */ +parse_let: + go_forward(1); + return (fetch_let(buf, size, &arg->id)); +} + +/* ************************************************************************** */ +/* Statements */ +/* ************************************************************************** */ +/* Statements */ +struct statement { + /* the start opcode */ + FONTCHARACTER opcode; + + /* number of arguments */ + int nargs; + + /* finishes with a parenthesis */ + int par; +}; + +/* Known statements */ +static const struct statement statements[] = { + /* Locate x,x,x */ + {0xF710, 3, 0}, + /* Send(A) */ + {0xF711, 1, 1}, + /* Receive(A) */ + {0xF712, 1, 1}, + + {0, 0} +}; + +/* Infix statements */ +static const struct statement infix_statements[] = { + /* x! */ + {0xEA, 1, 0}, + /* a = b */ + {0x3D, 2, 0}, + + {0, 0} +}; + +/** + * fetch_raw_statement: + * Fetch a statement. + * + * @arg buf the FONTCHARACTER buffer pointer. + * @arg size the FONTCHARACTER buffer size pointer. + * @arg st the statement pointer. + * @arg fst the first argument + * @arg infix is infix (boolean!) + * @return the error. + */ + +static int fetch_raw_statement(const FONTCHARACTER **buf, size_t *size, + struct statement *st, struct argument *fst, int infix) +{ + /* check if there is at least space for one opcode */ + if (!*size) return (1); + + /* get the statements tab */ + const struct *sts = + (const *struct statement[]){statements, infix_statements}[infix]; + + /* check which opcode it is */ + FONTCHARACTER op = **buf; + const struct *st; + for (st = sts; st->opcode && st->opcode != op; st++); + if (!st) return (1); + + /* prepare the arguments */ + int nargs = st->nargs; + struct argument *args = malloc(nargs * sizeof(struct argument)); + if (!args) return (1); + if (nargs) memcpy(&args[0], fst, sizeof(struct argument)); + + /* iterate */ + int last = infix - 1; + for (int i = infix; i < nargs; i++) { + /* parse the arg */ + if (fetch_argument(buf, size, &args[i])) + return (1); + + /* check the comma */ + if (i < last && (!*size || **buf != ',')) + return (1); + go_forward(1); + } + + /* check right parenthesis */ + if (st->par && *size && **buf != ')') + return (1); + if (*size) { go_forward(1); } + + /* no error */ + return (0); +} + +/** + * fetch_statement: + * Fetch a statement. + */ + +/* ************************************************************************** */ +/* Main function */ +/* ************************************************************************** */ +/** + * g1m_fetch_instruction: + * Fetch the instruction. + * + * @arg buf the FONTCHARACTER buffer. + * @arg size the FONTCHARACTER buffer size. + * @arg statement the statement. + * @return if negative: the negative libg1m error code. + * otherwise: the size of the instruction. + */ + +int g1m_fetch_instruction(const FONTCHARACTER *buf, size_t size, + g1m_bst_t *statement) +{ + size_t sav = size; + + /* start by free-ing statement content? */ + /* TODO */ + + /* check it it's a statement */ + int err = fetch_statement(&buf, &size, &statement, 0); + return (err ? -err : (int)(sav - size)); +} diff --git a/tools/check-set b/tools/check-set new file mode 100755 index 0000000..0217927 --- /dev/null +++ b/tools/check-set @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +# Dependencies +import os, sys +from fontcharacter import Reference + +# Open the reference +refpath = os.path.join(os.path.dirname(__file__), 'fontcharacter_reference') +ref = Reference(refpath, sets_only=True) + +# Exit with the correct code +exit(not sys.argv[1] in ref.sets.keys()) diff --git a/tools/fontcharacter b/tools/fontcharacter new file mode 160000 index 0000000..72a14ac --- /dev/null +++ b/tools/fontcharacter @@ -0,0 +1 @@ +Subproject commit 72a14ac14d774416efc9c72bd3dd6646ee6138ea diff --git a/tools/fontcharacter_reference b/tools/fontcharacter_reference new file mode 160000 index 0000000..1f382d0 --- /dev/null +++ b/tools/fontcharacter_reference @@ -0,0 +1 @@ +Subproject commit 1f382d0797f7534df408e858a9182bd11c9dddea diff --git a/tools/list-sets b/tools/list-sets new file mode 100755 index 0000000..af927cb --- /dev/null +++ b/tools/list-sets @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Dependencies +import os, sys +from fontcharacter import Reference + +# Open the reference +refpath = os.path.join(os.path.dirname(__file__), 'fontcharacter_reference') +ref = Reference(refpath, sets_only=True) + +# Put the default +if "--default" in sys.argv: + print(ref.default_set) + exit(0) + +# List them +lg = "--long" in sys.argv +k = sorted(ref.sets.keys()) +for name, s in zip(k, map(ref.sets.__getitem__, k)): + if lg: + print('* %s: %s%s'%(name, s['description'], \ + ' (default)' if name == ref.default_set else '')) + else: + print(name) diff --git a/tools/write-config b/tools/write-config index ed75f2a..d4062d2 100755 --- a/tools/write-config +++ b/tools/write-config @@ -45,12 +45,7 @@ exit 0 # Version message # #******************************************************************************# version() { -cat <