From 89b0dafe92ee723a69c1da1aaa2bbcb4551fab16 Mon Sep 17 00:00:00 2001 From: David McMackins II Date: Mon, 22 May 2017 11:46:38 -0500 Subject: Use new Delwink style --- .gitignore | 1 - Makefile | 38 ++ README | 14 +- autogen.sh | 5 - configure.ac | 23 - mvobjs.sh | 4 + src/button.h | 46 +- src/font.c | 242 +++---- src/font.h | 8 +- src/keys.c | 210 +++--- src/keys.h | 4 +- src/liberti.c | 597 ++++++++-------- src/log.c | 46 +- src/log.h | 12 +- src/mode_default.c | 497 +++++++------- src/mode_default.h | 6 +- src/point.h | 6 +- src/screen.c | 27 +- src/screen.h | 22 +- src/skin.c | 1240 ++++++++++++++++----------------- src/skin.h | 32 +- src/state.c | 475 +++++++------ src/state.h | 56 +- src/tibchar.c | 618 ++++++++--------- src/tibchar.h | 196 +++--- src/tibdecode.c | 131 ++-- src/tibencode.c | 262 ++++--- src/tiberr.h | 34 +- src/tibeval.c | 1287 ++++++++++++++++++----------------- src/tibeval.h | 24 +- src/tibexpr.c | 412 +++++------ src/tibexpr.h | 37 +- src/tibfunction.c | 381 ++++++----- src/tibfunction.h | 14 +- src/tiblst.c | 156 ++--- src/tiblst.h | 28 +- src/tibtranscode.c | 1526 ++++++++++++++++++++--------------------- src/tibtranscode.h | 6 +- src/tibtype.c | 1929 ++++++++++++++++++++++++++-------------------------- src/tibtype.h | 76 +-- src/tibvar.c | 182 ++--- src/tibvar.h | 16 +- src/util.c | 125 ++-- src/util.h | 14 +- 44 files changed, 5558 insertions(+), 5507 deletions(-) create mode 100644 Makefile delete mode 100755 autogen.sh delete mode 100644 configure.ac create mode 100755 mvobjs.sh diff --git a/.gitignore b/.gitignore index 5e1df20..97b83fd 100644 --- a/.gitignore +++ b/.gitignore @@ -32,7 +32,6 @@ autom4te.cache m4/ libtool src/.dirstamp -Makefile Makefile.in aclocal.m4 configure diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d3b83fd --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +CC=c99 +CFLAGS=-Wall -Wextra -Wunreachable-code -ftrapv -fPIC -g -D_POSIX_C_SOURCE=2 -D_REENTRANT -I/usr/include/SDL2 +CONFIG_LIBS=-lconfig +GSL_LIBS=-lgsl -lgslcblas -lm +PFXTREE_LIBS=-lpfxtree +SDL2_LIBS=-lSDL2 -lSDL2_image +PREFIX=/usr/local +BINDIR=$(DESTDIR)$(PREFIX)/bin + +all: liberti tibencode tibdecode + +liberti_deps=src/colors.o src/font.o src/keys.o src/liberti.o src/log.o src/mode_default.o src/screen.o src/skin.o src/state.o libtib.a +liberti: $(liberti_deps) + ./mvobjs.sh + $(CC) -o $@ $(liberti_deps) $(CONFIG_LIBS) $(GSL_LIBS) $(PFXTREE_LIBS) $(SDL2_LIBS) + +tibencode_deps=src/tibencode.o libtib.a +tibencode: $(tibencode_deps) + ./mvobjs.sh + $(CC) -o $@ $(tibencode_deps) $(GSL_LIBS) $(PFXTREE_LIBS) + +tibdecode_deps=src/tibdecode.o libtib.a +tibdecode: $(tibdecode_deps) + ./mvobjs.sh + $(CC) -o $@ $(tibdecode_deps) $(GSL_LIBS) $(PFXTREE_LIBS) + +libtib_deps=src/tibchar.o src/tiberr.o src/tibeval.o src/tibexpr.o src/tibfunction.o src/tiblst.o src/tibtranscode.o src/tibtype.o src/tibvar.o src/util.o +libtib.a: $(libtib_deps) + ./mvobjs.sh + $(AR) rcs $@ $(libtib_deps) + +install: all + install -m755 liberti $(BINDIR)/liberti + install -m755 tibencode $(BINDIR)/tibencode + install -m755 tibdecode $(BINDIR)/tibdecode + +clean: + rm -f src/*.o *.a liberti tibencode tibdecode diff --git a/README b/README index 3c107e2..243ec9c 100644 --- a/README +++ b/README @@ -10,8 +10,8 @@ You must first satisfy the build dependencies of LiberTI. | Library/Tool | Purpose | |----------------------------|-----------------------------------------------| -| GNU Autotools | Automatic build scripts | -| C11 Compiler | (Prefer GCC or Clang) Source compilation | +| POSIX Make | Build scripts | +| C99 Compiler | (Prefer GCC or Clang) Source compilation | | GNU Scientific Library | Complex math calculations and data structures | | Simple DirectMedia Layer 2 | Graphics and threading | | SDL2 Image | Image loading support | @@ -21,16 +21,14 @@ You must first satisfy the build dependencies of LiberTI. On Debian GNU/Linux and derivatives, you can install these with the following command: - # apt-get install build-essential autoconf automake libgsl0-dev \ - libsdl2-dev libsdl2-image-dev libconfig-dev + # apt-get install build-essential libgsl0-dev libsdl2-dev \ + libsdl2-image-dev libconfig-dev For libpfxtree, download the latest stable source from [Delwink's site][3], and build/install according to the README inside. After the dependencies are installed, you can build LiberTI as follows: - $ ./autogen.sh - $ ./configure $ make If you wish to install LiberTI to the system, you can run the following: @@ -74,9 +72,7 @@ officially endorsed or supported by LibreCalc. Hacking ------- -We prefer the GNU coding style for C with a strict limit of 79 columns in the -source code. Indentations are two spaces, and tab characters are eight -spaces. +Copy the style you see in the code. Do not use spaces for indentation. To submit a patch, [submit your diff to Delwink][2], or use GitHub's pull request system. diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 5b883a6..0000000 --- a/autogen.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -set -e -srcdir="$(dirname $0)" -cd "$srcdir" -autoreconf --install --force diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 4363aa4..0000000 --- a/configure.ac +++ /dev/null @@ -1,23 +0,0 @@ -AC_PREREQ([2.60]) -AC_INIT([liberti],[0.0.0],[support@delwink.com]) - -AC_CONFIG_SRCDIR([src/liberti.c]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) -AM_SILENT_RULES([yes]) -AM_PROG_AR -AC_PROG_RANLIB -AC_PROG_CC - -PKG_CHECK_MODULES([gsl], [gsl]) -PKG_CHECK_MODULES([pfxtree], [pfxtree]) -PKG_CHECK_MODULES([sdl2], [sdl2]) -PKG_CHECK_MODULES([libconfig], [libconfig]) - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([ - Makefile -]) -AC_OUTPUT diff --git a/mvobjs.sh b/mvobjs.sh new file mode 100755 index 0000000..467ac53 --- /dev/null +++ b/mvobjs.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +mv *.o src/ >/dev/null 2>&1 +exit 0 diff --git a/src/button.h b/src/button.h index 21c5dca..4e7ebe9 100644 --- a/src/button.h +++ b/src/button.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,41 +21,41 @@ #include "screen.h" enum cursor_direction - { - UP = -16, - DOWN = 16, - LEFT = -1, - RIGHT = 1 - }; +{ + UP = -16, + DOWN = 16, + LEFT = -1, + RIGHT = 1 +}; enum button_action_type - { - CHANGE_MODES, - CHAR_INSERT, - CURSOR_MOVE, - TOGGLE_2ND, - TOGGLE_ALPHA, - TOGGLE_INSERT - }; +{ + CHANGE_MODES, + CHAR_INSERT, + CURSOR_MOVE, + TOGGLE_2ND, + TOGGLE_ALPHA, + TOGGLE_INSERT +}; union button_action { - int char_insert; - enum cursor_direction cursor_move; - enum screen_mode mode_open; + int char_insert; + enum cursor_direction cursor_move; + enum screen_mode mode_open; }; struct button_action_set { - enum button_action_type type; - union button_action which; + enum button_action_type type; + union button_action which; }; struct button { - struct button_action_set actions[NUM_SCREEN_MODES][NUM_ACTION_STATES]; - struct point2d pos; - struct point2d size; + struct button_action_set actions[NUM_SCREEN_MODES][NUM_ACTION_STATES]; + struct point2d pos; + struct point2d size; }; #endif diff --git a/src/font.c b/src/font.c index 973ab70..ce7c646 100644 --- a/src/font.c +++ b/src/font.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -31,138 +31,138 @@ static bool tiles_init = false; static SDL_Surface *tiles[NUM_TILES]; int -font_init () +font_init() { - SDL_Surface *tileset; - - if (tiles_init) - return 0; - - memset (tiles, 0, sizeof tiles); - - tileset = IMG_Load_RW (SDL_RWFromMem (FONT_PNG_DATA, FONT_PNG_SIZE), 1); - if (!tileset) - { - critical ("Failed to load tileset: %s", SDL_GetError ()); - return TIB_EALLOC; - } - - for (unsigned int i = 0; i < NUM_TILES; ++i) - { - tiles[i] = SDL_CreateRGBSurface (0, 6, 8, 32, 0, 0, 0, 0); - if (!tiles[i]) - { - critical ("Failed to alloc tile %u: %s", i, SDL_GetError ()); - - for (unsigned int j = 0; j < i; ++j) - SDL_FreeSurface (tiles[j]); - - return TIB_EALLOC; - } - - SDL_Rect src = { i * 6, 0, 6, 8 }; - if (SDL_BlitSurface (tileset, &src, tiles[i], NULL)) - error ("Failed to blit tile %u: %s", i, SDL_GetError ()); - } - - SDL_FreeSurface (tileset); - tiles_init = true; - return 0; + SDL_Surface *tileset; + + if (tiles_init) + return 0; + + memset(tiles, 0, sizeof tiles); + + tileset = IMG_Load_RW(SDL_RWFromMem(FONT_PNG_DATA, FONT_PNG_SIZE), 1); + if (!tileset) + { + critical("Failed to load tileset: %s", SDL_GetError()); + return TIB_EALLOC; + } + + for (unsigned int i = 0; i < NUM_TILES; ++i) + { + tiles[i] = SDL_CreateRGBSurface(0, 6, 8, 32, 0, 0, 0, 0); + if (!tiles[i]) + { + critical("Failed to alloc tile %u: %s", i, + SDL_GetError()); + + for (unsigned int j = 0; j < i; ++j) + SDL_FreeSurface(tiles[j]); + + return TIB_EALLOC; + } + + SDL_Rect src = { i * 6, 0, 6, 8 }; + if (SDL_BlitSurface(tileset, &src, tiles[i], NULL)) + error("Failed to blit tile %u: %s", i, SDL_GetError()); + } + + SDL_FreeSurface(tileset); + tiles_init = true; + return 0; } void -font_free () +font_free() { - if (tiles_init) - for (unsigned int i = 0; i < NUM_TILES; ++i) - SDL_FreeSurface (tiles[i]); + if (tiles_init) + for (unsigned int i = 0; i < NUM_TILES; ++i) + SDL_FreeSurface(tiles[i]); - tiles_init = false; + tiles_init = false; } SDL_Surface * -get_font_char (int c) +get_font_char(int c) { - if (!tiles_init || c < 0) - return NULL; + if (!tiles_init || c < 0) + return NULL; - return tiles[c]; + return tiles[c]; } // generated from font.png -unsigned char FONT_PNG_DATA[] = - { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08, - 0x08, 0x03, 0x00, 0x00, 0x00, 0x08, 0xb3, 0xc4, 0x0e, 0x00, 0x00, 0x00, - 0x06, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa5, - 0xd9, 0x9f, 0xdd, 0x00, 0x00, 0x03, 0x12, 0x49, 0x44, 0x41, 0x54, 0x68, - 0xde, 0xed, 0x5a, 0x81, 0x76, 0x9c, 0x30, 0x0c, 0x93, 0xff, 0xff, 0xa7, - 0xf7, 0xda, 0x83, 0x20, 0xc9, 0x0e, 0x81, 0x5b, 0xdf, 0x8d, 0x6d, 0xf6, - 0xbb, 0xa6, 0x94, 0xa3, 0xc1, 0x71, 0x82, 0x64, 0x2b, 0x20, 0xbe, 0x0d, - 0x5f, 0x56, 0xb4, 0xbb, 0x21, 0xb5, 0x4f, 0x33, 0xbc, 0x1a, 0x8c, 0xf6, - 0x75, 0x28, 0x2e, 0xd3, 0xaf, 0xeb, 0x83, 0xd8, 0xc2, 0x80, 0x71, 0x3c, - 0x22, 0x43, 0xc7, 0x74, 0x7e, 0x3f, 0x81, 0xda, 0x45, 0x0e, 0x24, 0x5d, - 0x39, 0x7a, 0xd6, 0x63, 0x99, 0x8b, 0x57, 0x33, 0x6e, 0xbc, 0x77, 0x41, - 0x43, 0xa6, 0x63, 0x4c, 0xfb, 0x0c, 0x9e, 0x65, 0x0b, 0x9a, 0xb5, 0x34, - 0xba, 0x11, 0x8d, 0xb4, 0x06, 0x50, 0x1c, 0xa5, 0x6f, 0xe0, 0xe7, 0xd2, - 0x5c, 0x00, 0xef, 0xcc, 0xf8, 0xd5, 0x39, 0xd4, 0xf5, 0x90, 0xbe, 0xe3, - 0x5e, 0xd5, 0x55, 0x70, 0x2b, 0x0b, 0x02, 0xd5, 0x14, 0xfe, 0xdc, 0x7a, - 0x7e, 0xe6, 0x63, 0xd6, 0xf6, 0x8f, 0x19, 0x94, 0x00, 0xfc, 0x23, 0x20, - 0x88, 0x27, 0x33, 0x40, 0x22, 0x80, 0x7d, 0x44, 0xdf, 0x7f, 0x62, 0x42, - 0x63, 0xab, 0x01, 0x11, 0x98, 0x32, 0x5a, 0x0d, 0x04, 0x80, 0x61, 0x11, - 0x1c, 0x82, 0x4f, 0x40, 0x73, 0x01, 0xbe, 0x29, 0xe0, 0xd2, 0x33, 0xdd, - 0x79, 0x7c, 0x5e, 0xb7, 0xc2, 0xb5, 0x3e, 0xaf, 0xf8, 0xa0, 0x57, 0xa5, - 0x38, 0x5f, 0x27, 0x00, 0x0c, 0xb6, 0xac, 0x62, 0x8d, 0x78, 0x6b, 0x59, - 0xe1, 0xe6, 0x95, 0x60, 0xff, 0x43, 0x5d, 0x53, 0xa6, 0x50, 0x46, 0xaa, - 0xa2, 0x1f, 0x16, 0x45, 0x78, 0x50, 0x7e, 0x7f, 0x25, 0x47, 0x33, 0x40, - 0xdb, 0xa7, 0x09, 0x20, 0x76, 0xb8, 0x44, 0xf0, 0xc3, 0xba, 0x41, 0x28, - 0x04, 0xcf, 0x1e, 0x4b, 0x00, 0xfb, 0x58, 0x18, 0x22, 0x8b, 0x87, 0x9f, - 0xa8, 0x01, 0x27, 0x9d, 0x32, 0xf8, 0x87, 0x92, 0xc0, 0x91, 0xa7, 0x1b, - 0x9a, 0x94, 0x04, 0x80, 0x23, 0xce, 0x0c, 0x7a, 0x20, 0x2f, 0xea, 0x5c, - 0x3e, 0x0a, 0x1a, 0x88, 0x34, 0x3a, 0x70, 0x7f, 0x78, 0x9f, 0x00, 0xb6, - 0x71, 0x29, 0xd5, 0x15, 0x29, 0xbb, 0x31, 0xc0, 0x16, 0x07, 0x49, 0x88, - 0x8f, 0x35, 0x03, 0x1e, 0x51, 0x02, 0x59, 0xba, 0xdf, 0xf6, 0x4f, 0x51, - 0x54, 0x2d, 0xfc, 0xbf, 0x74, 0xc7, 0x4b, 0x15, 0x4c, 0x01, 0xe4, 0xb0, - 0x29, 0x03, 0x67, 0x3c, 0xbb, 0x1b, 0xf6, 0xd9, 0xd6, 0x15, 0x1d, 0xeb, - 0x79, 0xbb, 0xe3, 0xbb, 0xc5, 0x03, 0xee, 0x16, 0xa9, 0x6d, 0x6d, 0x3f, - 0x42, 0x00, 0xfc, 0xf0, 0x0b, 0xb0, 0x15, 0x02, 0xcb, 0x43, 0x07, 0x12, - 0x5c, 0x01, 0x54, 0x19, 0x9f, 0xe2, 0x9f, 0x48, 0x3a, 0x11, 0x85, 0xf0, - 0x65, 0x24, 0x01, 0xcd, 0xbb, 0x63, 0x00, 0x8d, 0xca, 0x44, 0x01, 0x24, - 0x69, 0x61, 0x96, 0xe7, 0xa9, 0xec, 0x66, 0x40, 0xc5, 0x72, 0x50, 0x86, - 0x18, 0x66, 0x19, 0x23, 0x14, 0x68, 0x0f, 0xec, 0x27, 0x79, 0xab, 0xa0, - 0x09, 0xa3, 0xb7, 0xdb, 0xd5, 0x92, 0x92, 0x2d, 0xc8, 0x87, 0xf0, 0x75, - 0x05, 0x4f, 0xa0, 0xd9, 0x8b, 0x8a, 0xc0, 0xa0, 0xfd, 0xdf, 0x20, 0x30, - 0x14, 0x85, 0x86, 0xab, 0x53, 0xf0, 0x0a, 0x00, 0x46, 0xae, 0x28, 0x62, - 0x55, 0x44, 0x0e, 0xa2, 0x34, 0xdd, 0x2c, 0x1e, 0x66, 0x02, 0x6c, 0x5b, - 0xdb, 0x27, 0x25, 0x20, 0x59, 0xde, 0xb9, 0xf0, 0xc7, 0xc3, 0x09, 0xe0, - 0x80, 0x48, 0x90, 0xe3, 0x95, 0x08, 0xad, 0x90, 0x87, 0xba, 0xa8, 0x10, - 0xc0, 0xa2, 0x9a, 0x68, 0x3c, 0xa2, 0xf4, 0xf0, 0x87, 0x5d, 0xbb, 0xa8, - 0x00, 0x5c, 0xd4, 0x59, 0x57, 0x00, 0x58, 0x56, 0x00, 0x04, 0x97, 0xd2, - 0x03, 0x3c, 0xef, 0xe5, 0x1f, 0x50, 0x34, 0x50, 0x67, 0xfd, 0x15, 0x97, - 0x8a, 0x64, 0x5d, 0xef, 0x46, 0x08, 0xa7, 0x1d, 0xd7, 0x28, 0x01, 0x78, - 0x6e, 0xee, 0x59, 0x7c, 0xa8, 0x7c, 0x74, 0x89, 0xc0, 0xea, 0xdc, 0xff, - 0xcc, 0x7f, 0xce, 0x1e, 0xea, 0xac, 0x3f, 0xc2, 0x2b, 0x80, 0x83, 0xe0, - 0xf6, 0xea, 0x64, 0x42, 0x9c, 0xbc, 0x99, 0x52, 0xa6, 0x0b, 0x5d, 0x01, - 0xb4, 0x3d, 0x8b, 0x00, 0xfe, 0x5e, 0x15, 0x52, 0xc5, 0x19, 0xc0, 0x75, - 0xde, 0x58, 0xe6, 0xb6, 0x98, 0x68, 0xe0, 0x30, 0x11, 0xc8, 0x73, 0x4f, - 0xbf, 0x16, 0x33, 0xe8, 0xa9, 0xb6, 0xd7, 0xef, 0xef, 0x01, 0x20, 0xef, - 0x01, 0xcc, 0x7b, 0xb0, 0xaa, 0x65, 0x46, 0x00, 0x88, 0x89, 0xee, 0x1f, - 0x67, 0xb0, 0xb4, 0x90, 0x9b, 0xd2, 0x1e, 0x09, 0xfb, 0x7f, 0x80, 0xe6, - 0x99, 0x60, 0x15, 0x29, 0x21, 0x19, 0xc2, 0x64, 0x49, 0x60, 0x3e, 0xda, - 0x15, 0x01, 0xd4, 0x27, 0xee, 0xb6, 0x15, 0x7d, 0x9e, 0x4c, 0x62, 0xb9, - 0xaf, 0x86, 0xde, 0x02, 0x68, 0xfb, 0xa3, 0x04, 0x30, 0x79, 0x23, 0xe8, - 0xd9, 0xc5, 0x69, 0x92, 0x80, 0xb8, 0xaa, 0x07, 0x8a, 0x27, 0xec, 0x04, - 0x02, 0x00, 0xcf, 0x0d, 0x91, 0xde, 0xf3, 0x21, 0x11, 0x29, 0x24, 0xdd, - 0xf4, 0x17, 0x67, 0x12, 0x8e, 0x5a, 0x4a, 0x0d, 0xa0, 0x90, 0x68, 0xe4, - 0x2d, 0xa0, 0x94, 0x65, 0xf3, 0x5d, 0x38, 0xd7, 0x2e, 0xde, 0x02, 0x22, - 0x55, 0x1b, 0x33, 0xc1, 0x8a, 0x77, 0x35, 0x18, 0xa0, 0xa7, 0x6f, 0x01, - 0x25, 0xb9, 0x8c, 0x24, 0x2c, 0x11, 0xc1, 0x52, 0x64, 0xb2, 0xff, 0xcc, - 0x9d, 0x53, 0xff, 0x19, 0x2b, 0x35, 0xfe, 0xbe, 0x2b, 0x13, 0xfa, 0x06, - 0x14, 0x84, 0xd0, 0xa7, 0x4b, 0xb7, 0x5a, 0xe7, 0xa5, 0x50, 0xbf, 0x68, - 0x39, 0x79, 0xd0, 0xe0, 0x79, 0x05, 0x30, 0x5b, 0x2d, 0x79, 0x05, 0xb6, - 0xb5, 0x7d, 0x02, 0x37, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xfe, 0x27, 0xfb, - 0x05, 0x36, 0xf6, 0x29, 0xcf, 0xfc, 0x99, 0x25, 0xd1, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 - }; +unsigned char FONT_PNG_DATA[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, + 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x08, + 0x08, 0x03, 0x00, 0x00, 0x00, 0x08, 0xb3, 0xc4, 0x0e, 0x00, 0x00, 0x00, + 0x06, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa5, + 0xd9, 0x9f, 0xdd, 0x00, 0x00, 0x03, 0x12, 0x49, 0x44, 0x41, 0x54, 0x68, + 0xde, 0xed, 0x5a, 0x81, 0x76, 0x9c, 0x30, 0x0c, 0x93, 0xff, 0xff, 0xa7, + 0xf7, 0xda, 0x83, 0x20, 0xc9, 0x0e, 0x81, 0x5b, 0xdf, 0x8d, 0x6d, 0xf6, + 0xbb, 0xa6, 0x94, 0xa3, 0xc1, 0x71, 0x82, 0x64, 0x2b, 0x20, 0xbe, 0x0d, + 0x5f, 0x56, 0xb4, 0xbb, 0x21, 0xb5, 0x4f, 0x33, 0xbc, 0x1a, 0x8c, 0xf6, + 0x75, 0x28, 0x2e, 0xd3, 0xaf, 0xeb, 0x83, 0xd8, 0xc2, 0x80, 0x71, 0x3c, + 0x22, 0x43, 0xc7, 0x74, 0x7e, 0x3f, 0x81, 0xda, 0x45, 0x0e, 0x24, 0x5d, + 0x39, 0x7a, 0xd6, 0x63, 0x99, 0x8b, 0x57, 0x33, 0x6e, 0xbc, 0x77, 0x41, + 0x43, 0xa6, 0x63, 0x4c, 0xfb, 0x0c, 0x9e, 0x65, 0x0b, 0x9a, 0xb5, 0x34, + 0xba, 0x11, 0x8d, 0xb4, 0x06, 0x50, 0x1c, 0xa5, 0x6f, 0xe0, 0xe7, 0xd2, + 0x5c, 0x00, 0xef, 0xcc, 0xf8, 0xd5, 0x39, 0xd4, 0xf5, 0x90, 0xbe, 0xe3, + 0x5e, 0xd5, 0x55, 0x70, 0x2b, 0x0b, 0x02, 0xd5, 0x14, 0xfe, 0xdc, 0x7a, + 0x7e, 0xe6, 0x63, 0xd6, 0xf6, 0x8f, 0x19, 0x94, 0x00, 0xfc, 0x23, 0x20, + 0x88, 0x27, 0x33, 0x40, 0x22, 0x80, 0x7d, 0x44, 0xdf, 0x7f, 0x62, 0x42, + 0x63, 0xab, 0x01, 0x11, 0x98, 0x32, 0x5a, 0x0d, 0x04, 0x80, 0x61, 0x11, + 0x1c, 0x82, 0x4f, 0x40, 0x73, 0x01, 0xbe, 0x29, 0xe0, 0xd2, 0x33, 0xdd, + 0x79, 0x7c, 0x5e, 0xb7, 0xc2, 0xb5, 0x3e, 0xaf, 0xf8, 0xa0, 0x57, 0xa5, + 0x38, 0x5f, 0x27, 0x00, 0x0c, 0xb6, 0xac, 0x62, 0x8d, 0x78, 0x6b, 0x59, + 0xe1, 0xe6, 0x95, 0x60, 0xff, 0x43, 0x5d, 0x53, 0xa6, 0x50, 0x46, 0xaa, + 0xa2, 0x1f, 0x16, 0x45, 0x78, 0x50, 0x7e, 0x7f, 0x25, 0x47, 0x33, 0x40, + 0xdb, 0xa7, 0x09, 0x20, 0x76, 0xb8, 0x44, 0xf0, 0xc3, 0xba, 0x41, 0x28, + 0x04, 0xcf, 0x1e, 0x4b, 0x00, 0xfb, 0x58, 0x18, 0x22, 0x8b, 0x87, 0x9f, + 0xa8, 0x01, 0x27, 0x9d, 0x32, 0xf8, 0x87, 0x92, 0xc0, 0x91, 0xa7, 0x1b, + 0x9a, 0x94, 0x04, 0x80, 0x23, 0xce, 0x0c, 0x7a, 0x20, 0x2f, 0xea, 0x5c, + 0x3e, 0x0a, 0x1a, 0x88, 0x34, 0x3a, 0x70, 0x7f, 0x78, 0x9f, 0x00, 0xb6, + 0x71, 0x29, 0xd5, 0x15, 0x29, 0xbb, 0x31, 0xc0, 0x16, 0x07, 0x49, 0x88, + 0x8f, 0x35, 0x03, 0x1e, 0x51, 0x02, 0x59, 0xba, 0xdf, 0xf6, 0x4f, 0x51, + 0x54, 0x2d, 0xfc, 0xbf, 0x74, 0xc7, 0x4b, 0x15, 0x4c, 0x01, 0xe4, 0xb0, + 0x29, 0x03, 0x67, 0x3c, 0xbb, 0x1b, 0xf6, 0xd9, 0xd6, 0x15, 0x1d, 0xeb, + 0x79, 0xbb, 0xe3, 0xbb, 0xc5, 0x03, 0xee, 0x16, 0xa9, 0x6d, 0x6d, 0x3f, + 0x42, 0x00, 0xfc, 0xf0, 0x0b, 0xb0, 0x15, 0x02, 0xcb, 0x43, 0x07, 0x12, + 0x5c, 0x01, 0x54, 0x19, 0x9f, 0xe2, 0x9f, 0x48, 0x3a, 0x11, 0x85, 0xf0, + 0x65, 0x24, 0x01, 0xcd, 0xbb, 0x63, 0x00, 0x8d, 0xca, 0x44, 0x01, 0x24, + 0x69, 0x61, 0x96, 0xe7, 0xa9, 0xec, 0x66, 0x40, 0xc5, 0x72, 0x50, 0x86, + 0x18, 0x66, 0x19, 0x23, 0x14, 0x68, 0x0f, 0xec, 0x27, 0x79, 0xab, 0xa0, + 0x09, 0xa3, 0xb7, 0xdb, 0xd5, 0x92, 0x92, 0x2d, 0xc8, 0x87, 0xf0, 0x75, + 0x05, 0x4f, 0xa0, 0xd9, 0x8b, 0x8a, 0xc0, 0xa0, 0xfd, 0xdf, 0x20, 0x30, + 0x14, 0x85, 0x86, 0xab, 0x53, 0xf0, 0x0a, 0x00, 0x46, 0xae, 0x28, 0x62, + 0x55, 0x44, 0x0e, 0xa2, 0x34, 0xdd, 0x2c, 0x1e, 0x66, 0x02, 0x6c, 0x5b, + 0xdb, 0x27, 0x25, 0x20, 0x59, 0xde, 0xb9, 0xf0, 0xc7, 0xc3, 0x09, 0xe0, + 0x80, 0x48, 0x90, 0xe3, 0x95, 0x08, 0xad, 0x90, 0x87, 0xba, 0xa8, 0x10, + 0xc0, 0xa2, 0x9a, 0x68, 0x3c, 0xa2, 0xf4, 0xf0, 0x87, 0x5d, 0xbb, 0xa8, + 0x00, 0x5c, 0xd4, 0x59, 0x57, 0x00, 0x58, 0x56, 0x00, 0x04, 0x97, 0xd2, + 0x03, 0x3c, 0xef, 0xe5, 0x1f, 0x50, 0x34, 0x50, 0x67, 0xfd, 0x15, 0x97, + 0x8a, 0x64, 0x5d, 0xef, 0x46, 0x08, 0xa7, 0x1d, 0xd7, 0x28, 0x01, 0x78, + 0x6e, 0xee, 0x59, 0x7c, 0xa8, 0x7c, 0x74, 0x89, 0xc0, 0xea, 0xdc, 0xff, + 0xcc, 0x7f, 0xce, 0x1e, 0xea, 0xac, 0x3f, 0xc2, 0x2b, 0x80, 0x83, 0xe0, + 0xf6, 0xea, 0x64, 0x42, 0x9c, 0xbc, 0x99, 0x52, 0xa6, 0x0b, 0x5d, 0x01, + 0xb4, 0x3d, 0x8b, 0x00, 0xfe, 0x5e, 0x15, 0x52, 0xc5, 0x19, 0xc0, 0x75, + 0xde, 0x58, 0xe6, 0xb6, 0x98, 0x68, 0xe0, 0x30, 0x11, 0xc8, 0x73, 0x4f, + 0xbf, 0x16, 0x33, 0xe8, 0xa9, 0xb6, 0xd7, 0xef, 0xef, 0x01, 0x20, 0xef, + 0x01, 0xcc, 0x7b, 0xb0, 0xaa, 0x65, 0x46, 0x00, 0x88, 0x89, 0xee, 0x1f, + 0x67, 0xb0, 0xb4, 0x90, 0x9b, 0xd2, 0x1e, 0x09, 0xfb, 0x7f, 0x80, 0xe6, + 0x99, 0x60, 0x15, 0x29, 0x21, 0x19, 0xc2, 0x64, 0x49, 0x60, 0x3e, 0xda, + 0x15, 0x01, 0xd4, 0x27, 0xee, 0xb6, 0x15, 0x7d, 0x9e, 0x4c, 0x62, 0xb9, + 0xaf, 0x86, 0xde, 0x02, 0x68, 0xfb, 0xa3, 0x04, 0x30, 0x79, 0x23, 0xe8, + 0xd9, 0xc5, 0x69, 0x92, 0x80, 0xb8, 0xaa, 0x07, 0x8a, 0x27, 0xec, 0x04, + 0x02, 0x00, 0xcf, 0x0d, 0x91, 0xde, 0xf3, 0x21, 0x11, 0x29, 0x24, 0xdd, + 0xf4, 0x17, 0x67, 0x12, 0x8e, 0x5a, 0x4a, 0x0d, 0xa0, 0x90, 0x68, 0xe4, + 0x2d, 0xa0, 0x94, 0x65, 0xf3, 0x5d, 0x38, 0xd7, 0x2e, 0xde, 0x02, 0x22, + 0x55, 0x1b, 0x33, 0xc1, 0x8a, 0x77, 0x35, 0x18, 0xa0, 0xa7, 0x6f, 0x01, + 0x25, 0xb9, 0x8c, 0x24, 0x2c, 0x11, 0xc1, 0x52, 0x64, 0xb2, 0xff, 0xcc, + 0x9d, 0x53, 0xff, 0x19, 0x2b, 0x35, 0xfe, 0xbe, 0x2b, 0x13, 0xfa, 0x06, + 0x14, 0x84, 0xd0, 0xa7, 0x4b, 0xb7, 0x5a, 0xe7, 0xa5, 0x50, 0xbf, 0x68, + 0x39, 0x79, 0xd0, 0xe0, 0x79, 0x05, 0x30, 0x5b, 0x2d, 0x79, 0x05, 0xb6, + 0xb5, 0x7d, 0x02, 0x37, 0xdb, 0xda, 0xda, 0xda, 0xda, 0xfe, 0x27, 0xfb, + 0x05, 0x36, 0xf6, 0x29, 0xcf, 0xfc, 0x99, 0x25, 0xd1, 0x00, 0x00, 0x00, + 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; diff --git a/src/font.h b/src/font.h index f735adf..26feda8 100644 --- a/src/font.h +++ b/src/font.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,12 +21,12 @@ #include int -font_init (void); +font_init(void); void -font_free (void); +font_free(void); SDL_Surface * -get_font_char (int c); +get_font_char(int c); #endif diff --git a/src/keys.c b/src/keys.c index b87a295..0b5e7d8 100644 --- a/src/keys.c +++ b/src/keys.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -18,113 +18,113 @@ #include "keys.h" #include "tibchar.h" -static const SDL_Keycode UNCHANGED_RANGES[] = - { - SDLK_0, SDLK_9 - }; +static const SDL_Keycode UNCHANGED_RANGES[] = { + SDLK_0, SDLK_9 +}; -static const SDL_Keycode UNCHANGED[] = - { - SDLK_PERIOD, - SDLK_MINUS, - SDLK_SLASH, +static const SDL_Keycode UNCHANGED[] = { + SDLK_PERIOD, + SDLK_MINUS, + SDLK_SLASH, - SDLK_e, - SDLK_i - }; + SDLK_e, + SDLK_i +}; int -normalize_keycode (SDL_Keycode code, SDL_Keymod mod) +normalize_keycode(SDL_Keycode code, SDL_Keymod mod) { - if (mod & KMOD_CTRL) - { - switch (code) - { - case SDLK_a: - return TIB_CHAR_ANS; - - case SDLK_d: - return TIB_CHAR_DEGREE; - - case SDLK_e: - return TIB_CHAR_EPOW10; - - case SDLK_p: - return TIB_CHAR_PI; - } - } - else if (mod & KMOD_SHIFT) - { - switch (code) - { - case SDLK_EQUALS: - return '+'; - - case SDLK_1: - return '!'; - - case SDLK_4: - return TIB_CHAR_STO; - - case SDLK_6: - return '^'; - - case SDLK_8: - return '*'; - - case SDLK_9: - return '('; - - case SDLK_0: - return ')'; - } - } - else - { - switch (code) - { - case SDLK_KP_0: - return '0'; - - case SDLK_KP_PERIOD: - return '.'; - - case SDLK_KP_PLUS: - return '+'; - - case SDLK_KP_MINUS: - return '-'; - - case SDLK_KP_MULTIPLY: - return '*'; - - case SDLK_KP_DIVIDE: - return '/'; - - case SDLK_c: - return TIB_CHAR_COS; - - case SDLK_s: - return TIB_CHAR_SIN; - - case SDLK_t: - return TIB_CHAR_TAN; - } - } - - for (unsigned int i = 0; i < (sizeof UNCHANGED_RANGES / sizeof (int)); ++i) - if (code >= UNCHANGED_RANGES[i++] && code <= UNCHANGED_RANGES[i]) - return code; - - for (unsigned int i = 0; i < (sizeof UNCHANGED / sizeof (int)); ++i) - if (code == UNCHANGED[i]) - return code; - - if (code >= SDLK_KP_1 && code <= SDLK_KP_9) - return code - SDLK_KP_1 + '1'; - - if (code >= SDLK_a && code <= SDLK_z) - return code - SDLK_a + 'A'; - - return 0; + if (mod & KMOD_CTRL) + { + switch (code) + { + case SDLK_a: + return TIB_CHAR_ANS; + + case SDLK_d: + return TIB_CHAR_DEGREE; + + case SDLK_e: + return TIB_CHAR_EPOW10; + + case SDLK_p: + return TIB_CHAR_PI; + } + } + else if (mod & KMOD_SHIFT) + { + switch (code) + { + case SDLK_EQUALS: + return '+'; + + case SDLK_1: + return '!'; + + case SDLK_4: + return TIB_CHAR_STO; + + case SDLK_6: + return '^'; + + case SDLK_8: + return '*'; + + case SDLK_9: + return '('; + + case SDLK_0: + return ')'; + } + } + else + { + switch (code) + { + case SDLK_KP_0: + return '0'; + + case SDLK_KP_PERIOD: + return '.'; + + case SDLK_KP_PLUS: + return '+'; + + case SDLK_KP_MINUS: + return '-'; + + case SDLK_KP_MULTIPLY: + return '*'; + + case SDLK_KP_DIVIDE: + return '/'; + + case SDLK_c: + return TIB_CHAR_COS; + + case SDLK_s: + return TIB_CHAR_SIN; + + case SDLK_t: + return TIB_CHAR_TAN; + } + } + + for (unsigned int i = 0; i < (sizeof UNCHANGED_RANGES / sizeof(int)); + ++i) + if (code >= UNCHANGED_RANGES[i++] + && code <= UNCHANGED_RANGES[i]) + return code; + + for (unsigned int i = 0; i < (sizeof UNCHANGED / sizeof(int)); ++i) + if (code == UNCHANGED[i]) + return code; + + if (code >= SDLK_KP_1 && code <= SDLK_KP_9) + return code - SDLK_KP_1 + '1'; + + if (code >= SDLK_a && code <= SDLK_z) + return code - SDLK_a + 'A'; + + return 0; } diff --git a/src/keys.h b/src/keys.h index 63e3e44..256dd85 100644 --- a/src/keys.h +++ b/src/keys.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,6 +21,6 @@ #include int -normalize_keycode (SDL_Keycode code, SDL_Keymod mod); +normalize_keycode(SDL_Keycode code, SDL_Keymod mod); #endif diff --git a/src/liberti.c b/src/liberti.c index 89ea691..2bcc175 100644 --- a/src/liberti.c +++ b/src/liberti.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -23,7 +23,6 @@ #include #include #include -#include #include #include "font.h" @@ -33,342 +32,338 @@ #include "tibfunction.h" #include "tibvar.h" -#ifdef HAVE_CONFIG_H -# include "config.h" -# define VERSION_STRING PACKAGE_VERSION -# define PROG PACKAGE -#else -# define VERSION_STRING "custom build" -# define PROG "liberti" -#endif +#define VERSION_STRING "0.0.0" +#define PROG "liberti" #define USAGE_INFO "USAGE: " PROG " [options]\n\n\ OPTIONS:\n\ -\t-d, --debug\tPrints extra activity while running\n\ -\t-h, --help\tPrints this help message and exits\n\ -\t-v, --version\tPrints version info and exits\n" +\t-d\tPrints extra activity while running\n\ +\t-h\tPrints this help message and exits\n\ +\t-v\tPrints version info and exits\n" #define VERSION_INFO "LiberTI " VERSION_STRING "\n\ -Copyright (C) 2015-2016 Delwink, LLC\n\ +Copyright (C) 2015-2017 Delwink, LLC\n\ License AGPLv3: GNU AGPL version 3 only .\n\ This is libre software: you are free to change and redistribute it.\n\ There is NO WARRANTY, to the extent permitted by law.\n\n\ Written by David McMackins II." #ifdef RUN_IN_PLACE -# define USER_DIR "." +#define USER_DIR "." #else -# define USER_DIR "~/.liberti" +#define USER_DIR "~/.liberti" #endif #define USER_STATE_PATH "state.conf" static Uint32 -timer (Uint32 interval, void *data) +timer(Uint32 interval, void *data) { - SDL_Event event; - SDL_UserEvent user; + SDL_Event event; + SDL_UserEvent user; - user.type = SDL_USEREVENT; - user.code = 0; - user.data1 = data; + user.type = SDL_USEREVENT; + user.code = 0; + user.data1 = data; - event.type = SDL_USEREVENT; - event.user = user; + event.type = SDL_USEREVENT; + event.user = user; - SDL_PushEvent (&event); - return interval; + SDL_PushEvent(&event); + return interval; } static char * -get_conf_path (const char *path) +get_conf_path(const char *path) { - wordexp_t w; - int rc = wordexp (USER_DIR, &w, 0); - if (rc) - return NULL; - - size_t len = strlen (w.we_wordv[0]) + strlen (path) + 2; - char *out = malloc (len * sizeof (char)); - if (out) - snprintf (out, len, "%s/%s", w.we_wordv[0], path); - - wordfree (&w); - return out; + wordexp_t w; + int rc = wordexp(USER_DIR, &w, 0); + if (rc) + return NULL; + + size_t len = strlen(w.we_wordv[0]) + strlen(path) + 2; + char *out = malloc(len * sizeof(char)); + if (out) + snprintf(out, len, "%s/%s", w.we_wordv[0], path); + + wordfree(&w); + return out; } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - bool user_dir_exists = false, state_file_exists = false, state_init = false; - int rc = 0; - SDL_TimerID timer_id = 0; - SDL_Window *window = NULL; - Skin *skin = NULL; - - char *skin_path = NULL, *state_path = NULL; - Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; - - struct option longopts[] = - { - {"debug", no_argument, 0, 'd'}, - {"fullscreen", no_argument, 0, 'f'}, - {"help", no_argument, 0, 'h'}, - {"skin", required_argument, 0, 's'}, - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - - if (argc > 1) - { - int c; - int longindex; - while ((c = getopt_long (argc, argv, "dfhs:v", longopts, &longindex)) - != -1) - { - switch (c) - { - case 'd': - debug_mode = true; - break; - - case 'f': - window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - break; - - case 'h': - puts (USAGE_INFO); - return 0; - - case 's': - skin_path = optarg; - break; - - case 'v': - puts (VERSION_INFO); - return 0; - - case '?': - return 1; - } - } - } - - gsl_set_error_handler_off (); - - rc = SDL_Init (SDL_INIT_TIMER); - if (rc) - { - critical ("Could not initialize SDL timer: %s", SDL_GetError ()); - goto end; - } - - rc = SDL_VideoInit (NULL); - if (rc) - { - critical ("Could not initialize SDL video: %s", SDL_GetError ()); - goto end; - } - - rc = IMG_Init (IMG_INIT_PNG); - if (rc != IMG_INIT_PNG) - { - critical ("Could not initialize PNG image library: %s", IMG_GetError ()); - rc = 1; - goto end; - } - - rc = font_init (); - if (rc) - goto end; - - rc = tib_keyword_init (); - if (rc) - { - critical ("Could not initialize TI-BASIC keyword lookup tree: Error %d", - rc); - goto end; - } - - rc = tib_var_init (); - if (rc) - { - critical ("Could not initialize default variables: Error %d", rc); - goto end; - } - - rc = tib_registry_init (); - if (rc) - { - critical ("Could not initialize function registry: Error %d", rc); - goto end; - } - - SDL_DisplayMode display_mode; - rc = SDL_GetCurrentDisplayMode (0, &display_mode); - if (rc) - { - critical ("Could not get screen information: %s", SDL_GetError ()); - goto end; - } - - debug ("Screen resolution: %dx%d", display_mode.w, display_mode.h); - - { - char *user_dir_path = get_conf_path (""); - if (user_dir_path) - { - rc = mkdir (user_dir_path, 0755); - free (user_dir_path); - if (rc && EEXIST != errno) - { - warn ("Failed to create config directory: %s", strerror (errno)); - } - else - { - user_dir_exists = true; - - state_path = get_conf_path (USER_STATE_PATH); - if (state_path) - { - rc = access (state_path, F_OK); - if (rc) - { - debug ("Can't open state file: %s", strerror (errno)); - info ("Loading empty state"); - } - else - { - state_file_exists = true; - info ("Loading state from %s", state_path); - } - } - } - } - else - { - warn ("Could not determine config path"); - } - } - - struct state state; - rc = load_state (&state, state_file_exists ? state_path : NULL); - if (rc) - { - critical ("Could not initialize calculator state. Error %d", rc); - goto end; - } - - state_init = true; - - timer_id = SDL_AddTimer (500, timer, &state); - if (!timer_id) - { - critical ("Could not add blink timer: %s", SDL_GetError ()); - goto end; - } - - skin = open_skin (skin_path, &state, (struct point2d) { 96, 64 }); - if (!skin) - { - critical ("Could not load skin"); - goto end; - } - - window = SDL_CreateWindow ("LiberTI " VERSION_STRING, - SDL_WINDOWPOS_UNDEFINED, - SDL_WINDOWPOS_UNDEFINED, - skin->size.x, - skin->size.y, - window_flags); - if (!window) - { - critical ("Could not create window: %s", SDL_GetError ()); - goto end; - } - - for (;;) - { - SDL_Surface *frame = Skin_get_frame (skin); - if (frame) - { - SDL_Surface *screen = SDL_GetWindowSurface (window); - SDL_BlitScaled (frame, NULL, screen, NULL); - SDL_FreeSurface (frame); - SDL_UpdateWindowSurface (window); - } - - SDL_Event event; - SDL_WaitEvent (NULL); - - while (SDL_PollEvent (&event)) - { - switch (event.type) - { - case SDL_KEYDOWN: - rc = Skin_input (skin, &event.key); - if (rc) - error ("Error %d processing key entry", rc); - break; - - case SDL_USEREVENT: - switch (event.user.code) - { - case 0: - { - struct state *state = event.user.data1; - state->blink_state = !state->blink_state; - } - break; - - default: - break; - } - break; - - case SDL_QUIT: - info ("Got SDL quit event"); - goto end; - - default: - break; - } - } - } + bool user_dir_exists = false, state_file_exists = false; + bool state_init = false; + int rc = 0; + SDL_TimerID timer_id = 0; + SDL_Window *window = NULL; + Skin *skin = NULL; + + char *skin_path = NULL, *state_path = NULL; + Uint32 window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; + + if (argc > 1) + { + int c; + while ((c = getopt(argc, argv, ":dfhs:v")) != -1) + { + switch (c) + { + case 'd': + debug_mode = true; + break; + + case 'f': + window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; + break; + + case 'h': + puts(USAGE_INFO); + return 0; + + case 's': + skin_path = optarg; + break; + + case 'v': + puts(VERSION_INFO); + return 0; + + case ':': + fprintf(stderr, + PROG ": option -%c requires an argument\n", + optopt); + // SPILLS OVER! + + case '?': + return 1; + } + } + } + + gsl_set_error_handler_off(); + + rc = SDL_Init(SDL_INIT_TIMER); + if (rc) + { + critical("Could not initialize SDL timer: %s", SDL_GetError()); + goto end; + } + + rc = SDL_VideoInit(NULL); + if (rc) + { + critical("Could not initialize SDL video: %s", SDL_GetError()); + goto end; + } + + rc = IMG_Init(IMG_INIT_PNG); + if (rc != IMG_INIT_PNG) + { + critical("Could not initialize PNG image library: %s", + IMG_GetError()); + rc = 1; + goto end; + } + + rc = font_init(); + if (rc) + goto end; + + rc = tib_keyword_init(); + if (rc) + { + critical("Could not initialize TI-BASIC keyword lookup tree: Error %d", + rc); + goto end; + } + + rc = tib_var_init(); + if (rc) + { + critical("Could not initialize default variables: Error %d", + rc); + goto end; + } + + rc = tib_registry_init(); + if (rc) + { + critical("Could not initialize function registry: Error %d", + rc); + goto end; + } + + SDL_DisplayMode display_mode; + rc = SDL_GetCurrentDisplayMode(0, &display_mode); + if (rc) + { + critical("Could not get screen information: %s", + SDL_GetError()); + goto end; + } + + debug("Screen resolution: %dx%d", display_mode.w, display_mode.h); + + char *user_dir_path = get_conf_path(""); + if (user_dir_path) + { + rc = mkdir(user_dir_path, 0755); + free(user_dir_path); + if (rc && EEXIST != errno) + { + warn("Failed to create config directory: %s", + strerror(errno)); + } + else + { + user_dir_exists = true; + + state_path = get_conf_path(USER_STATE_PATH); + if (state_path) + { + rc = access(state_path, F_OK); + if (rc) + { + debug("Can't open state file: %s", + strerror(errno)); + info("Loading empty state"); + } + else + { + state_file_exists = true; + info("Loading state from %s", + state_path); + } + } + } + } + else + { + warn("Could not determine config path"); + } + + struct state state; + rc = load_state(&state, state_file_exists ? state_path : NULL); + if (rc) + { + critical("Could not initialize calculator state. Error %d", + rc); + goto end; + } + + state_init = true; + + timer_id = SDL_AddTimer(500, timer, &state); + if (!timer_id) + { + critical("Could not add blink timer: %s", SDL_GetError()); + goto end; + } + + skin = open_skin(skin_path, &state, (struct point2d) { 96, 64 }); + if (!skin) + { + critical("Could not load skin"); + goto end; + } + + window = SDL_CreateWindow("LiberTI " VERSION_STRING, + SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, + skin->size.x, skin->size.y, window_flags); + if (!window) + { + critical("Could not create window: %s", SDL_GetError()); + goto end; + } + + for (;;) + { + SDL_Surface *frame = Skin_get_frame(skin); + if (frame) + { + SDL_Surface *screen = SDL_GetWindowSurface(window); + SDL_BlitScaled(frame, NULL, screen, NULL); + SDL_FreeSurface(frame); + SDL_UpdateWindowSurface(window); + } + + SDL_Event event; + SDL_WaitEvent(NULL); + + while (SDL_PollEvent(&event)) + { + switch (event.type) + { + case SDL_KEYDOWN: + rc = Skin_input(skin, &event.key); + if (rc) + error("Error %d processing key entry", + rc); + break; + + case SDL_USEREVENT: + switch (event.user.code) + { + case 0: + { + struct state *state = + event.user.data1; + state->blink_state = + !state->blink_state; + } + break; + + default: + break; + } + break; + + case SDL_QUIT: + info("Got SDL quit event"); + goto end; + + default: + break; + } + } + } end: - if (timer_id) - SDL_RemoveTimer (timer_id); + if (timer_id) + SDL_RemoveTimer(timer_id); - SDL_Quit (); - SDL_VideoQuit (); - IMG_Quit (); + SDL_Quit(); + SDL_VideoQuit(); + IMG_Quit(); - font_free (); - tib_keyword_free (); - tib_registry_free (); - tib_var_free (); + font_free(); + tib_keyword_free(); + tib_registry_free(); + tib_var_free(); - if (state_init) - { - if (user_dir_exists && state_path) - { - errno = save_state (&state, state_path); - if (errno) - warn ("Failed to save state"); - } + if (state_init) + { + if (user_dir_exists && state_path) + { + errno = save_state(&state, state_path); + if (errno) + warn("Failed to save state"); + } - state_destroy (&state); - } + state_destroy(&state); + } - if (state_path) - free (state_path); + if (state_path) + free(state_path); - if (skin) - free_skin (skin); + if (skin) + free_skin(skin); - if (window) - SDL_DestroyWindow (window); + if (window) + SDL_DestroyWindow(window); - return !!rc; + return !!rc; } diff --git a/src/log.c b/src/log.c index cf7c6ed..168ac31 100644 --- a/src/log.c +++ b/src/log.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -23,46 +23,46 @@ bool debug_mode = false; -#define log(FMT,FILE,PRE) \ - { \ - fputs (PRE, FILE); \ - va_list ap; \ - va_start (ap, FMT); \ - int n = vfprintf (FILE, FMT, ap); \ - va_end (ap); \ - fputc ('\n', FILE); \ - return n; \ - } +#define log(FMT,FILE,PRE) \ + { \ + fputs(PRE, FILE); \ + va_list ap; \ + va_start(ap, FMT); \ + int n = vfprintf(FILE, FMT, ap); \ + va_end(ap); \ + fputc('\n', FILE); \ + return n; \ + } int -info (const char *fmt, ...) +info(const char *fmt, ...) { - log (fmt, stdout, "[info]: "); + log(fmt, stdout, "[info]: "); } int -warn (const char *fmt, ...) +warn(const char *fmt, ...) { - log (fmt, stdout, "[warn]: "); + log(fmt, stdout, "[warn]: "); } int -error (const char *fmt, ...) +error(const char *fmt, ...) { - log (fmt, stderr, "[error]: "); + log(fmt, stderr, "[error]: "); } int -critical (const char *fmt, ...) +critical(const char *fmt, ...) { - log (fmt, stderr, "[critical]: "); + log(fmt, stderr, "[critical]: "); } int -debug (const char *fmt, ...) +debug(const char *fmt, ...) { - if (!debug_mode) - return 0; + if (!debug_mode) + return 0; - log (fmt, stdout, "[debug]: "); + log(fmt, stdout, "[debug]: "); } diff --git a/src/log.h b/src/log.h index 4bbe807..789c0f5 100644 --- a/src/log.h +++ b/src/log.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2015 Delwink, LLC + * Copyright (C) 2015, 2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -23,18 +23,18 @@ extern bool debug_mode; int -info (const char *fmt, ...); +info(const char *fmt, ...); int -warn (const char *fmt, ...); +warn(const char *fmt, ...); int -error (const char *fmt, ...); +error(const char *fmt, ...); int -critical (const char *fmt, ...); +critical(const char *fmt, ...); int -debug (const char *fmt, ...); +debug(const char *fmt, ...); #endif diff --git a/src/mode_default.c b/src/mode_default.c index fe47654..76b3319 100644 --- a/src/mode_default.c +++ b/src/mode_default.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -28,266 +28,275 @@ #include "util.h" static SDL_Surface * -render_line (const struct tib_expr *line, unsigned int *width) +render_line(const struct tib_expr *line, unsigned int *width) { - int rc; - char *s = get_expr_display_str (line); - if (!s) - { - error ("Error converting expression to string"); - return NULL; - } - - unsigned int len = strlen (s); - SDL_Surface *parts[len + 1]; - parts[len] = get_font_char (' '); - - SDL_Rect pos; - pos.x = 0; - pos.y = 8; - - for (unsigned int i = 0; i < len; ++i) - { - SDL_Surface *part = get_font_char ((unsigned char) s[i]); - - pos.x += 6; - if (pos.x >= 96) - { - pos.y += 8; - pos.x = 6; - } - - parts[i] = part; - } - - SDL_Surface *final = SDL_CreateRGBSurface (0, 96, pos.y, 32, 0, 0, 0, 0); - if (!final) - { - error ("Failed to initialize expression render surface: %s", - SDL_GetError ()); - goto end; - } - - SDL_LockSurface (final); - - rc = SDL_FillRect (final, NULL, SDL_MapRGB (final->format, 255, 255, 255)); - if (rc < 0) - error ("Failed to set background of expression render surface: %s", - SDL_GetError ()); - - SDL_UnlockSurface (final); - - pos.x = 0; - pos.y = 0; - for (unsigned int i = 0; i <= len; ++i) - { - if (pos.x + 6 > 96) - { - pos.x = 0; - pos.y += 8; - } - - rc = SDL_BlitSurface (parts[i], NULL, final, &pos); - if (rc < 0) - { - error ("Failed to blit expression portion: %s", SDL_GetError ()); - continue; - } - - pos.x += 6; - } - - *width = min (16, len) * 6; + int rc; + char *s = get_expr_display_str(line); + if (!s) + { + error("Error converting expression to string"); + return NULL; + } + + unsigned int len = strlen(s); + SDL_Surface *parts[len + 1]; + parts[len] = get_font_char(' '); + + SDL_Rect pos; + pos.x = 0; + pos.y = 8; + + for (unsigned int i = 0; i < len; ++i) + { + SDL_Surface *part = get_font_char((unsigned char) s[i]); + + pos.x += 6; + if (pos.x >= 96) + { + pos.y += 8; + pos.x = 6; + } + + parts[i] = part; + } + + SDL_Surface *final = SDL_CreateRGBSurface(0, 96, pos.y, 32, 0, 0, 0, + 0); + if (!final) + { + error("Failed to initialize expression render surface: %s", + SDL_GetError()); + goto end; + } + + SDL_LockSurface(final); + + rc = SDL_FillRect(final, NULL, + SDL_MapRGB(final->format, 255, 255, 255)); + if (rc < 0) + error("Failed to set background of expression render surface: %s", + SDL_GetError()); + + SDL_UnlockSurface(final); + + pos.x = 0; + pos.y = 0; + for (unsigned int i = 0; i <= len; ++i) + { + if (pos.x + 6 > 96) + { + pos.x = 0; + pos.y += 8; + } + + rc = SDL_BlitSurface(parts[i], NULL, final, &pos); + if (rc < 0) + { + error("Failed to blit expression portion: %s", + SDL_GetError()); + continue; + } + + pos.x += 6; + } + + *width = min(16, len) * 6; end: - free (s); - return final; + free(s); + return final; } static void -draw_line (const struct tib_expr *line, SDL_Surface *final, - unsigned int *height, bool right_align) +draw_line(const struct tib_expr *line, SDL_Surface *final, + unsigned int *height, bool right_align) { - unsigned int width; - - SDL_Surface *line_render = render_line (line, &width); - if (line_render) - { - SDL_Rect pos; - if (right_align) - pos.x = 96 - width; - else - pos.x = 0; - - *height += line_render->h; - pos.y = 64 - *height; - - int rc = SDL_BlitSurface (line_render, NULL, final, &pos); - if (rc < 0) - error ("Failed to draw line on screen frame: %s", SDL_GetError ()); - - SDL_FreeSurface (line_render); - } + unsigned int width; + + SDL_Surface *line_render = render_line(line, &width); + if (line_render) + { + SDL_Rect pos; + if (right_align) + pos.x = 96 - width; + else + pos.x = 0; + + *height += line_render->h; + pos.y = 64 - *height; + + int rc = SDL_BlitSurface(line_render, NULL, final, &pos); + if (rc < 0) + error("Failed to draw line on screen frame: %s", + SDL_GetError()); + + SDL_FreeSurface(line_render); + } } static void -draw_cursor (const struct state *state, SDL_Surface *frame) +draw_cursor(const struct state *state, SDL_Surface *frame) { - if (!state->blink_state) - return; - - SDL_Keymod mod = SDL_GetModState (); - int c = 1; - - if (state->insert_mode) - c += 4; - - if (STATE_2ND == state->action_state || mod & KMOD_CTRL) - ++c; - else if (STATE_ALPHA == state->action_state || mod & KMOD_SHIFT) - c += 2; - - int x = 0; - for (int i = 0; i < state->entry_cursor; ++i) - { - const char *special = display_special_char (state->entry.data[i]); - if (special) - x += strlen (special); - else - ++x; - - if (x >= 16) - x %= 16; - } - - SDL_Rect pos = { .x = (6 * x), .y = (64 - 8) }; - SDL_Surface *tile = get_font_char (c); - - int rc = SDL_BlitSurface (tile, NULL, frame, &pos); - if (rc < 0) - error ("Failed to draw cursor on screen frame: %s", SDL_GetError ()); + if (!state->blink_state) + return; + + SDL_Keymod mod = SDL_GetModState(); + int c = 1; + + if (state->insert_mode) + c += 4; + + if (STATE_2ND == state->action_state || mod & KMOD_CTRL) + ++c; + else if (STATE_ALPHA == state->action_state || mod & KMOD_SHIFT) + c += 2; + + int x = 0; + for (int i = 0; i < state->entry_cursor; ++i) + { + const char *special = + display_special_char(state->entry.data[i]); + + if (special) + x += strlen(special); + else + ++x; + + x %= 16; + } + + SDL_Rect pos = { .x = (6 * x), .y = (64 - 8) }; + SDL_Surface *tile = get_font_char(c); + + int rc = SDL_BlitSurface(tile, NULL, frame, &pos); + if (rc < 0) + error("Failed to draw cursor on screen frame: %s", + SDL_GetError()); } SDL_Surface * -default_draw (const struct screen *screen) +default_draw(const struct screen *screen) { - int rc; - SDL_Surface *final; - - final = SDL_CreateRGBSurface (0, 96, 64, 32, 0, 0, 0, 0); - if (!final) - { - error ("Failed to initialize screen frame: %s", SDL_GetError ()); - return NULL; - } - - rc = SDL_FillRect (final, NULL, SDL_MapRGB (final->format, 255, 255, 255)); - if (rc < 0) - error ("Failed to fill screen frame with white background: %s", - SDL_GetError ()); - - struct state *state = screen->state; - unsigned int height = 0; - draw_line (&state->entry, final, &height, false); - draw_cursor (state, final); - - for (int i = state->history_len - 1; i >= 0 && height < 64; --i) - { - draw_line (&state->history[i].answer_string, final, &height, true); - - if (height < 64) - draw_line (&state->history[i].entry, final, &height, false); - } - - return final; + int rc; + SDL_Surface *final; + + final = SDL_CreateRGBSurface(0, 96, 64, 32, 0, 0, 0, 0); + if (!final) + { + error("Failed to initialize screen frame: %s", SDL_GetError()); + return NULL; + } + + rc = SDL_FillRect(final, NULL, + SDL_MapRGB(final->format, 255, 255, 255)); + if (rc < 0) + error("Failed to fill screen frame with white background: %s", + SDL_GetError()); + + struct state *state = screen->state; + unsigned int height = 0; + draw_line(&state->entry, final, &height, false); + draw_cursor(state, final); + + for (int i = state->history_len - 1; i >= 0 && height < 64; --i) + { + draw_line(&state->history[i].answer_string, final, &height, + true); + + if (height < 64) + draw_line(&state->history[i].entry, final, &height, + false); + } + + return final; } int -default_input (struct screen *screen, SDL_KeyboardEvent *key) +default_input(struct screen *screen, SDL_KeyboardEvent *key) { - struct state *state = screen->state; - SDL_Keycode code = key->keysym.sym; - SDL_Keymod mod = key->keysym.mod; - - switch (state->action_state) - { - case STATE_2ND: - mod |= KMOD_LCTRL; - break; - - case STATE_ALPHA: - mod |= KMOD_LSHIFT; - break; - - default: - break; - } - - switch (code) - { - case SDLK_BACKSPACE: - if (!state->entry_cursor) - return 0; - - --state->entry_cursor; - // SPILLS OVER! - case SDLK_DELETE: - if (state->entry_cursor < state->entry.len) - tib_expr_delete (&state->entry, state->entry_cursor); - return 0; - - case SDLK_END: - state->entry_cursor = state->entry.len; - return 0; - - case SDLK_HOME: - state->entry_cursor = 0; - return 0; - - case SDLK_INSERT: - state->insert_mode = !state->insert_mode; - return 0; - - case SDLK_LEFT: - entry_move_cursor (state, LEFT); - return 0; - - case SDLK_RETURN: - case SDLK_KP_ENTER: - if (mod & KMOD_CTRL) - { - return entry_recall (state); - } - else - { - if (0 == state->entry.len) - { - int rc = entry_write (state, TIB_CHAR_ANS); - if (rc) - return rc; - } - - return state_calc_entry (state); - } - - case SDLK_RIGHT: - entry_move_cursor (state, RIGHT); - return 0; - } - - int normal = normalize_keycode (code, mod); - if (normal) - { - if (is_math_operator (normal) && 0 == state->entry.len - && !(mod & KMOD_CTRL)) - { - int rc = entry_write (state, TIB_CHAR_ANS); - if (rc) - return rc; - } - - return entry_write (state, normal); - } - - return 0; + struct state *state = screen->state; + SDL_Keycode code = key->keysym.sym; + SDL_Keymod mod = key->keysym.mod; + + switch (state->action_state) + { + case STATE_2ND: + mod |= KMOD_LCTRL; + break; + + case STATE_ALPHA: + mod |= KMOD_LSHIFT; + break; + + default: + break; + } + + switch (code) + { + case SDLK_BACKSPACE: + if (!state->entry_cursor) + return 0; + + --state->entry_cursor; + // SPILLS OVER! + case SDLK_DELETE: + if (state->entry_cursor < state->entry.len) + tib_expr_delete(&state->entry, state->entry_cursor); + return 0; + + case SDLK_END: + state->entry_cursor = state->entry.len; + return 0; + + case SDLK_HOME: + state->entry_cursor = 0; + return 0; + + case SDLK_INSERT: + state->insert_mode = !state->insert_mode; + return 0; + + case SDLK_LEFT: + entry_move_cursor(state, LEFT); + return 0; + + case SDLK_RETURN: + case SDLK_KP_ENTER: + if (mod & KMOD_CTRL) + { + return entry_recall(state); + } + else + { + if (0 == state->entry.len) + { + int rc = entry_write(state, TIB_CHAR_ANS); + if (rc) + return rc; + } + + return state_calc_entry(state); + } + + case SDLK_RIGHT: + entry_move_cursor(state, RIGHT); + return 0; + } + + int normal = normalize_keycode(code, mod); + if (normal) + { + if (is_math_operator(normal) && 0 == state->entry.len + && !(mod & KMOD_CTRL)) + { + int rc = entry_write(state, TIB_CHAR_ANS); + if (rc) + return rc; + } + + return entry_write(state, normal); + } + + return 0; } diff --git a/src/mode_default.h b/src/mode_default.h index 59caaed..d720978 100644 --- a/src/mode_default.h +++ b/src/mode_default.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,9 +21,9 @@ #include "screen.h" SDL_Surface * -default_draw (const struct screen *screen); +default_draw(const struct screen *screen); int -default_input (struct screen *screen, SDL_KeyboardEvent *key); +default_input(struct screen *screen, SDL_KeyboardEvent *key); #endif diff --git a/src/point.h b/src/point.h index 727521a..0ae4079 100644 --- a/src/point.h +++ b/src/point.h @@ -1,6 +1,6 @@ /* * LiberTI - Libre TI calculator emulator designed for LibreCalc - * Copyright (C) 2015 Delwink, LLC + * Copyright (C) 2015, 2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -20,8 +20,8 @@ struct point2d { - int x; - int y; + int x; + int y; }; #endif diff --git a/src/screen.c b/src/screen.c index d4b5ea8..ba04e8b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -22,26 +22,25 @@ struct _screen_mode { - SDL_Surface * (*draw) (const struct screen *); - int (*input) (struct screen *, SDL_KeyboardEvent *); + SDL_Surface *(*draw)(const struct screen *); + int (*input)(struct screen *, SDL_KeyboardEvent *); }; -const struct _screen_mode SCREEN_MODES[NUM_SCREEN_MODES] = - { - { - .draw = default_draw, - .input = default_input - } - }; +const struct _screen_mode SCREEN_MODES[NUM_SCREEN_MODES] = { + { + .draw = default_draw, + .input = default_input + } +}; SDL_Surface * -screen_draw (const struct screen *screen) +screen_draw(const struct screen *screen) { - return SCREEN_MODES[screen->mode].draw (screen); + return SCREEN_MODES[screen->mode].draw(screen); } int -screen_input (struct screen *screen, SDL_KeyboardEvent *event) +screen_input(struct screen *screen, SDL_KeyboardEvent *event) { - return SCREEN_MODES[screen->mode].input (screen, event); + return SCREEN_MODES[screen->mode].input(screen, event); } diff --git a/src/screen.h b/src/screen.h index 5d6014f..627e5f6 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,25 +24,25 @@ #include "state.h" enum screen_mode - { - DEFAULT_SCREEN_MODE, - NUM_SCREEN_MODES - }; +{ + DEFAULT_SCREEN_MODE, + NUM_SCREEN_MODES +}; struct screen { - struct state *state; + struct state *state; - struct point2d pos; - struct point2d size; + struct point2d pos; + struct point2d size; - enum screen_mode mode; + enum screen_mode mode; }; SDL_Surface * -screen_draw (const struct screen *screen); +screen_draw(const struct screen *screen); int -screen_input (struct screen *screen, SDL_KeyboardEvent *event); +screen_input(struct screen *screen, SDL_KeyboardEvent *event); #endif diff --git a/src/skin.c b/src/skin.c index 2d41ed7..c24f9e8 100644 --- a/src/skin.c +++ b/src/skin.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -27,12 +27,12 @@ #include "tibchar.h" #include "tiberr.h" -#define DEFAULT_SKIN \ - "screens=({" \ - "mode=\"default\";" \ - "x=0;" \ - "y=0;" \ - "});" +#define DEFAULT_SKIN \ + "screens=({" \ + "mode=\"default\";" \ + "x=0;" \ + "y=0;" \ + "});" #define DEFAULT_SCREEN_WIDTH (96) #define DEFAULT_SCREEN_HEIGHT (64) @@ -40,725 +40,737 @@ static PrefixTree *action_keywords = NULL; static int -mode_from_string (const char *s) +mode_from_string(const char *s) { - if (0 == strcmp (s, "default")) - return DEFAULT_SCREEN_MODE; + if (0 == strcmp(s, "default")) + return DEFAULT_SCREEN_MODE; - return -1; + return -1; } static int -add_screen (Skin *self, struct state *state, struct point2d pos, - enum screen_mode mode, double scale) +add_screen(Skin *self, struct state *state, struct point2d pos, + enum screen_mode mode, double scale) { - struct skin_screen_list *node = self->screens; - - if (scale <= 0) - return TIB_EBADFILE; - - if (!node) - { - self->screens = malloc (sizeof (struct skin_screen_list)); - if (!self->screens) - return TIB_EALLOC; - - node = self->screens; - self->active_screen = &node->screen; - } - else - { - while (node->next) - node = node->next; - - node->next = malloc (sizeof (struct skin_screen_list)); - if (!node->next) - return TIB_EALLOC; - - node = node->next; - } - - node->next = NULL; - node->screen.state = state; - node->screen.pos = pos; - node->screen.size.x = DEFAULT_SCREEN_WIDTH * scale; - node->screen.size.y = DEFAULT_SCREEN_HEIGHT * scale; - node->screen.mode = mode; - - return 0; + struct skin_screen_list *node = self->screens; + + if (scale <= 0) + return TIB_EBADFILE; + + if (!node) + { + self->screens = malloc(sizeof(struct skin_screen_list)); + if (!self->screens) + return TIB_EALLOC; + + node = self->screens; + self->active_screen = &node->screen; + } + else + { + while (node->next) + node = node->next; + + node->next = malloc(sizeof(struct skin_screen_list)); + if (!node->next) + return TIB_EALLOC; + + node = node->next; + } + + node->next = NULL; + node->screen.state = state; + node->screen.pos = pos; + node->screen.size.x = DEFAULT_SCREEN_WIDTH * scale; + node->screen.size.y = DEFAULT_SCREEN_HEIGHT * scale; + node->screen.mode = mode; + + return 0; } static char * -skin_file_path (const char *root, const char *file) +skin_file_path(const char *root, const char *file) { - size_t len = strlen (root) + strlen (file) + 2; - char *full_path = malloc (len * sizeof (char)); - if (!full_path) - return NULL; + size_t len = strlen(root) + strlen(file) + 2; + char *full_path = malloc(len * sizeof(char)); + if (!full_path) + return NULL; - sprintf (full_path, "%s/%s", root, file); - return full_path; + sprintf(full_path, "%s/%s", root, file); + return full_path; } static void -free_action_keywords () +free_action_keywords() { - pt_free (action_keywords); - action_keywords = NULL; + pt_free(action_keywords); + action_keywords = NULL; } static int -init_action_keywords () +init_action_keywords() { - action_keywords = pt_new (); - if (!action_keywords) - return TIB_EALLOC; + action_keywords = pt_new(); + if (!action_keywords) + return TIB_EALLOC; - for (int i = TIB_CHAR_AND; i <= TIB_CHAR_YSCL; ++i) - { - const char *trans = tib_special_char_text (i); - if (!trans) - continue; + for (int i = TIB_CHAR_AND; i <= TIB_CHAR_YSCL; ++i) + { + const char *trans = tib_special_char_text(i); + if (!trans) + continue; - if (' ' == *trans) - ++trans; /* trim any leading space */ + if (' ' == *trans) + ++trans; // trim any leading space - char trim[11]; /* long enough to hold all translated strings and NUL */ - strcpy (trim, trans); + char trim[11]; /* long enough to hold all translated strings + * and NUL + */ + strcpy(trim, trans); - char *p = strrchr (trim, ' '); - if (p) - *p = '\0'; /* trim any trailing space */ + char *p = strrchr(trim, ' '); + if (p) + *p = '\0'; // trim any trailing space - for (p = trim; *p != '\0'; ++p) - *p = tolower (*p); + for (p = trim; *p != '\0'; ++p) + *p = tolower(*p); - tib_errno = pt_add (action_keywords, trim, i); - if (tib_errno) - goto fail; - } + tib_errno = pt_add(action_keywords, trim, i); + if (tib_errno) + goto fail; + } - return 0; + return 0; fail: - free_action_keywords (); - return TIB_EALLOC; + free_action_keywords(); + return TIB_EALLOC; } static int -action_type_from_string (const char *s) +action_type_from_string(const char *s) { - if (!s) - return -1; - - if (0 == strcmp (s, "mode")) - return CHANGE_MODES; - else if (0 == strcmp (s, "char")) - return CHAR_INSERT; - else if (0 == strcmp (s, "move")) - return CURSOR_MOVE; - else if (0 == strcmp (s, "shift")) - return TOGGLE_2ND; - else if (0 == strcmp (s, "alpha")) - return TOGGLE_ALPHA; - else if (0 == strcmp (s, "insert")) - return TOGGLE_INSERT; - - return -1; + if (!s) + return -1; + + if (0 == strcmp(s, "mode")) + return CHANGE_MODES; + else if (0 == strcmp(s, "char")) + return CHAR_INSERT; + else if (0 == strcmp(s, "move")) + return CURSOR_MOVE; + else if (0 == strcmp(s, "shift")) + return TOGGLE_2ND; + else if (0 == strcmp(s, "alpha")) + return TOGGLE_ALPHA; + else if (0 == strcmp(s, "insert")) + return TOGGLE_INSERT; + + return -1; } static bool -isdisplayable (char c) +isdisplayable(char c) { - return (c > 31 && c < 96) || (c > 96 && c < 127); + return (c > 31 && c < 96) || (c > 96 && c < 127); } static int -char_insert_from_string (const char *s) +char_insert_from_string(const char *s) { - const PrefixTree *t = pt_search (action_keywords, s); - if (t) - return pt_data (t); + const PrefixTree *t = pt_search(action_keywords, s); + if (t) + return pt_data(t); - if (strlen (s) != 1 || !isdisplayable (s[0])) - return -1; + if (strlen(s) != 1 || !isdisplayable(s[0])) + return -1; - return s[0]; + return s[0]; } static int -cursor_move_from_string (const char *s) +cursor_move_from_string(const char *s) { - if (!s) - return -1; - - if (0 == strcmp (s, "up")) - return UP; - else if (0 == strcmp (s, "down")) - return DOWN; - else if (0 == strcmp (s, "left")) - return LEFT; - else if (0 == strcmp (s, "right")) - return RIGHT; - - return -1; + if (!s) + return -1; + + if (0 == strcmp(s, "up")) + return UP; + else if (0 == strcmp(s, "down")) + return DOWN; + else if (0 == strcmp(s, "left")) + return LEFT; + else if (0 == strcmp(s, "right")) + return RIGHT; + + return -1; } static int -get_action_set (const config_setting_t *mode, const char *name, - struct button_action_set *action) +get_action_set(const config_setting_t *mode, const char *name, + struct button_action_set *action) { - const config_setting_t *root = config_setting_get_member (mode, name); - if (!root) - return TIB_EBADFILE; - - const config_setting_t *setting = config_setting_get_member (root, "type"); - if (!setting || CONFIG_TYPE_STRING != config_setting_type (setting)) - return TIB_EBADFILE; - - int i = action_type_from_string (config_setting_get_string (setting)); - if (-1 == i) - return TIB_EBADFILE; - - action->type = i; - setting = config_setting_get_member (root, "which"); - const char *value = NULL; - if (setting) - value = config_setting_get_string (setting); - switch (i) - { - case CHANGE_MODES: - if (!setting) - return TIB_EBADFILE; - - i = mode_from_string (value); - if (-1 == i) - return TIB_EBADFILE; - - action->which.mode_open = i; - break; - - case CHAR_INSERT: - if (!setting) - return TIB_EBADFILE; - - action->which.char_insert = char_insert_from_string (value); - if (-1 == action->which.char_insert) - return TIB_EBADFILE; - break; - - case CURSOR_MOVE: - if (!setting) - return TIB_EBADFILE; - - i = cursor_move_from_string (value); - if (-1 == i) - return TIB_EBADFILE; - - action->which.cursor_move = i; - break; - - default: - break; - } - - return 0; + const config_setting_t *root = config_setting_get_member(mode, name); + if (!root) + return TIB_EBADFILE; + + const config_setting_t *setting = + config_setting_get_member(root, "type"); + if (!setting || CONFIG_TYPE_STRING != config_setting_type(setting)) + return TIB_EBADFILE; + + int i = action_type_from_string(config_setting_get_string(setting)); + if (-1 == i) + return TIB_EBADFILE; + + action->type = i; + setting = config_setting_get_member(root, "which"); + const char *value = NULL; + if (setting) + value = config_setting_get_string(setting); + switch (i) + { + case CHANGE_MODES: + if (!setting) + return TIB_EBADFILE; + + i = mode_from_string(value); + if (-1 == i) + return TIB_EBADFILE; + + action->which.mode_open = i; + break; + + case CHAR_INSERT: + if (!setting) + return TIB_EBADFILE; + + action->which.char_insert = char_insert_from_string(value); + if (-1 == action->which.char_insert) + return TIB_EBADFILE; + break; + + case CURSOR_MOVE: + if (!setting) + return TIB_EBADFILE; + + i = cursor_move_from_string(value); + if (-1 == i) + return TIB_EBADFILE; + + action->which.cursor_move = i; + break; + + default: + break; + } + + return 0; } static int -get_all_actions (const config_setting_t *mode, - struct button_action_set actions[]) +get_all_actions(const config_setting_t *mode, + struct button_action_set actions[]) { - if (!mode) - return TIB_EBADFILE; + if (!mode) + return TIB_EBADFILE; - tib_errno = init_action_keywords (); + tib_errno = init_action_keywords(); #define GET_ACTION_SET(A,S) tib_errno = get_action_set (mode, S, &A); \ - if (tib_errno) goto fail; + if (tib_errno) goto fail; - GET_ACTION_SET (actions[STATE_NORMAL], "normal"); - GET_ACTION_SET (actions[STATE_2ND], "shift"); - GET_ACTION_SET (actions[STATE_ALPHA], "alpha"); + GET_ACTION_SET(actions[STATE_NORMAL], "normal"); + GET_ACTION_SET(actions[STATE_2ND], "shift"); + GET_ACTION_SET(actions[STATE_ALPHA], "alpha"); fail: - free_action_keywords (); - return tib_errno; + free_action_keywords(); + return tib_errno; } Skin * -open_skin (const char *path, struct state *state, struct point2d size) +open_skin(const char *path, struct state *state, struct point2d size) { - if (!state) - { - tib_errno = TIB_ENULLPTR; - return NULL; - } - - Skin *new = malloc (sizeof (Skin)); - if (!new) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - memset (new, 0, sizeof (Skin)); - new->state = state; - - config_t conf; - config_init (&conf); - - if (path) - { - char *spec_path = skin_file_path (path, "spec.conf"); - if (!spec_path) - { - tib_errno = TIB_EALLOC; - goto fail; - } - - tib_errno = config_read_file (&conf, spec_path); - free (spec_path); - } - else - { - tib_errno = config_read_string (&conf, DEFAULT_SKIN); - } - - if (CONFIG_FALSE == tib_errno) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - tib_errno = 0; - - config_setting_t *setting = config_lookup (&conf, "background"); - if (setting) - { - if (CONFIG_TYPE_STRING != config_setting_type (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - char *bgpath = skin_file_path (path, - config_setting_get_string (setting)); - if (!bgpath) - { - tib_errno = TIB_EALLOC; - goto fail; - } - - new->background = IMG_Load (bgpath); - free (bgpath); - if (!new->background) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - new->size.x = new->background->w; - new->size.y = new->background->h; - } - else - { - new->size = size; - } - - setting = config_lookup (&conf, "screens"); - if (setting) - { - if (!config_setting_is_list (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - config_setting_t * const screens = setting; - unsigned int i = 0; - while ((setting = config_setting_get_elem (screens, i++))) - { - if (!config_setting_is_group (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - config_setting_t * const screen = setting; - - setting = config_setting_get_member (screen, "mode"); - if (!setting || config_setting_type (setting) != CONFIG_TYPE_STRING) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - int mode = mode_from_string (config_setting_get_string (setting)); - if (-1 == mode) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - setting = config_setting_get_member (screen, "x"); - if (!setting || !config_setting_is_number (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - struct point2d pos; - pos.x = config_setting_get_int (setting); - - setting = config_setting_get_member (screen, "y"); - if (!setting || !config_setting_is_number (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - pos.y = config_setting_get_int (setting); - - double scale = 1.0; - setting = config_setting_get_member (screen, "scale"); - if (setting) - { - if (!config_setting_is_number (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - scale = config_setting_get_float (setting); - } - - tib_errno = add_screen (new, state, pos, mode, scale); - if (tib_errno) - goto fail; - } - } - - setting = config_lookup (&conf, "buttons"); - if (setting) - { - if (!config_setting_is_list (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - new->buttons = malloc (sizeof (struct skin_button_list)); - if (!new->buttons) - { - tib_errno = TIB_EALLOC; - goto fail; - } - - const config_setting_t *buttons = setting; - struct skin_button_list *next = new->buttons; - unsigned int i = 0; - while ((setting = config_setting_get_elem (buttons, i++))) - { - if (!config_setting_is_group (setting)) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - if (i > 1) - { - next->next = malloc (sizeof (struct skin_button_list)); - if (!next->next) - { - tib_errno = TIB_EALLOC; - goto fail; - } - - next = next->next; - } - - next->button = malloc (sizeof (struct button)); - if (!next->button) - { - tib_errno = TIB_EALLOC; - goto fail; - } - - const config_setting_t *button = setting; - - setting = config_setting_get_member (button, "actions"); - if (!setting) - { - tib_errno = TIB_EBADFILE; - goto fail; - } - - const config_setting_t *modes = setting; - - setting = config_setting_get_member (modes, "default"); - bool have_default = setting != NULL; - struct button_action_set default_actions[NUM_ACTION_STATES]; - if (have_default) - { - tib_errno = get_all_actions (setting, default_actions); - if (tib_errno) - goto fail; - } - - size_t j; - struct button_action_set actions[NUM_ACTION_STATES]; -#define ADD_ACTION(A,I) setting = config_setting_get_member (modes, (A)); \ - if (setting) \ - { \ - tib_errno = get_all_actions (setting, actions); \ - if (tib_errno) \ - goto fail; \ - } \ - else \ - { \ - for (j = 0; j < NUM_ACTION_STATES; ++j) \ - actions[j] = default_actions[j]; \ - } \ - for (j = 0; j < NUM_ACTION_STATES; ++j) \ - next->button->actions[(I)][j] = actions[j]; - - ADD_ACTION ("default", DEFAULT_SCREEN_MODE); - -#define ADD_DIM(D,V) setting = config_setting_get_member (button, (D)); \ - if (!setting || !config_setting_is_number (setting)) \ - { \ - tib_errno = TIB_EBADFILE; \ - goto fail; \ - } \ - (V) = config_setting_get_int (setting); - - ADD_DIM ("x", next->button->pos.x); - ADD_DIM ("y", next->button->pos.y); - ADD_DIM ("w", next->button->size.x); - ADD_DIM ("h", next->button->size.y); - } - } - - config_destroy (&conf); - return new; + if (!state) + { + tib_errno = TIB_ENULLPTR; + return NULL; + } + + Skin *new = malloc(sizeof(Skin)); + if (!new) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + memset(new, 0, sizeof(Skin)); + new->state = state; + + config_t conf; + config_init(&conf); + + if (path) + { + char *spec_path = skin_file_path(path, "spec.conf"); + if (!spec_path) + { + tib_errno = TIB_EALLOC; + goto fail; + } + + tib_errno = config_read_file(&conf, spec_path); + free(spec_path); + } + else + { + tib_errno = config_read_string(&conf, DEFAULT_SKIN); + } + + if (CONFIG_FALSE == tib_errno) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + tib_errno = 0; + + config_setting_t *setting = config_lookup(&conf, "background"); + if (setting) + { + if (CONFIG_TYPE_STRING != config_setting_type(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + char *bgpath = skin_file_path(path, + config_setting_get_string(setting)); + if (!bgpath) + { + tib_errno = TIB_EALLOC; + goto fail; + } + + new->background = IMG_Load(bgpath); + free(bgpath); + if (!new->background) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + new->size.x = new->background->w; + new->size.y = new->background->h; + } + else + { + new->size = size; + } + + setting = config_lookup(&conf, "screens"); + if (setting) + { + if (!config_setting_is_list(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + config_setting_t * const screens = setting; + unsigned int i = 0; + while ((setting = config_setting_get_elem(screens, i++))) + { + if (!config_setting_is_group(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + config_setting_t * const screen = setting; + + setting = config_setting_get_member(screen, "mode"); + if (!setting + || (config_setting_type(setting) != + CONFIG_TYPE_STRING)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + const char *mode_str = + config_setting_get_string(setting); + int mode = mode_from_string(mode_str); + if (-1 == mode) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + setting = config_setting_get_member(screen, "x"); + if (!setting || !config_setting_is_number(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + struct point2d pos; + pos.x = config_setting_get_int(setting); + + setting = config_setting_get_member(screen, "y"); + if (!setting || !config_setting_is_number(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + pos.y = config_setting_get_int(setting); + + double scale = 1.0; + setting = config_setting_get_member(screen, "scale"); + if (setting) + { + if (!config_setting_is_number(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + scale = config_setting_get_float(setting); + } + + tib_errno = add_screen(new, state, pos, mode, scale); + if (tib_errno) + goto fail; + } + } + + setting = config_lookup(&conf, "buttons"); + if (setting) + { + if (!config_setting_is_list(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + new->buttons = malloc(sizeof(struct skin_button_list)); + if (!new->buttons) + { + tib_errno = TIB_EALLOC; + goto fail; + } + + const config_setting_t *buttons = setting; + struct skin_button_list *next = new->buttons; + unsigned int i = 0; + while ((setting = config_setting_get_elem(buttons, i++))) + { + if (!config_setting_is_group(setting)) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + if (i > 1) + { + next->next = + malloc(sizeof(struct skin_button_list)); + if (!next->next) + { + tib_errno = TIB_EALLOC; + goto fail; + } + + next = next->next; + } + + next->button = malloc(sizeof(struct button)); + if (!next->button) + { + tib_errno = TIB_EALLOC; + goto fail; + } + + const config_setting_t *button = setting; + + setting = config_setting_get_member(button, "actions"); + if (!setting) + { + tib_errno = TIB_EBADFILE; + goto fail; + } + + const config_setting_t *modes = setting; + + setting = config_setting_get_member(modes, "default"); + bool have_default = setting != NULL; + struct button_action_set default_actions[NUM_ACTION_STATES]; + if (have_default) + { + tib_errno = get_all_actions(setting, + default_actions); + if (tib_errno) + goto fail; + } + + size_t j; + struct button_action_set actions[NUM_ACTION_STATES]; +#define ADD_ACTION(A,I) setting = config_setting_get_member(modes, (A)); \ + if (setting) \ + { \ + tib_errno = get_all_actions(setting, actions); \ + if (tib_errno) \ + goto fail; \ + } \ + else \ + { \ + for (j = 0; j < NUM_ACTION_STATES; ++j) \ + actions[j] = default_actions[j]; \ + } \ + for (j = 0; j < NUM_ACTION_STATES; ++j) \ + next->button->actions[(I)][j] = actions[j]; + + ADD_ACTION("default", DEFAULT_SCREEN_MODE); + +#define ADD_DIM(D,V) setting = config_setting_get_member(button, (D)); \ + if (!setting || !config_setting_is_number(setting)) \ + { \ + tib_errno = TIB_EBADFILE; \ + goto fail; \ + } \ + (V) = config_setting_get_int(setting); + + ADD_DIM("x", next->button->pos.x); + ADD_DIM("y", next->button->pos.y); + ADD_DIM("w", next->button->size.x); + ADD_DIM("h", next->button->size.y); + } + } + + config_destroy(&conf); + return new; fail: - config_destroy (&conf); - - if (new->background) - SDL_FreeSurface (new->background); - - if (new->screens) - { - struct skin_screen_list *s = new->screens; - while (s) - { - s = s->next; - free (new->screens); - new->screens = s; - } - } - - if (new->buttons) - { - struct skin_button_list *s = new->buttons; - while (s) - { - if (s->button) - free (s->button); - s = s->next; - free (new->buttons); - new->buttons = s; - } - } - - free (new); - return NULL; + config_destroy(&conf); + + if (new->background) + SDL_FreeSurface(new->background); + + if (new->screens) + { + struct skin_screen_list *s = new->screens; + while (s) + { + s = s->next; + free(new->screens); + new->screens = s; + } + } + + if (new->buttons) + { + struct skin_button_list *s = new->buttons; + while (s) + { + if (s->button) + free(s->button); + s = s->next; + free(new->buttons); + new->buttons = s; + } + } + + free(new); + return NULL; } void -free_skin (Skin *self) +free_skin(Skin *self) { - if (self->background) - SDL_FreeSurface (self->background); - - struct skin_screen_list *s = self->screens; - while (s) - { - s = s->next; - free (self->screens); - self->screens = s; - } - - struct skin_button_list *b = self->buttons; - while (b) - { - free (b->button); - b = b->next; - free (self->buttons); - self->buttons = b; - } - - free (self); + if (self->background) + SDL_FreeSurface(self->background); + + struct skin_screen_list *s = self->screens; + while (s) + { + s = s->next; + free(self->screens); + self->screens = s; + } + + struct skin_button_list *b = self->buttons; + while (b) + { + free(b->button); + b = b->next; + free(self->buttons); + self->buttons = b; + } + + free(self); } static bool -in_bounds (struct point2d start, struct point2d size, struct point2d pos) +in_bounds(struct point2d start, struct point2d size, struct point2d pos) { - return pos.x >= start.x && pos.x <= (start.x + size.x) - && pos.y >= start.y && pos.y <= (start.y + size.y); + return pos.x >= start.x && pos.x <= (start.x + size.x) + && pos.y >= start.y && pos.y <= (start.y + size.y); } static bool -on_skin (const Skin *self, struct point2d pos) +on_skin(const Skin *self, struct point2d pos) { - struct point2d size = { .x = self->background->w, .y = self->background->h }; - return in_bounds ((struct point2d) { 0, 0 }, size, pos); + struct point2d size = { + .x = self->background->w, + .y = self->background->h + }; + + return in_bounds((struct point2d) { 0, 0 }, size, pos); } static bool -on_screen (const struct screen *screen, struct point2d pos) +on_screen(const struct screen *screen, struct point2d pos) { - return in_bounds (screen->pos, screen->size, pos); + return in_bounds(screen->pos, screen->size, pos); } static bool -on_button (const struct button *button, struct point2d pos) +on_button(const struct button *button, struct point2d pos) { - return in_bounds (button->pos, button->size, pos); + return in_bounds(button->pos, button->size, pos); } static int -do_button_action (Skin *self, struct button *button) +do_button_action(Skin *self, struct button *button) { - struct screen *screen = self->active_screen; - struct state *state = self->state; - enum screen_mode mode = screen->mode; + struct screen *screen = self->active_screen; + struct state *state = self->state; + enum screen_mode mode = screen->mode; - struct button_action_set *action; - action = &button->actions[mode][state->action_state]; - union button_action which = action->which; + struct button_action_set *action; + action = &button->actions[mode][state->action_state]; + union button_action which = action->which; - switch (action->type) - { - case CHANGE_MODES: - screen->mode = which.mode_open; - break; + switch (action->type) + { + case CHANGE_MODES: + screen->mode = which.mode_open; + break; - case CHAR_INSERT: - return entry_write (state, which.char_insert); + case CHAR_INSERT: + return entry_write(state, which.char_insert); - case CURSOR_MOVE: - entry_move_cursor (state, which.cursor_move); - break; + case CURSOR_MOVE: + entry_move_cursor(state, which.cursor_move); + break; - case TOGGLE_2ND: - change_action_state (state, STATE_2ND); - break; + case TOGGLE_2ND: + change_action_state(state, STATE_2ND); + break; - case TOGGLE_ALPHA: - change_action_state (state, STATE_ALPHA); - break; + case TOGGLE_ALPHA: + change_action_state(state, STATE_ALPHA); + break; - case TOGGLE_INSERT: - state->insert_mode = !state->insert_mode; - break; - } + case TOGGLE_INSERT: + state->insert_mode = !state->insert_mode; + break; + } - return 0; + return 0; } int -Skin_click (Skin *self, struct point2d pos) +Skin_click(Skin * self, struct point2d pos) { - if (!on_skin (self, pos)) - return TIB_EDIM; - - for (struct skin_button_list *elem = self->buttons; - elem != NULL; - elem = elem->next) - { - struct button *button = elem->button; - - if (on_button (button, pos)) - return do_button_action (self, button); - } - - for (struct skin_screen_list *elem = self->screens; - elem != NULL; - elem = elem->next) - { - struct screen *screen = &elem->screen; - - if (on_screen (screen, pos)) - { - if (screen != self->active_screen) - { - self->active_screen = screen; - self->state->action_state = STATE_NORMAL; - } - } - } - - return 0; + if (!on_skin(self, pos)) + return TIB_EDIM; + + for (struct skin_button_list *elem = self->buttons; elem != NULL; + elem = elem->next) + { + struct button *button = elem->button; + + if (on_button(button, pos)) + return do_button_action(self, button); + } + + for (struct skin_screen_list *elem = self->screens; elem != NULL; + elem = elem->next) + { + struct screen *screen = &elem->screen; + + if (on_screen(screen, pos)) + { + if (screen != self->active_screen) + { + self->active_screen = screen; + self->state->action_state = STATE_NORMAL; + } + } + } + + return 0; } int -Skin_input (Skin *self, SDL_KeyboardEvent *event) +Skin_input(Skin *self, SDL_KeyboardEvent *event) { - return screen_input (self->active_screen, event); + return screen_input(self->active_screen, event); } static SDL_Rect -get_rect (struct point2d pos, struct point2d size) +get_rect(struct point2d pos, struct point2d size) { - SDL_Rect r = - { - .x = pos.x, - .y = pos.y, - .w = size.x, - .h = size.y - }; - - return r; + SDL_Rect r = { + .x = pos.x, + .y = pos.y, + .w = size.x, + .h = size.y + }; + + return r; } SDL_Surface * -Skin_get_frame (Skin *self) +Skin_get_frame(Skin *self) { - int rc; - SDL_Surface *final; - - final = SDL_CreateRGBSurface (0, self->size.x, self->size.y, 32, 0, 0, 0, 0); - if (!final) - { - error ("Failed to initialize skin frame: %s", SDL_GetError ()); - return NULL; - } - - if (self->background) - { - rc = SDL_BlitSurface (self->background, NULL, final, NULL); - if (rc < 0) - error ("Failed to blit background: %s", SDL_GetError ()); - } - - struct skin_screen_list *elem = self->screens; - unsigned int i = 0; - for (; elem != NULL; elem = elem->next, ++i) - { - struct screen *screen = &elem->screen; - SDL_Surface *render = screen_draw (screen); - if (render) - { - SDL_Rect r = get_rect (screen->pos, screen->size); - rc = SDL_BlitScaled (render, NULL, final, &r); - SDL_FreeSurface (render); - if (rc < 0) - error ("Failed to blit screen %u: %s", i, SDL_GetError ()); - } - } - - return final; + int rc; + SDL_Surface *final; + + final = SDL_CreateRGBSurface(0, self->size.x, self->size.y, 32, 0, 0, + 0, 0); + if (!final) + { + error("Failed to initialize skin frame: %s", SDL_GetError()); + return NULL; + } + + if (self->background) + { + rc = SDL_BlitSurface(self->background, NULL, final, NULL); + if (rc < 0) + error("Failed to blit background: %s", SDL_GetError()); + } + + struct skin_screen_list *elem = self->screens; + unsigned int i = 0; + for (; elem != NULL; elem = elem->next, ++i) + { + struct screen *screen = &elem->screen; + SDL_Surface *render = screen_draw(screen); + if (render) + { + SDL_Rect r = get_rect(screen->pos, screen->size); + rc = SDL_BlitScaled(render, NULL, final, &r); + SDL_FreeSurface(render); + if (rc < 0) + error("Failed to blit screen %u: %s", i, + SDL_GetError()); + } + } + + return final; } diff --git a/src/skin.h b/src/skin.h index 92afe68..0996fb9 100644 --- a/src/skin.h +++ b/src/skin.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -27,40 +27,40 @@ struct skin_button_list { - struct button *button; - struct skin_button_list *next; + struct button *button; + struct skin_button_list *next; }; struct skin_screen_list { - struct screen screen; - struct skin_screen_list *next; + struct screen screen; + struct skin_screen_list *next; }; typedef struct { - SDL_Surface *background; - struct screen *active_screen; - struct skin_screen_list *screens; - struct skin_button_list *buttons; - struct state *state; + SDL_Surface *background; + struct screen *active_screen; + struct skin_screen_list *screens; + struct skin_button_list *buttons; + struct state *state; - struct point2d size; + struct point2d size; } Skin; Skin * -open_skin (const char *path, struct state *state, struct point2d size); +open_skin(const char *path, struct state *state, struct point2d size); void -free_skin (Skin *self); +free_skin(Skin *self); int -Skin_click (Skin *self, struct point2d pos); +Skin_click(Skin *self, struct point2d pos); int -Skin_input (Skin *self, SDL_KeyboardEvent *event); +Skin_input(Skin *self, SDL_KeyboardEvent *event); SDL_Surface * -Skin_get_frame (Skin *self); +Skin_get_frame(Skin *self); #endif diff --git a/src/state.c b/src/state.c index f280e0f..dcb8884 100644 --- a/src/state.c +++ b/src/state.c @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -26,302 +26,301 @@ #include "util.h" static void -add_history (struct state *state, struct tib_expr *in, struct tib_expr *ans_s, - TIB *ans) +add_history(struct state *state, struct tib_expr *in, struct tib_expr *ans_s, + TIB *ans) { - if (MAX_HISTORY == state->history_len) - { - tib_expr_destroy (&state->history[0].entry); - tib_expr_destroy (&state->history[0].answer_string); - tib_decref (state->history[0].answer); - - for (unsigned int i = 0; i < MAX_HISTORY - 1; ++i) - state->history[i] = state->history[i + 1]; - } - else - { - ++state->history_len; - } - - unsigned int i = state->history_len - 1; - state->history[i].entry = *in; - state->history[i].answer_string = *ans_s; - state->history[i].answer = ans; + if (MAX_HISTORY == state->history_len) + { + tib_expr_destroy(&state->history[0].entry); + tib_expr_destroy(&state->history[0].answer_string); + tib_decref(state->history[0].answer); + + for (unsigned int i = 0; i < MAX_HISTORY - 1; ++i) + state->history[i] = state->history[i + 1]; + } + else + { + ++state->history_len; + } + + unsigned int i = state->history_len - 1; + state->history[i].entry = *in; + state->history[i].answer_string = *ans_s; + state->history[i].answer = ans; } int -load_state (struct state *dest, const char *path) +load_state(struct state *dest, const char *path) { - int rc = 0; - - if (!dest) - return TIB_ENULLPTR; - - dest->action_state = STATE_NORMAL; - dest->entry_cursor = 0; - dest->history_len = 0; - dest->blink_state = true; - dest->insert_mode = false; - - rc = tib_expr_init (&dest->entry); - if (rc) - return rc; - - if (!path) - return 0; - - config_t conf; - config_init (&conf); - - rc = config_read_file (&conf, path); - if (CONFIG_FALSE == rc) - { - config_destroy (&conf); - return TIB_EBADFILE; - } - - config_setting_t *setting = config_lookup (&conf, "history"); - if (setting) - { - if (config_setting_type (setting) != CONFIG_TYPE_LIST) - { - rc = TIB_EBADFILE; - goto fail; - } - - unsigned int i = 0; - config_setting_t *line; - - while ((line = config_setting_get_elem (setting, i++))) - { - if (config_setting_type (line) != CONFIG_TYPE_GROUP) - { - rc = TIB_EBADFILE; - goto fail; - } - - config_setting_t *e = config_setting_get_member (line, "input"); - if (!e || config_setting_type (e) != CONFIG_TYPE_STRING) - { - rc = TIB_EBADFILE; - goto fail; - } - - const char *s = config_setting_get_string (e); - rc = tib_encode_str (&dest->entry, s); - if (rc) - goto fail; - - rc = state_calc_entry (dest); - if (rc) - goto fail; - } - } - - config_destroy (&conf); - return 0; + int rc = 0; + + if (!dest) + return TIB_ENULLPTR; + + dest->action_state = STATE_NORMAL; + dest->entry_cursor = 0; + dest->history_len = 0; + dest->blink_state = true; + dest->insert_mode = false; + + rc = tib_expr_init(&dest->entry); + if (rc) + return rc; + + if (!path) + return 0; + + config_t conf; + config_init(&conf); + + rc = config_read_file(&conf, path); + if (CONFIG_FALSE == rc) + { + config_destroy(&conf); + return TIB_EBADFILE; + } + + config_setting_t *setting = config_lookup(&conf, "history"); + if (setting) + { + if (config_setting_type(setting) != CONFIG_TYPE_LIST) + { + rc = TIB_EBADFILE; + goto fail; + } + + unsigned int i = 0; + config_setting_t *line; + + while ((line = config_setting_get_elem(setting, i++))) + { + if (config_setting_type(line) != CONFIG_TYPE_GROUP) + { + rc = TIB_EBADFILE; + goto fail; + } + + config_setting_t *e = + config_setting_get_member(line, "input"); + if (!e || config_setting_type(e) != CONFIG_TYPE_STRING) + { + rc = TIB_EBADFILE; + goto fail; + } + + const char *s = config_setting_get_string(e); + rc = tib_encode_str(&dest->entry, s); + if (rc) + goto fail; + + rc = state_calc_entry(dest); + if (rc) + goto fail; + } + } + + config_destroy(&conf); + return 0; fail: - state_destroy (dest); - config_destroy (&conf); - return rc; + state_destroy(dest); + config_destroy(&conf); + return rc; } int -save_state (const struct state *state, const char *path) +save_state(const struct state *state, const char *path) { - int rc = 0; + int rc = 0; - if (!state || !path) - return TIB_ENULLPTR; + if (!state || !path) + return TIB_ENULLPTR; - config_t conf; - config_init (&conf); + config_t conf; + config_init(&conf); - config_setting_t * const root = config_root_setting (&conf); + config_setting_t * const root = config_root_setting(&conf); #define CHECK_NULL(P) if (!(P)) { rc = TIB_EALLOC; goto end; } - { - config_setting_t *history = config_setting_add (root, "history", - CONFIG_TYPE_LIST); - CHECK_NULL (history); - - for (unsigned int i = 0; i < state->history_len; ++i) - { - config_setting_t * const line = config_setting_add (history, NULL, - CONFIG_TYPE_GROUP); - CHECK_NULL (line); - - config_setting_t *info = config_setting_add (line, "input", - CONFIG_TYPE_STRING); - CHECK_NULL (info); - - char *s = tib_expr_tostr (&state->history[i].entry); - if (!s) - { - rc = tib_errno; - goto end; - } - - rc = config_setting_set_string (info, s); - free (s); - if (CONFIG_FALSE == rc) - { - rc = TIB_EALLOC; - goto end; - } - } - } + config_setting_t *history = config_setting_add(root, "history", + CONFIG_TYPE_LIST); + CHECK_NULL(history); + + for (unsigned int i = 0; i < state->history_len; ++i) + { + config_setting_t * const line = + config_setting_add(history, NULL, CONFIG_TYPE_GROUP); + CHECK_NULL(line); + + config_setting_t *info = config_setting_add(line, "input", + CONFIG_TYPE_STRING); + CHECK_NULL(info); + + char *s = tib_expr_tostr(&state->history[i].entry); + if (!s) + { + rc = tib_errno; + goto end; + } + + rc = config_setting_set_string(info, s); + free(s); + if (CONFIG_FALSE == rc) + { + rc = TIB_EALLOC; + goto end; + } + } #undef CHECK_NULL - rc = 0; - config_write_file (&conf, path); + rc = 0; + config_write_file(&conf, path); end: - config_destroy (&conf); - return rc; + config_destroy(&conf); + return rc; } void -state_destroy (struct state *state) +state_destroy(struct state *state) { - tib_expr_destroy (&state->entry); - state_clear_history (state); + tib_expr_destroy(&state->entry); + state_clear_history(state); } void -entry_move_cursor (struct state *state, int distance) +entry_move_cursor(struct state *state, int distance) { - state->entry_cursor += distance; + state->entry_cursor += distance; - if (state->entry_cursor > state->entry.len) - state->entry_cursor = state->entry.len; - else if (state->entry_cursor < 0) - state->entry_cursor = 0; + if (state->entry_cursor > state->entry.len) + state->entry_cursor = state->entry.len; + else if (state->entry_cursor < 0) + state->entry_cursor = 0; - state->action_state = STATE_NORMAL; + state->action_state = STATE_NORMAL; } static int -entry_insert (struct state *state, int c) +entry_insert(struct state *state, int c) { - int rc = tib_expr_insert (&state->entry, state->entry_cursor, c); - if (!rc) - { - ++state->entry_cursor; - state->action_state = STATE_NORMAL; - state->insert_mode = false; - } - - return rc; + int rc = tib_expr_insert(&state->entry, state->entry_cursor, c); + if (!rc) + { + ++state->entry_cursor; + state->action_state = STATE_NORMAL; + state->insert_mode = false; + } + + return rc; } int -entry_write (struct state *state, int c) +entry_write(struct state *state, int c) { - if (state->insert_mode || state->entry_cursor == state->entry.len) - return entry_insert (state, c); + if (state->insert_mode || state->entry_cursor == state->entry.len) + return entry_insert(state, c); - state->entry.data[state->entry_cursor++] = c; - state->action_state = STATE_NORMAL; - return 0; + state->entry.data[state->entry_cursor++] = c; + state->action_state = STATE_NORMAL; + return 0; } int -entry_recall (struct state *state) +entry_recall(struct state *state) { - if (state->history_len) - { - int rc = tib_exprcpy (&state->entry, - &state->history[state->history_len - 1].entry); - if (rc) - return rc; - - state->entry_cursor = state->entry.len; - } - else - { - state->entry.len = 0; - } - - return 0; + if (state->history_len) + { + int rc = tib_exprcpy(&state->entry, + &state->history[state->history_len - 1].entry); + if (rc) + return rc; + + state->entry_cursor = state->entry.len; + } + else + { + state->entry.len = 0; + } + + return 0; } void -change_action_state (struct state *state, enum action_state action_state) +change_action_state(struct state *state, enum action_state action_state) { - if (state->action_state != action_state) - state->action_state = action_state; - else - state->action_state = STATE_NORMAL; + if (state->action_state != action_state) + state->action_state = action_state; + else + state->action_state = STATE_NORMAL; } int -state_calc_entry (struct state *state) +state_calc_entry(struct state *state) { - TIB *ans = tib_eval (&state->entry); - if (!ans) - return tib_errno; - - int rc = state_add_history (state, &state->entry, ans); - if (rc) - { - tib_decref (ans); - return rc; - } - - state->entry_cursor = 0; - state->entry.len = 0; - - rc = tib_var_set (TIB_CHAR_ANS, ans); - tib_decref (ans); - return rc; + TIB *ans = tib_eval(&state->entry); + if (!ans) + return tib_errno; + + int rc = state_add_history(state, &state->entry, ans); + if (rc) + { + tib_decref(ans); + return rc; + } + + state->entry_cursor = 0; + state->entry.len = 0; + + rc = tib_var_set(TIB_CHAR_ANS, ans); + tib_decref(ans); + return rc; } int -state_add_history (struct state *state, const struct tib_expr *in, - const TIB *answer) +state_add_history(struct state *state, const struct tib_expr *in, + const TIB *answer) { - struct tib_expr in_copy = { .bufsize = 0 }; - int rc = tib_exprcpy (&in_copy, in); - if (rc) - return rc; - - TIB *ans_copy = tib_copy (answer); - if (!ans_copy) - { - tib_expr_destroy (&in_copy); - return tib_errno; - } - - struct tib_expr ans_s; - rc = tib_toexpr (&ans_s, ans_copy); - if (rc) - { - rc = load_expr (&ans_s, "Error"); - if (rc) - { - tib_expr_destroy (&in_copy); - tib_decref (ans_copy); - return rc; - } - } - - add_history (state, &in_copy, &ans_s, ans_copy); - return 0; + struct tib_expr in_copy = { .bufsize = 0 }; + int rc = tib_exprcpy(&in_copy, in); + if (rc) + return rc; + + TIB *ans_copy = tib_copy(answer); + if (!ans_copy) + { + tib_expr_destroy(&in_copy); + return tib_errno; + } + + struct tib_expr ans_s; + rc = tib_toexpr(&ans_s, ans_copy); + if (rc) + { + rc = load_expr(&ans_s, "Error"); + if (rc) + { + tib_expr_destroy(&in_copy); + tib_decref(ans_copy); + return rc; + } + } + + add_history(state, &in_copy, &ans_s, ans_copy); + return 0; } void -state_clear_history (struct state *state) +state_clear_history(struct state *state) { - for (unsigned int i = 0; i < state->history_len; ++i) - { - tib_expr_destroy (&state->history[i].entry); - tib_expr_destroy (&state->history[i].answer_string); - tib_decref (state->history[i].answer); - } - - state->history_len = 0; + for (unsigned int i = 0; i < state->history_len; ++i) + { + tib_expr_destroy(&state->history[i].entry); + tib_expr_destroy(&state->history[i].answer_string); + tib_decref(state->history[i].answer); + } + + state->history_len = 0; } diff --git a/src/state.h b/src/state.h index 7522673..316ad60 100644 --- a/src/state.h +++ b/src/state.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,63 +24,63 @@ #define MAX_HISTORY 35 enum action_state - { - STATE_NORMAL, - STATE_2ND, - STATE_ALPHA, - NUM_ACTION_STATES - }; +{ + STATE_NORMAL, + STATE_2ND, + STATE_ALPHA, + NUM_ACTION_STATES +}; struct history { - struct tib_expr entry; - struct tib_expr answer_string; + struct tib_expr entry; + struct tib_expr answer_string; - TIB *answer; + TIB *answer; }; struct state { - struct history history[MAX_HISTORY]; - struct tib_expr entry; + struct history history[MAX_HISTORY]; + struct tib_expr entry; - enum action_state action_state; - int entry_cursor; - unsigned int history_len; + enum action_state action_state; + int entry_cursor; + unsigned int history_len; - bool blink_state; - bool insert_mode; + bool blink_state; + bool insert_mode; }; int -load_state (struct state *dest, const char *path); +load_state(struct state *dest, const char *path); int -save_state (const struct state *state, const char *path); +save_state(const struct state *state, const char *path); void -state_destroy (struct state *state); +state_destroy(struct state *state); void -entry_move_cursor (struct state *state, int distance); +entry_move_cursor(struct state *state, int distance); int -entry_write (struct state *state, int c); +entry_write(struct state *state, int c); int -entry_recall (struct state *state); +entry_recall(struct state *state); void -change_action_state (struct state *state, enum action_state action_state); +change_action_state(struct state *state, enum action_state action_state); int -state_calc_entry (struct state *state); +state_calc_entry(struct state *state); int -state_add_history (struct state *state, const struct tib_expr *in, - const TIB *answer); +state_add_history(struct state *state, const struct tib_expr *in, + const TIB *answer); void -state_clear_history (struct state *state); +state_clear_history(struct state *state); #endif diff --git a/src/tibchar.c b/src/tibchar.c index 876cc77..8b59fbc 100644 --- a/src/tibchar.c +++ b/src/tibchar.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -26,412 +26,412 @@ static PrefixTree *keywords = NULL; const char * -tib_special_char_text (int c) +tib_special_char_text(int c) { - switch (c) - { - case TIB_CHAR_AND: - return " And "; + switch (c) + { + case TIB_CHAR_AND: + return " And "; - case TIB_CHAR_ANS: - return "Ans"; + case TIB_CHAR_ANS: + return "Ans"; - case TIB_CHAR_AXESOFF: - return "AxesOff"; + case TIB_CHAR_AXESOFF: + return "AxesOff"; - case TIB_CHAR_CLEARDRAW: - return "ClrDraw"; + case TIB_CHAR_CLEARDRAW: + return "ClrDraw"; - case TIB_CHAR_CLEARHOME: - return "ClrHome"; + case TIB_CHAR_CLEARHOME: + return "ClrHome"; - case TIB_CHAR_CLRLIST: - return "ClrList"; + case TIB_CHAR_CLRLIST: + return "ClrList"; - case TIB_CHAR_COS: - return "cos("; + case TIB_CHAR_COS: + return "cos("; - case TIB_CHAR_DEGREE: - return "*(pi/180)"; + case TIB_CHAR_DEGREE: + return "*(pi/180)"; - case TIB_CHAR_DELVAR: - return "DelVar"; + case TIB_CHAR_DELVAR: + return "DelVar"; - case TIB_CHAR_DIFFERENT: - return "~"; + case TIB_CHAR_DIFFERENT: + return "~"; - case TIB_CHAR_DIM: - return "Dim("; + case TIB_CHAR_DIM: + return "Dim("; - case TIB_CHAR_DISP: - return "Disp("; + case TIB_CHAR_DISP: + return "Disp("; - case TIB_CHAR_ELSE: - return "Else"; + case TIB_CHAR_ELSE: + return "Else"; - case TIB_CHAR_END: - return "End"; + case TIB_CHAR_END: + return "End"; - case TIB_CHAR_EPOW10: - return "*10^"; + case TIB_CHAR_EPOW10: + return "*10^"; - case TIB_CHAR_FILL: - return "Fill("; + case TIB_CHAR_FILL: + return "Fill("; - case TIB_CHAR_FOR: - return "For("; + case TIB_CHAR_FOR: + return "For("; - case TIB_CHAR_GETKEY: - return "GetKey"; + case TIB_CHAR_GETKEY: + return "GetKey"; - case TIB_CHAR_GOTO: - return "Goto "; + case TIB_CHAR_GOTO: + return "Goto "; - case TIB_CHAR_IF: - return "If "; + case TIB_CHAR_IF: + return "If "; - case TIB_CHAR_INPUT: - return "Input "; + case TIB_CHAR_INPUT: + return "Input "; - case TIB_CHAR_INT: - return "int("; + case TIB_CHAR_INT: + return "int("; - case TIB_CHAR_L1: - return "L\\1"; + case TIB_CHAR_L1: + return "L\\1"; - case TIB_CHAR_L2: - return "L\\2"; + case TIB_CHAR_L2: + return "L\\2"; - case TIB_CHAR_L3: - return "L\\3"; + case TIB_CHAR_L3: + return "L\\3"; - case TIB_CHAR_L4: - return "L\\4"; + case TIB_CHAR_L4: + return "L\\4"; - case TIB_CHAR_L5: - return "L\\5"; + case TIB_CHAR_L5: + return "L\\5"; - case TIB_CHAR_L6: - return "L\\6"; + case TIB_CHAR_L6: + return "L\\6"; - case TIB_CHAR_L7: - return "L\\7"; + case TIB_CHAR_L7: + return "L\\7"; - case TIB_CHAR_L8: - return "L\\8"; + case TIB_CHAR_L8: + return "L\\8"; - case TIB_CHAR_L9: - return "L\\9"; + case TIB_CHAR_L9: + return "L\\9"; - case TIB_CHAR_LABEL: - return "Lbl "; + case TIB_CHAR_LABEL: + return "Lbl "; - case TIB_CHAR_LINE: - return "Line("; + case TIB_CHAR_LINE: + return "Line("; - case TIB_CHAR_MATA: - return "[[A]]"; + case TIB_CHAR_MATA: + return "[[A]]"; - case TIB_CHAR_MATB: - return "[[B]]"; + case TIB_CHAR_MATB: + return "[[B]]"; - case TIB_CHAR_MATC: - return "[[C]]"; + case TIB_CHAR_MATC: + return "[[C]]"; - case TIB_CHAR_MATD: - return "[[D]]"; + case TIB_CHAR_MATD: + return "[[D]]"; - case TIB_CHAR_MATE: - return "[[E]]"; + case TIB_CHAR_MATE: + return "[[E]]"; - case TIB_CHAR_MATF: - return "[[F]]"; + case TIB_CHAR_MATF: + return "[[F]]"; - case TIB_CHAR_MATG: - return "[[G]]"; + case TIB_CHAR_MATG: + return "[[G]]"; - case TIB_CHAR_MATH: - return "[[H]]"; + case TIB_CHAR_MATH: + return "[[H]]"; - case TIB_CHAR_MATI: - return "[[I]]"; + case TIB_CHAR_MATI: + return "[[I]]"; - case TIB_CHAR_MENU: - return "Menu("; + case TIB_CHAR_MENU: + return "Menu("; - case TIB_CHAR_NOT: - return "Not("; + case TIB_CHAR_NOT: + return "Not("; - case TIB_CHAR_OR: - return " Or "; + case TIB_CHAR_OR: + return " Or "; - case TIB_CHAR_OUTPUT: - return "Output("; + case TIB_CHAR_OUTPUT: + return "Output("; - case TIB_CHAR_PAUSE: - return "Pause "; + case TIB_CHAR_PAUSE: + return "Pause "; - case TIB_CHAR_PI: - return "pi"; + case TIB_CHAR_PI: + return "pi"; - case TIB_CHAR_PIC1: - return "Pic1"; + case TIB_CHAR_PIC1: + return "Pic1"; - case TIB_CHAR_PIXEL_TEST: - return "pxl-Test("; + case TIB_CHAR_PIXEL_TEST: + return "pxl-Test("; - case TIB_CHAR_RAND: - return "RAND"; + case TIB_CHAR_RAND: + return "RAND"; - case TIB_CHAR_RANDINT: - return "RandInt("; + case TIB_CHAR_RANDINT: + return "RandInt("; - case TIB_CHAR_RECALLPIC: - return "RecallPic "; + case TIB_CHAR_RECALLPIC: + return "RecallPic "; - case TIB_CHAR_REPEAT: - return "Repeat "; + case TIB_CHAR_REPEAT: + return "Repeat "; - case TIB_CHAR_RETURN: - return "Return "; + case TIB_CHAR_RETURN: + return "Return "; - case TIB_CHAR_ROUND: - return "Round("; + case TIB_CHAR_ROUND: + return "Round("; - case TIB_CHAR_SIN: - return "sin("; + case TIB_CHAR_SIN: + return "sin("; - case TIB_CHAR_STO: - return "$"; + case TIB_CHAR_STO: + return "$"; - case TIB_CHAR_STOP: - return "Stop "; + case TIB_CHAR_STOP: + return "Stop "; - case TIB_CHAR_STOREPIC: - return "StorePic "; + case TIB_CHAR_STOREPIC: + return "StorePic "; - case TIB_CHAR_TAN: - return "tan("; + case TIB_CHAR_TAN: + return "tan("; - case TIB_CHAR_TEXT: - return "Text("; + case TIB_CHAR_TEXT: + return "Text("; - case TIB_CHAR_THEN: - return "Then"; + case TIB_CHAR_THEN: + return "Then"; - case TIB_CHAR_THETA: - return "Theta"; + case TIB_CHAR_THETA: + return "Theta"; - case TIB_CHAR_WHILE: - return "While "; + case TIB_CHAR_WHILE: + return "While "; - case TIB_CHAR_XMIN: - return "Xmin"; + case TIB_CHAR_XMIN: + return "Xmin"; - case TIB_CHAR_XMAX: - return "Xmax"; + case TIB_CHAR_XMAX: + return "Xmax"; - case TIB_CHAR_XSCL: - return "Xscl"; + case TIB_CHAR_XSCL: + return "Xscl"; - case TIB_CHAR_YMIN: - return "Ymin"; + case TIB_CHAR_YMIN: + return "Ymin"; - case TIB_CHAR_YMAX: - return "Ymax"; + case TIB_CHAR_YMAX: + return "Ymax"; - case TIB_CHAR_YSCL: - return "Yscl"; + case TIB_CHAR_YSCL: + return "Yscl"; - default: - return NULL; - } + default: + return NULL; + } } static int -load_range (int beg, int end) +load_range(int beg, int end) { - int rc = 0, i; - for (i = beg; i <= end; ++i) - { - const char *trans = tib_special_char_text (i); - if (NULL == trans) - continue; - - rc = pt_add (keywords, trans, i); - if (rc) - return rc; - } - - return rc; + int rc = 0, i; + for (i = beg; i <= end; ++i) + { + const char *trans = tib_special_char_text(i); + if (NULL == trans) + continue; + + rc = pt_add(keywords, trans, i); + if (rc) + return rc; + } + + return rc; } static int -tokenize (struct tib_expr *expr, char *beg) +tokenize(struct tib_expr *expr, char *beg) { - int rc; - char *orig = beg; - size_t len = strlen (beg); - - rc = tib_expr_init (expr); - if (rc) - return rc; - - while (beg < orig + len) - { - char temp; - char *end = strchr (beg, '('); - - if (end) - { - temp = *(++end); - *end = '\0'; - - const PrefixTree *t = pt_search (keywords, beg); - *end = temp; - - if (t) - { - rc = tib_expr_push (expr, pt_data (t)); - if (rc) - goto fail; - - beg = end; - continue; - } - } - - bool found = false; - for (end = beg + 1; end <= orig + len; ++end) - { - temp = *end; - *end = '\0'; - - const PrefixTree *t = pt_search (keywords, beg); - if (t) - { - rc = tib_expr_push (expr, pt_data (t)); - if (rc) - goto fail; - - beg = end; - found = true; - } - - *end = temp; - if (found) - break; - } - - if (!found) - { - rc = tib_expr_push (expr, *beg); - if (rc) - goto fail; - - ++beg; - } - } - - return rc; + int rc; + char *orig = beg; + size_t len = strlen(beg); + + rc = tib_expr_init(expr); + if (rc) + return rc; + + while (beg < orig + len) + { + char temp; + char *end = strchr(beg, '('); + + if (end) + { + temp = *(++end); + *end = '\0'; + + const PrefixTree *t = pt_search(keywords, beg); + *end = temp; + + if (t) + { + rc = tib_expr_push(expr, pt_data(t)); + if (rc) + goto fail; + + beg = end; + continue; + } + } + + bool found = false; + for (end = beg + 1; end <= orig + len; ++end) + { + temp = *end; + *end = '\0'; + + const PrefixTree *t = pt_search(keywords, beg); + if (t) + { + rc = tib_expr_push(expr, pt_data(t)); + if (rc) + goto fail; + + beg = end; + found = true; + } + + *end = temp; + if (found) + break; + } + + if (!found) + { + rc = tib_expr_push(expr, *beg); + if (rc) + goto fail; + + ++beg; + } + } + + return rc; fail: - tib_expr_destroy (expr); - return rc; + tib_expr_destroy(expr); + return rc; } int -tib_encode_str (struct tib_expr *expr, const char *s) +tib_encode_str(struct tib_expr *expr, const char *s) { - int rc = 0; - char *buf, *beg; - size_t line_len = strlen (s); - - buf = malloc ((line_len + 1) * sizeof (char)); - if (!buf) - return TIB_EALLOC; - - strcpy (buf, s); - beg = buf; - expr->len = 0; - - while (beg < buf + line_len) - { - char *end = strchr (beg, '"'); - if (end) - *end = '\0'; - - struct tib_expr part; - rc = tokenize (&part, beg); - if (rc) - break; - - rc = tib_exprcat (expr, &part); - tib_expr_destroy (&part); - if (rc) - break; - - if (!end) - break; - - beg = end + 1; - end = strchr (beg, '"'); - - if (!end) - end = buf + line_len; - - rc = tib_expr_push (expr, '"'); - if (rc) - break; - - for (; beg < end; ++beg) - { - rc = tib_expr_push (expr, *beg); - if (rc) - goto end; - } - - if (*end) - { - rc = tib_expr_push (expr, *end); - if (rc) - break; - } - - beg = end + 1; - } + int rc = 0; + char *buf, *beg; + size_t line_len = strlen(s); + + buf = malloc((line_len + 1) * sizeof(char)); + if (!buf) + return TIB_EALLOC; + + strcpy(buf, s); + beg = buf; + expr->len = 0; + + while (beg < buf + line_len) + { + char *end = strchr(beg, '"'); + if (end) + *end = '\0'; + + struct tib_expr part; + rc = tokenize(&part, beg); + if (rc) + break; + + rc = tib_exprcat(expr, &part); + tib_expr_destroy(&part); + if (rc) + break; + + if (!end) + break; + + beg = end + 1; + end = strchr(beg, '"'); + + if (!end) + end = buf + line_len; + + rc = tib_expr_push(expr, '"'); + if (rc) + break; + + for (; beg < end; ++beg) + { + rc = tib_expr_push(expr, *beg); + if (rc) + goto end; + } + + if (*end) + { + rc = tib_expr_push(expr, *end); + if (rc) + break; + } + + beg = end + 1; + } end: - if (rc) - tib_expr_destroy (expr); + if (rc) + tib_expr_destroy(expr); - free (buf); - return rc; + free(buf); + return rc; } int -tib_keyword_init () +tib_keyword_init() { - if (keywords) - return 0; + if (keywords) + return 0; - keywords = pt_new (); - if (NULL == keywords) - return TIB_EALLOC; + keywords = pt_new(); + if (NULL == keywords) + return TIB_EALLOC; - int rc = load_range (TIB_FIRST_CHAR, TIB_LAST_CHAR); - if (rc) - tib_keyword_free (); + int rc = load_range(TIB_FIRST_CHAR, TIB_LAST_CHAR); + if (rc) + tib_keyword_free(); - return rc; + return rc; } void -tib_keyword_free () +tib_keyword_free() { - if (keywords) - { - pt_free (keywords); - keywords = NULL; - } + if (keywords) + { + pt_free(keywords); + keywords = NULL; + } } diff --git a/src/tibchar.h b/src/tibchar.h index 1b35b71..84c3521 100644 --- a/src/tibchar.h +++ b/src/tibchar.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,112 +21,112 @@ #include "tibexpr.h" enum tib_special_char - { - /* printing characters */ - TIB_CHAR_DEGREE = 128, - TIB_CHAR_EPOW10, - TIB_CHAR_LESSEQUAL, - TIB_CHAR_GREATEREQUAL, - TIB_CHAR_L1, - TIB_CHAR_L2, - TIB_CHAR_L3, - TIB_CHAR_L4, - TIB_CHAR_L5, - TIB_CHAR_L6, - TIB_CHAR_L7, - TIB_CHAR_L8, - TIB_CHAR_L9, - TIB_CHAR_PI, - TIB_CHAR_SMALL1, - TIB_CHAR_SMALL2, - TIB_CHAR_SMALL3, - TIB_CHAR_SMALL4, - TIB_CHAR_SMALL5, - TIB_CHAR_SMALL6, - TIB_CHAR_SMALL7, - TIB_CHAR_SMALL8, - TIB_CHAR_SMALL9, - TIB_CHAR_SMALL_MINUS, - TIB_CHAR_STO, - TIB_CHAR_THETA, +{ + /* printing characters */ + TIB_CHAR_DEGREE = 128, + TIB_CHAR_EPOW10, + TIB_CHAR_LESSEQUAL, + TIB_CHAR_GREATEREQUAL, + TIB_CHAR_L1, + TIB_CHAR_L2, + TIB_CHAR_L3, + TIB_CHAR_L4, + TIB_CHAR_L5, + TIB_CHAR_L6, + TIB_CHAR_L7, + TIB_CHAR_L8, + TIB_CHAR_L9, + TIB_CHAR_PI, + TIB_CHAR_SMALL1, + TIB_CHAR_SMALL2, + TIB_CHAR_SMALL3, + TIB_CHAR_SMALL4, + TIB_CHAR_SMALL5, + TIB_CHAR_SMALL6, + TIB_CHAR_SMALL7, + TIB_CHAR_SMALL8, + TIB_CHAR_SMALL9, + TIB_CHAR_SMALL_MINUS, + TIB_CHAR_STO, + TIB_CHAR_THETA, - /* "characters" expanded to strings */ - TIB_CHAR_AND, - TIB_CHAR_ANS, - TIB_CHAR_AXESOFF, - TIB_CHAR_AXESON, - TIB_CHAR_CLEARDRAW, - TIB_CHAR_CLEARHOME, - TIB_CHAR_CLRLIST, - TIB_CHAR_COS, - TIB_CHAR_DELVAR, - TIB_CHAR_DIFFERENT, - TIB_CHAR_DIM, - TIB_CHAR_DISP, - TIB_CHAR_ELSE, - TIB_CHAR_END, - TIB_CHAR_FILL, - TIB_CHAR_FOR, - TIB_CHAR_GETKEY, - TIB_CHAR_GOTO, - TIB_CHAR_IF, - TIB_CHAR_INPUT, - TIB_CHAR_INT, - TIB_CHAR_LABEL, - TIB_CHAR_LINE, - TIB_CHAR_LUSER, - TIB_CHAR_MATA, - TIB_CHAR_MATB, - TIB_CHAR_MATC, - TIB_CHAR_MATD, - TIB_CHAR_MATE, - TIB_CHAR_MATF, - TIB_CHAR_MATG, - TIB_CHAR_MATH, - TIB_CHAR_MATI, - TIB_CHAR_MENU, - TIB_CHAR_NOT, - TIB_CHAR_OR, - TIB_CHAR_OUTPUT, - TIB_CHAR_PAUSE, - TIB_CHAR_PIC1, - TIB_CHAR_PIXEL_TEST, - TIB_CHAR_RAND, - TIB_CHAR_RANDINT, - TIB_CHAR_RECALLPIC, - TIB_CHAR_REPEAT, - TIB_CHAR_RETURN, - TIB_CHAR_ROUND, - TIB_CHAR_SIN, - TIB_CHAR_STOP, - TIB_CHAR_STOREPIC, - TIB_CHAR_TAN, - TIB_CHAR_TEXT, - TIB_CHAR_THEN, - TIB_CHAR_TRANSPOSE, - TIB_CHAR_WHILE, - TIB_CHAR_XMAX, - TIB_CHAR_XMIN, - TIB_CHAR_XSCL, - TIB_CHAR_YMAX, - TIB_CHAR_YMIN, - TIB_CHAR_YSCL, + /* "characters" expanded to strings */ + TIB_CHAR_AND, + TIB_CHAR_ANS, + TIB_CHAR_AXESOFF, + TIB_CHAR_AXESON, + TIB_CHAR_CLEARDRAW, + TIB_CHAR_CLEARHOME, + TIB_CHAR_CLRLIST, + TIB_CHAR_COS, + TIB_CHAR_DELVAR, + TIB_CHAR_DIFFERENT, + TIB_CHAR_DIM, + TIB_CHAR_DISP, + TIB_CHAR_ELSE, + TIB_CHAR_END, + TIB_CHAR_FILL, + TIB_CHAR_FOR, + TIB_CHAR_GETKEY, + TIB_CHAR_GOTO, + TIB_CHAR_IF, + TIB_CHAR_INPUT, + TIB_CHAR_INT, + TIB_CHAR_LABEL, + TIB_CHAR_LINE, + TIB_CHAR_LUSER, + TIB_CHAR_MATA, + TIB_CHAR_MATB, + TIB_CHAR_MATC, + TIB_CHAR_MATD, + TIB_CHAR_MATE, + TIB_CHAR_MATF, + TIB_CHAR_MATG, + TIB_CHAR_MATH, + TIB_CHAR_MATI, + TIB_CHAR_MENU, + TIB_CHAR_NOT, + TIB_CHAR_OR, + TIB_CHAR_OUTPUT, + TIB_CHAR_PAUSE, + TIB_CHAR_PIC1, + TIB_CHAR_PIXEL_TEST, + TIB_CHAR_RAND, + TIB_CHAR_RANDINT, + TIB_CHAR_RECALLPIC, + TIB_CHAR_REPEAT, + TIB_CHAR_RETURN, + TIB_CHAR_ROUND, + TIB_CHAR_SIN, + TIB_CHAR_STOP, + TIB_CHAR_STOREPIC, + TIB_CHAR_TAN, + TIB_CHAR_TEXT, + TIB_CHAR_THEN, + TIB_CHAR_TRANSPOSE, + TIB_CHAR_WHILE, + TIB_CHAR_XMAX, + TIB_CHAR_XMIN, + TIB_CHAR_XSCL, + TIB_CHAR_YMAX, + TIB_CHAR_YMIN, + TIB_CHAR_YSCL, - /* meta */ - TIB_FIRST_CHAR = 128, - TIB_LAST_CHAR = TIB_CHAR_YSCL - }; + /* meta */ + TIB_FIRST_CHAR = 128, + TIB_LAST_CHAR = TIB_CHAR_YSCL +}; const char * -tib_special_char_text (int c); +tib_special_char_text(int c); int -tib_encode_str (struct tib_expr *dest, const char *src); +tib_encode_str(struct tib_expr *dest, const char *src); int -tib_keyword_init (void); +tib_keyword_init(void); void -tib_keyword_free (void); +tib_keyword_free(void); #endif diff --git a/src/tibdecode.c b/src/tibdecode.c index d4f0092..3ec916e 100644 --- a/src/tibdecode.c +++ b/src/tibdecode.c @@ -1,6 +1,6 @@ /* * tibdecode - Decompile a TI BASIC program - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -20,7 +20,6 @@ #include #include #include -#include #include "tiberr.h" #include "tibtranscode.h" @@ -28,95 +27,87 @@ #define USAGE_INFO "USAGE: tibdecode [options]\n\n\ tibdecode reads a TI-82 or TI-83 program from stdin and prints to stdout.\n\n\ OPTIONS:\n\ -\t-d, --debug\tShows the decimal value of unknown characters in {}\n\ -\t-h, --help\tPrints this help message and exits\n\ -\t-v, --version\tPrints version info and exits\n" +\t-d\tShows the decimal value of unknown characters in {}\n\ +\t-h\tPrints this help message and exits\n\ +\t-v\tPrints version info and exits\n" -#define VERSION_INFO "tibdecode (Delwink LiberTI) 1.0.0\n\ -Copyright (C) 2015-2016 Delwink, LLC\n\ +#define VERSION_INFO "tibdecode (Delwink LiberTI) 0.0.0\n\ +Copyright (C) 2015-2017 Delwink, LLC\n\ License AGPLv3: GNU AGPL version 3 only .\n\ This is libre software: you are free to change and redistribute it.\n\ There is NO WARRANTY, to the extent permitted by law.\n\n\ Written by David McMackins II." #if _BSD_SOURCE || _SVID_SOURCE || _XOPEN_SOURCE -# include +#include #else static int -isascii (int c) +isascii(int c) { - return c & 0x7F; + return c & 0x7F; } #endif int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - bool debug = false; + bool debug = false; - struct option longopts[] = - { - {"debug", no_argument, 0, 'd'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; + if (argc > 1) + { + int c; + while ((c = getopt(argc, argv, "dhv")) != -1) + { + switch (c) + { + case 'd': + debug = true; + break; - if (argc > 1) - { - int c; - int longindex; - while ((c = getopt_long (argc, argv, "dhv", longopts, &longindex)) != -1) - { - switch (c) - { - case 'd': - debug = true; - break; + case 'h': + puts(USAGE_INFO); + return 0; - case 'h': - puts (USAGE_INFO); - return 0; + case 'v': + puts(VERSION_INFO); + return 0; - case 'v': - puts (VERSION_INFO); - return 0; + case '?': + return 1; + } + } + } - case '?': - return 1; - } - } - } + struct tib_expr translated; + unsigned long parsed; + tib_errno = tib_fread(&translated, stdin, &parsed); + if (tib_errno) + { + fprintf(stderr, + "tibdecode: Error %d occurred while processing. Parsed %lu characters.\n", + tib_errno, parsed); + return 1; + } - struct tib_expr translated; - unsigned long parsed; - tib_errno = tib_fread (&translated, stdin, &parsed); - if (tib_errno) - { - fprintf (stderr, "tibdecode: Error %d occurred while processing. " - "Parsed %lu characters.\n", - tib_errno, parsed); - return 1; - } + char *s = tib_expr_tostr(&translated); + tib_expr_destroy(&translated); + if (NULL == s) + { + fprintf(stderr, + "tibdecode: Error %d occurred while processing\n", + tib_errno); + return 1; + } - char *s = tib_expr_tostr (&translated); - tib_expr_destroy (&translated); - if (NULL == s) - { - fprintf (stderr, "tibdecode: Error %d occurred while processing\n", - tib_errno); - return 1; - } + size_t len = strlen(s); + for (size_t i = 0; i < len; ++i) + { + if (debug && !isascii(s[i])) + printf("`%d`", s[i]); + else + putchar(s[i]); + } - size_t len = strlen (s); - for (size_t i = 0; i < len; ++i) - { - if (debug && !isascii (s[i])) - printf ("`%d`", s[i]); - else - putchar (s[i]); - } - - free (s); - return 0; + free(s); + return 0; } diff --git a/src/tibencode.c b/src/tibencode.c index a08fc69..022004f 100644 --- a/src/tibencode.c +++ b/src/tibencode.c @@ -1,6 +1,6 @@ /* * tibencode - Compile a TI BASIC program - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -19,7 +19,6 @@ #include #include #include -#include #include "tibchar.h" #include "tibtranscode.h" @@ -28,146 +27,141 @@ #define USAGE_INFO "USAGE: tibencode [options]\n\n\ tibencode reads a TI-BASIC program from stdin and prints to stdout.\n\n\ OPTIONS:\n\ -\t-h, --help\tPrints this help message and exits\n\ -\t-v, --version\tPrints version info and exits\n" +\t-h\tPrints this help message and exits\n\ +\t-v\tPrints version info and exits\n" -#define VERSION_INFO "tibencode (Delwink LiberTI) 1.0.0\n\ -Copyright (C) 2015-2016 Delwink, LLC\n\ +#define VERSION_INFO "tibencode (Delwink LiberTI) 0.0.0\n\ +Copyright (C) 2015-2017 Delwink, LLC\n\ License AGPLv3: GNU AGPL version 3 only .\n\ This is libre software: you are free to change and redistribute it.\n\ There is NO WARRANTY, to the extent permitted by law.\n\n\ Written by David McMackins II." int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - unsigned long written; - - struct option longopts[] = - { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - - if (argc > 1) - { - int c; - int longindex; - while ((c = getopt_long (argc, argv, "hv", longopts, &longindex)) != -1) - { - switch (c) - { - case 'h': - puts (USAGE_INFO); - return 0; - - case 'v': - puts (VERSION_INFO); - return 0; - - case '?': - return 1; - } - } - } - - tib_errno = tib_keyword_init (); - if (tib_errno) - { - fputs ("tibencode: Error allocating space for keyword tree.\n", stderr); - return 1; - } - - struct tib_expr translated; - tib_errno = tib_expr_init (&translated); - if (tib_errno) - { - fputs ("tibencode: Error creating expression buffer.\n", stderr); - return 1; - } - - unsigned int max_line_len = 128; - char *buf = malloc (max_line_len * sizeof (char)); - if (NULL == buf) - { - tib_expr_destroy (&translated); - fputs ("tibencode: Error allocating line buffer.\n", stderr); - return 1; - } - - int c = '\0'; - unsigned int line_len = 0; - while (c != EOF) - { - for (; line_len < max_line_len - 1; ++line_len) - { - c = getchar (); - if ('\n' == c || EOF == c) - break; - - buf[line_len] = c; - } - - if (max_line_len - 1 == line_len) - { - char *old = buf; - - max_line_len *= 2; - buf = realloc (buf, max_line_len * sizeof (char)); - if (!buf) - { - free (old); - tib_errno = TIB_EALLOC; - goto end; - } - - continue; - } - - buf[line_len] = '\0'; - - struct tib_expr line; - tib_errno = tib_encode_str (&line, buf); - if (tib_errno) - goto end; - - tib_errno = tib_exprcat (&translated, &line); - tib_expr_destroy (&line); - if (tib_errno) - goto end; - - if (c != EOF) - { - tib_errno = tib_expr_push (&translated, '\n'); - if (tib_errno) - goto end; - } - - line_len = 0; - } + unsigned long written; + + if (argc > 1) + { + int c; + while ((c = getopt(argc, argv, "hv")) != -1) + { + switch (c) + { + case 'h': + puts(USAGE_INFO); + return 0; + + case 'v': + puts(VERSION_INFO); + return 0; + + case '?': + return 1; + } + } + } + + tib_errno = tib_keyword_init(); + if (tib_errno) + { + fputs("tibencode: Error allocating space for keyword tree.\n", + stderr); + return 1; + } + + struct tib_expr translated; + tib_errno = tib_expr_init(&translated); + if (tib_errno) + { + fputs("tibencode: Error creating expression buffer.\n", + stderr); + return 1; + } + + unsigned int max_line_len = 128; + char *buf = malloc(max_line_len * sizeof(char)); + if (NULL == buf) + { + tib_expr_destroy(&translated); + fputs("tibencode: Error allocating line buffer.\n", stderr); + return 1; + } + + int c = '\0'; + unsigned int line_len = 0; + while (c != EOF) + { + for (; line_len < max_line_len - 1; ++line_len) + { + c = getchar(); + if ('\n' == c || EOF == c) + break; + + buf[line_len] = c; + } + + if (max_line_len - 1 == line_len) + { + char *old = buf; + + max_line_len *= 2; + buf = realloc(buf, max_line_len * sizeof(char)); + if (!buf) + { + free(old); + tib_errno = TIB_EALLOC; + goto end; + } + + continue; + } + + buf[line_len] = '\0'; + + struct tib_expr line; + tib_errno = tib_encode_str(&line, buf); + if (tib_errno) + goto end; + + tib_errno = tib_exprcat(&translated, &line); + tib_expr_destroy(&line); + if (tib_errno) + goto end; + + if (c != EOF) + { + tib_errno = tib_expr_push(&translated, '\n'); + if (tib_errno) + goto end; + } + + line_len = 0; + } end: - free (buf); - tib_keyword_free (); - - if (tib_errno) - { - tib_expr_destroy (&translated); - fprintf (stderr, "tibencode: Error %d occurred while assembling.\n", - tib_errno); - return 1; - } - - tib_errno = tib_fwrite (stdout, &translated, &written); - tib_expr_destroy (&translated); - if (tib_errno) - { - fprintf (stderr, "tibencode: Error %d occurred while processing. " - "Wrote %lu characters.\n", - tib_errno, written); - return 1; - } - - return 0; + free(buf); + tib_keyword_free(); + + if (tib_errno) + { + tib_expr_destroy(&translated); + fprintf(stderr, + "tibencode: Error %d occurred while assembling.\n", + tib_errno); + return 1; + } + + tib_errno = tib_fwrite(stdout, &translated, &written); + tib_expr_destroy(&translated); + if (tib_errno) + { + fprintf(stderr, + "tibencode: Error %d occurred while processing. Wrote %lu characters.\n", + tib_errno, written); + return 1; + } + + return 0; } diff --git a/src/tiberr.h b/src/tiberr.h index b236510..696a249 100644 --- a/src/tiberr.h +++ b/src/tiberr.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -19,22 +19,22 @@ #define DELWINK_TIB_ERR_H enum tib_err - { - TIB_EALLOC = -1, - TIB_EINDEX = -2, - TIB_ESYNTAX = -3, - TIB_ETYPE = -4, - TIB_EDIM = -5, - TIB_ENULLPTR = -6, - TIB_EDOMAIN = -7, - TIB_EBADCHAR = -8, - TIB_EWRITE = -9, - TIB_EBADFILE = -10, - TIB_EBADFUNC = -11, - TIB_EARGNUM = -12, - TIB_DBYZERO = -13, - TIB_EOVER = -14 - }; +{ + TIB_EALLOC = -1, + TIB_EINDEX = -2, + TIB_ESYNTAX = -3, + TIB_ETYPE = -4, + TIB_EDIM = -5, + TIB_ENULLPTR = -6, + TIB_EDOMAIN = -7, + TIB_EBADCHAR = -8, + TIB_EWRITE = -9, + TIB_EBADFILE = -10, + TIB_EBADFUNC = -11, + TIB_EARGNUM = -12, + TIB_DBYZERO = -13, + TIB_EOVER = -14 +}; extern int tib_errno; diff --git a/src/tibeval.c b/src/tibeval.c index 3f1f182..364d569 100644 --- a/src/tibeval.c +++ b/src/tibeval.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -26,787 +26,798 @@ #include "tibvar.h" enum math_operator_function_type - { - T, - TT - }; +{ + T, + TT +}; struct math_operator { - union - { - TIB *(*t) (const TIB *); - TIB *(*tt) (const TIB *, const TIB *); - } func; + union + { + TIB *(*t)(const TIB *); + TIB *(*tt)(const TIB *, const TIB *); + } func; - enum math_operator_function_type function_type; + enum math_operator_function_type function_type; - int c; - int priority; + int c; + int priority; }; -static const struct math_operator OPERATORS[] = - { - { { .t = tib_factorial }, T, '!', 0 }, - { { .t = tib_toradians }, T, TIB_CHAR_DEGREE, 0 }, - { { .tt = tib_pow }, TT, '^', 1 }, - { { .tt = tib_mul }, TT, '*', 2 }, - { { .tt = tib_div }, TT, '/', 2 }, - { { .tt = tib_add }, TT, '+', 3 }, - { { .tt = tib_sub }, TT, '-', 3 } - }; +static const struct math_operator OPERATORS[] = { + { {.t = tib_factorial }, T, '!', 0}, + { {.t = tib_toradians }, T, TIB_CHAR_DEGREE, 0}, + { {.tt = tib_pow }, TT, '^', 1}, + { {.tt = tib_mul }, TT, '*', 2}, + { {.tt = tib_div }, TT, '/', 2}, + { {.tt = tib_add }, TT, '+', 3}, + { {.tt = tib_sub }, TT, '-', 3} +}; #define NUM_MATH_OPERATORS (sizeof OPERATORS / sizeof (struct math_operator)) #define LAST_PRIORITY 3 static bool -is_var_char (int c) +is_var_char(int c) { - return isupper (c) || TIB_CHAR_THETA == c; + return isupper(c) || TIB_CHAR_THETA == c; } static bool -needs_mult_common (int c) +needs_mult_common(int c) { - return (isdigit (c) || is_var_char (c) || tib_is_var (c)); + return (isdigit(c) || is_var_char(c) || tib_is_var(c)); } static bool -needs_mult_right (int c) +needs_mult_right(int c) { - return (needs_mult_common (c) || tib_is_func (c)); + return (needs_mult_common(c) || tib_is_func(c)); } static bool -needs_mult_left (int c) +needs_mult_left(int c) { - return (needs_mult_common (c) || ')' == c); + return (needs_mult_common(c) || ')' == c); } bool -is_sign_operator (int c) +is_sign_operator(int c) { - return ('+' == c || '-' == c); + return ('+' == c || '-' == c); } static const struct math_operator * -get_math_operator (int c) +get_math_operator(int c) { - for (unsigned int i = 0; i < NUM_MATH_OPERATORS; ++i) - if (OPERATORS[i].c == c) - return &OPERATORS[i]; + for (unsigned int i = 0; i < NUM_MATH_OPERATORS; ++i) + if (OPERATORS[i].c == c) + return &OPERATORS[i]; - return NULL; + return NULL; } bool -is_math_operator (int c) +is_math_operator(int c) { - return get_math_operator (c) != NULL; + return get_math_operator(c) != NULL; } unsigned int -sign_count (const struct tib_expr *expr) +sign_count(const struct tib_expr *expr) { - int i; - unsigned int out = 0; + int i; + unsigned int out = 0; - tib_expr_foreach (expr, i) - if (is_sign_operator (expr->data[i])) - ++out; + tib_expr_foreach(expr, i) + if (is_sign_operator(expr->data[i])) + ++out; - return out; + return out; } bool -contains_i (const struct tib_expr *expr) +contains_i(const struct tib_expr *expr) { - int i; + int i; - tib_expr_foreach (expr, i) - if ('i' == expr->data[i]) - return true; + tib_expr_foreach(expr, i) + if ('i' == expr->data[i]) + return true; - return false; + return false; } static int -replace_epow10 (struct tib_expr *expr) +replace_epow10(struct tib_expr *expr) { - int i; - - tib_expr_foreach (expr, i) - { - if (TIB_CHAR_EPOW10 == expr->data[i]) - { - expr->data[i++] = '*'; - - const char *s = "10^"; - for (; *s != '\0'; ++s, ++i) - { - int rc = tib_expr_insert (expr, i, *s); - if (rc) - return rc; - } - } - } - - return 0; + int i; + + tib_expr_foreach(expr, i) + { + if (TIB_CHAR_EPOW10 == expr->data[i]) + { + expr->data[i++] = '*'; + + const char *s = "10^"; + for (; *s != '\0'; ++s, ++i) + { + int rc = tib_expr_insert(expr, i, *s); + if (rc) + return rc; + } + } + } + + return 0; } static TIB * -single_eval (const struct tib_expr *expr) +single_eval(const struct tib_expr *expr) { - int len = expr->len; - - if (0 == len) - return tib_empty (); - - if (1 == len && (is_var_char (expr->data[0]) || tib_is_var (expr->data[0]))) - return tib_var_get (expr->data[0]); - - int func = tib_eval_surrounded (expr); - if (func) - { - struct tib_expr temp; - tib_subexpr (&temp, expr, 1, len - 1); - return tib_call (func, &temp); - } - - if (tib_eval_isnum (expr)) - { - gsl_complex z; - tib_errno = tib_expr_parse_complex (expr, &z); - return tib_errno ? NULL : tib_new_complex (GSL_REAL (z), GSL_IMAG (z)); - } - - if (tib_eval_isstr (expr)) - { - char *s = tib_expr_tostr (expr); - if (NULL == s) - return NULL; - - TIB *temp = tib_new_str (s); - free (s); - - return temp; - } - - tib_errno = TIB_ESYNTAX; - return NULL; + int len = expr->len; + + if (0 == len) + return tib_empty(); + + if (1 == len + && (is_var_char(expr->data[0]) || tib_is_var(expr->data[0]))) + return tib_var_get(expr->data[0]); + + int func = tib_eval_surrounded(expr); + if (func) + { + struct tib_expr temp; + tib_subexpr(&temp, expr, 1, len - 1); + return tib_call(func, &temp); + } + + if (tib_eval_isnum(expr)) + { + gsl_complex z; + tib_errno = tib_expr_parse_complex(expr, &z); + return tib_errno ? NULL : tib_new_complex(GSL_REAL(z), + GSL_IMAG(z)); + } + + if (tib_eval_isstr(expr)) + { + char *s = tib_expr_tostr(expr); + if (NULL == s) + return NULL; + + TIB *temp = tib_new_str(s); + free(s); + + return temp; + } + + tib_errno = TIB_ESYNTAX; + return NULL; } TIB * -tib_eval (const struct tib_expr *in) +tib_eval(const struct tib_expr *in) { - int i; - - if (0 == in->len) - return tib_empty (); - - /* check for store operator */ - i = tib_expr_indexof (in, TIB_CHAR_STO); - if (i >= 0) - { - if (i != in->len - 2 || 0 == i) - { - tib_errno = TIB_ESYNTAX; - return NULL; - } - - int c = in->data[i + 1]; - if (!is_var_char (c)) - { - tib_errno = TIB_ESYNTAX; - return NULL; - } - - struct tib_expr e; - tib_subexpr (&e, in, 0, i); - - TIB *stoval = tib_eval (&e); - if (NULL == stoval) - return NULL; - - tib_errno = tib_var_set (c, stoval); - if (tib_errno) - { - tib_decref (stoval); - return NULL; - } - - return stoval; - } - - struct tib_expr expr = { .bufsize = 0 }; - tib_errno = tib_exprcpy (&expr, in); - if (tib_errno) - return NULL; - - /* check for sign operator at the beginning of number */ - if (expr.len > 0 && ('-' == expr.data[0] || '+' == expr.data[0])) - { - tib_errno = tib_expr_insert (&expr, 0, '0'); - if (tib_errno) - { - tib_expr_destroy (&expr); - return NULL; - } - } - - /* check for implicit closing parentheses and close them */ - tib_errno = tib_eval_close_parens (&expr); - if (tib_errno) - { - tib_expr_destroy (&expr); - return NULL; - } - - /* replace power of 10 E character with "*10^" */ - tib_errno = replace_epow10 (&expr); - if (tib_errno) - { - tib_expr_destroy (&expr); - return NULL; - } - - /* add multiplication operators between implicit multiplications */ - bool add = true; - tib_expr_foreach (&expr, i) - { - int c = expr.data[i]; - - if ('"' == c) - { - add = !add; /* don't change anything inside a string */ - } - else if (add) - { - if (is_var_char (c) || tib_is_var (c)) - { - if (i > 0 && needs_mult_left (expr.data[i - 1])) - tib_errno = tib_expr_insert (&expr, i++, '*'); - - if (!tib_errno && i < expr.len - 1 - && needs_mult_right (expr.data[i + 1])) - tib_errno = tib_expr_insert (&expr, ++i, '*'); - } - else if (i > 0 && i < expr.len - 1) - { - if (tib_is_func (c) && needs_mult_left (expr.data[i - 1])) - tib_errno = tib_expr_insert (&expr, i++, '*'); - else if (')' == c && needs_mult_right (expr.data[i + 1])) - tib_errno = tib_expr_insert (&expr, ++i, '*'); - } - - if (tib_errno) - { - tib_expr_destroy (&expr); - return NULL; - } - } - } - - /* this is temp storage for internally-resolved portions */ - struct tib_lst *resolved = tib_new_lst (); - if (!resolved) - { - tib_expr_destroy (&expr); - tib_errno = TIB_EALLOC; - return NULL; - } - - /* this is to remember the operations to be executed */ - struct tib_expr calc; - tib_errno = tib_expr_init (&calc); - if (tib_errno) - { - tib_expr_destroy (&expr); - tib_free_lst (resolved); - return NULL; - } - - /* resolve operand expressions, and store the values for later */ - int beg = 0, numpar = 0; - add = true; - tib_expr_foreach (&expr, i) - { - int c = expr.data[i]; - - if ('"' == c) - { - add = !add; - continue; - } - - if (!add) - continue; - - if (tib_is_func (c)) - { - ++numpar; - } - else if (')' == c) - { - if (0 == numpar) - { - tib_errno = TIB_ESYNTAX; - break; - } - - --numpar; - } - - const struct math_operator *oper; - if (0 == numpar && (oper = get_math_operator (c)) != NULL) - { - struct tib_expr sub; - tib_subexpr (&sub, &expr, beg, i); - - TIB *part = single_eval (&sub); - if (!part) - break; - - if (T == oper->function_type) - { - do - { - TIB *temp = oper->func.t (part); - tib_decref (part); - if (!temp) - break; - - part = temp; - } - while (++i < expr.len - && (oper = get_math_operator (expr.data[i])) != NULL - && T == oper->function_type); - - if (tib_errno) - break; - - tib_errno = tib_lst_push (resolved, part); - tib_decref (part); - if (tib_errno) - break; - - if (i < expr.len) - { - c = expr.data[i]; - - if (is_math_operator (c)) - { - tib_errno = tib_expr_push (&calc, c); - if (tib_errno) - break; - - ++i; - } - else - { - tib_errno = tib_expr_push (&calc, '*'); - if (tib_errno) - break; - } - - beg = i; - } - } - else - { - tib_errno = tib_lst_push (resolved, part); - tib_decref (part); - if (tib_errno) - break; - - tib_errno = tib_expr_push (&calc, c); - if (tib_errno) - break; - - beg = i + 1; - } - } - } - - if (!tib_errno) - { - const struct math_operator *oper; - - if (tib_lst_len (resolved) == 0) - { - TIB *temp = single_eval (&expr); - if (!temp) - goto end; - - tib_errno = tib_lst_push (resolved, temp); - tib_decref (temp); - if (tib_errno) - goto end; - } - else if (NULL == (oper = get_math_operator (expr.data[expr.len - 1])) - || oper->function_type != T) - { - struct tib_expr sub; - tib_subexpr (&sub, &expr, beg, i); - - TIB *temp = single_eval (&sub); - if (!temp) - goto end; - - tib_errno = tib_lst_push (resolved, temp); - tib_decref (temp); - if (tib_errno) - goto end; - } - - if (tib_lst_len (resolved) != calc.len + 1) - tib_errno = TIB_ESYNTAX; - } - - tib_expr_destroy (&expr); - - if (tib_errno) - goto end; - - for (int priority = 1; priority <= LAST_PRIORITY; ++priority) - { - for (i = 0; i < calc.len; ++i) - { - const struct math_operator *oper = get_math_operator (calc.data[i]); - if (oper->priority != priority) - continue; - - TIB *t; - unsigned int num_operands; - switch (oper->function_type) - { - case TT: - t = oper->func.tt (tib_lst_ref (resolved, i), - tib_lst_ref (resolved, i + 1)); - if (!t) - goto end; - - num_operands = 2; - break; - - default: - tib_errno = TIB_ESYNTAX; - goto end; - } - - for (unsigned int _ = 0; _ < num_operands; ++_) - tib_lst_remove (resolved, i); - - tib_errno = tib_lst_insert (resolved, t, i); - tib_decref (t); - - if (tib_errno) - goto end; - - tib_expr_delete (&calc, i--); - } - } + int i; + + if (0 == in->len) + return tib_empty(); + + /* check for store operator */ + i = tib_expr_indexof(in, TIB_CHAR_STO); + if (i >= 0) + { + if (i != in->len - 2 || 0 == i) + { + tib_errno = TIB_ESYNTAX; + return NULL; + } + + int c = in->data[i + 1]; + if (!is_var_char(c)) + { + tib_errno = TIB_ESYNTAX; + return NULL; + } + + struct tib_expr e; + tib_subexpr(&e, in, 0, i); + + TIB *stoval = tib_eval(&e); + if (NULL == stoval) + return NULL; + + tib_errno = tib_var_set(c, stoval); + if (tib_errno) + { + tib_decref(stoval); + return NULL; + } + + return stoval; + } + + struct tib_expr expr = {.bufsize = 0 }; + tib_errno = tib_exprcpy(&expr, in); + if (tib_errno) + return NULL; + + // check for sign operator at the beginning of number + if (expr.len > 0 && ('-' == expr.data[0] || '+' == expr.data[0])) + { + tib_errno = tib_expr_insert(&expr, 0, '0'); + if (tib_errno) + { + tib_expr_destroy(&expr); + return NULL; + } + } + + // check for implicit closing parentheses and close them + tib_errno = tib_eval_close_parens(&expr); + if (tib_errno) + { + tib_expr_destroy(&expr); + return NULL; + } + + // replace power of 10 E character with "*10^" + tib_errno = replace_epow10(&expr); + if (tib_errno) + { + tib_expr_destroy(&expr); + return NULL; + } + + // add multiplication operators between implicit multiplications + bool add = true; + tib_expr_foreach(&expr, i) + { + int c = expr.data[i]; + + if ('"' == c) + { + add = !add; // don't change anything inside a string + } + else if (add) + { + if (is_var_char(c) || tib_is_var(c)) + { + if (i > 0 && needs_mult_left(expr.data[i - 1])) + tib_errno = tib_expr_insert(&expr, + i++, '*'); + + if (!tib_errno && i < expr.len - 1 + && needs_mult_right(expr.data[i + 1])) + tib_errno = tib_expr_insert(&expr, + ++i, '*'); + } + else if (i > 0 && i < expr.len - 1) + { + if (tib_is_func(c) + && needs_mult_left(expr.data[i - 1])) + tib_errno = tib_expr_insert(&expr, + i++, '*'); + else if (')' == c + && needs_mult_right(expr.data[i + 1])) + tib_errno = tib_expr_insert(&expr, + ++i, '*'); + } + + if (tib_errno) + { + tib_expr_destroy(&expr); + return NULL; + } + } + } + + // this is temp storage for internally-resolved portions + struct tib_lst *resolved = tib_new_lst(); + if (!resolved) + { + tib_expr_destroy(&expr); + tib_errno = TIB_EALLOC; + return NULL; + } + + // this is to remember the operations to be executed + struct tib_expr calc; + tib_errno = tib_expr_init(&calc); + if (tib_errno) + { + tib_expr_destroy(&expr); + tib_free_lst(resolved); + return NULL; + } + + // resolve operand expressions, and store the values for later + int beg = 0, numpar = 0; + add = true; + tib_expr_foreach(&expr, i) + { + int c = expr.data[i]; + + if ('"' == c) + { + add = !add; + continue; + } + + if (!add) + continue; + + if (tib_is_func(c)) + { + ++numpar; + } + else if (')' == c) + { + if (0 == numpar) + { + tib_errno = TIB_ESYNTAX; + break; + } + + --numpar; + } + + const struct math_operator *oper; + if (0 == numpar && (oper = get_math_operator(c)) != NULL) + { + struct tib_expr sub; + tib_subexpr(&sub, &expr, beg, i); + + TIB *part = single_eval(&sub); + if (!part) + break; + + if (T == oper->function_type) + { + do + { + TIB *temp = oper->func.t(part); + tib_decref(part); + if (!temp) + break; + + part = temp; + } while (++i < expr.len + && (oper = get_math_operator(expr.data[i])) != NULL + && T == oper->function_type); + + if (tib_errno) + break; + + tib_errno = tib_lst_push(resolved, part); + tib_decref(part); + if (tib_errno) + break; + + if (i < expr.len) + { + c = expr.data[i]; + + if (is_math_operator(c)) + { + tib_errno = tib_expr_push(&calc, + c); + if (tib_errno) + break; + + ++i; + } + else + { + tib_errno = tib_expr_push(&calc, + '*'); + if (tib_errno) + break; + } + + beg = i; + } + } + else + { + tib_errno = tib_lst_push(resolved, part); + tib_decref(part); + if (tib_errno) + break; + + tib_errno = tib_expr_push(&calc, c); + if (tib_errno) + break; + + beg = i + 1; + } + } + } + + if (!tib_errno) + { + const struct math_operator *oper; + + if (tib_lst_len(resolved) == 0) + { + TIB *temp = single_eval(&expr); + if (!temp) + goto end; + + tib_errno = tib_lst_push(resolved, temp); + tib_decref(temp); + if (tib_errno) + goto end; + } + else if (NULL == + (oper = get_math_operator(expr.data[expr.len - 1])) + || oper->function_type != T) + { + struct tib_expr sub; + tib_subexpr(&sub, &expr, beg, i); + + TIB *temp = single_eval(&sub); + if (!temp) + goto end; + + tib_errno = tib_lst_push(resolved, temp); + tib_decref(temp); + if (tib_errno) + goto end; + } + + if (tib_lst_len(resolved) != calc.len + 1) + tib_errno = TIB_ESYNTAX; + } + + tib_expr_destroy(&expr); + + if (tib_errno) + goto end; + + for (int priority = 1; priority <= LAST_PRIORITY; ++priority) + { + for (i = 0; i < calc.len; ++i) + { + const struct math_operator *oper = + get_math_operator(calc.data[i]); + if (oper->priority != priority) + continue; + + TIB *t; + unsigned int num_operands; + switch (oper->function_type) + { + case TT: + t = oper->func.tt(tib_lst_ref(resolved, i), + tib_lst_ref(resolved, i + 1)); + if (!t) + goto end; + + num_operands = 2; + break; + + default: + tib_errno = TIB_ESYNTAX; + goto end; + } + + for (unsigned int _ = 0; _ < num_operands; ++_) + tib_lst_remove(resolved, i); + + tib_errno = tib_lst_insert(resolved, t, i); + tib_decref(t); + + if (tib_errno) + goto end; + + tib_expr_delete(&calc, i--); + } + } end: - tib_expr_destroy (&calc); - - TIB *out = NULL; - if (!tib_errno) - { - if (tib_lst_len (resolved) != 1) - { - tib_errno = TIB_ESYNTAX; - } - else - { - out = tib_lst_ref (resolved, 0); - tib_incref (out); - } - } - - tib_free_lst (resolved); - - return out; + tib_expr_destroy(&calc); + + TIB *out = NULL; + if (!tib_errno) + { + if (tib_lst_len(resolved) != 1) + { + tib_errno = TIB_ESYNTAX; + } + else + { + out = tib_lst_ref(resolved, 0); + tib_incref(out); + } + } + + tib_free_lst(resolved); + + return out; } int -tib_eval_surrounded (const struct tib_expr *expr) +tib_eval_surrounded(const struct tib_expr *expr) { - int count = 0, opening = expr->data[0], len = expr->len; + int count = 0, opening = expr->data[0], len = expr->len; - if (len > 2 && tib_is_func (opening) && ')' == expr->data[len - 1]) - { - count = 1; + if (len > 2 && tib_is_func(opening) && ')' == expr->data[len - 1]) + { + count = 1; - for (int i = 1; i < len-1; ++i) - { - int c = expr->data[i]; + for (int i = 1; i < len - 1; ++i) + { + int c = expr->data[i]; - if (tib_is_func (c)) - ++count; - else if (')' == c && --count == 0) - return 0; - } + if (tib_is_func(c)) + ++count; + else if (')' == c && --count == 0) + return 0; + } - return opening; - } + return opening; + } - return 0; + return 0; } static int -char_count (const struct tib_expr *expr, int c) +char_count(const struct tib_expr *expr, int c) { - int i, count = 0; + int i, count = 0; - tib_expr_foreach (expr, i) - if (c == expr->data[i]) - ++count; + tib_expr_foreach(expr, i) + if (c == expr->data[i]) + ++count; - return count; + return count; } int -i_count (const struct tib_expr *expr) +i_count(const struct tib_expr *expr) { - return char_count (expr, 'i'); + return char_count(expr, 'i'); } static int -dot_count (const struct tib_expr *expr) +dot_count(const struct tib_expr *expr) { - return char_count (expr, '.'); + return char_count(expr, '.'); } static bool -is_number_char (int c) +is_number_char(int c) { - return (isdigit (c) || '.' == c || 'i' == c || is_sign_operator (c)); + return (isdigit(c) || '.' == c || 'i' == c || is_sign_operator(c)); } int -get_char_pos (const struct tib_expr *expr, int c, int which) +get_char_pos(const struct tib_expr *expr, int c, int which) { - int i, found = 0; + int i, found = 0; - tib_expr_foreach (expr, i) - { - if (c == expr->data[i] && ++found == which) - break; - } + tib_expr_foreach(expr, i) + { + if (c == expr->data[i] && ++found == which) + break; + } - return i; + return i; } static int -get_sign_pos (const struct tib_expr *expr, int which) +get_sign_pos(const struct tib_expr *expr, int which) { - int i, found = 0; + int i, found = 0; - tib_expr_foreach (expr, i) - { - if (is_sign_operator (expr->data[i]) && ++found == which) - break; - } + tib_expr_foreach(expr, i) + { + if (is_sign_operator(expr->data[i]) && ++found == which) + break; + } - return i; + return i; } static bool -good_sign_pos (const struct tib_expr *expr, int numsign, int numi) +good_sign_pos(const struct tib_expr *expr, int numsign, int numi) { - switch (numsign) - { - case 0: - return true; - - case 1: - if (!numi && get_sign_pos (expr, 1) != 0) - return false; - break; - - case 2: - if (!numi || get_sign_pos (expr, 1) != 0 - || get_sign_pos (expr, 2) > get_char_pos (expr, 'i', 1)) - return false; - break; - - default: - return false; - } - - return true; + switch (numsign) + { + case 0: + return true; + + case 1: + if (!numi && get_sign_pos(expr, 1) != 0) + return false; + break; + + case 2: + if (!numi || get_sign_pos(expr, 1) != 0 + || get_sign_pos(expr, 2) > get_char_pos(expr, 'i', 1)) + return false; + break; + + default: + return false; + } + + return true; } bool -tib_eval_isnum (const struct tib_expr *expr) +tib_eval_isnum(const struct tib_expr *expr) { - int signs = sign_count (expr); - int dots = dot_count (expr); - int is = i_count (expr); + int signs = sign_count(expr); + int dots = dot_count(expr); + int is = i_count(expr); - if (signs > 2 || dots > 2 || is > 1) - return false; + if (signs > 2 || dots > 2 || is > 1) + return false; - if (!good_sign_pos (expr, signs, is)) - return false; + if (!good_sign_pos(expr, signs, is)) + return false; - if (is && get_char_pos (expr, 'i', 1) < expr->len - 1) - return false; + if (is && get_char_pos(expr, 'i', 1) < expr->len - 1) + return false; - int i; - tib_expr_foreach (expr, i) - if (!is_number_char (expr->data[i])) - return false; + int i; + tib_expr_foreach(expr, i) + if (!is_number_char(expr->data[i])) + return false; - return true; + return true; } bool -tib_eval_isstr (const struct tib_expr *expr) +tib_eval_isstr(const struct tib_expr *expr) { - int len = expr->len; + int len = expr->len; - if (len > 1 && '"' == expr->data[0]) - { - for (int i = 1; i < len-1; ++i) - { - int c = expr->data[i]; + if (len > 1 && '"' == expr->data[0]) + { + for (int i = 1; i < len - 1; ++i) + { + int c = expr->data[i]; - if (c > 127 || '"' == c) - return false; - } + if (c > 127 || '"' == c) + return false; + } - return true; - } + return true; + } - return false; + return false; } bool -tib_eval_islist (const struct tib_expr *expr) +tib_eval_islist(const struct tib_expr *expr) { - int len = expr->len; + int len = expr->len; - if (len > 2 && '{' == expr->data[0] && '}' == expr->data[len - 1]) - { - for (int i = 1; i < len-1; ++i) - { - int c = expr->data[i]; + if (len > 2 && '{' == expr->data[0] && '}' == expr->data[len - 1]) + { + for (int i = 1; i < len - 1; ++i) + { + int c = expr->data[i]; - if ('{' == c || '}' == c) - return false; - } + if ('{' == c || '}' == c) + return false; + } - return true; - } + return true; + } - return false; + return false; } static bool -sub_isnum (const struct tib_expr *expr, int beg, int end) +sub_isnum(const struct tib_expr *expr, int beg, int end) { - if (end <= beg) - return false; + if (end <= beg) + return false; - struct tib_expr temp; - int rc = tib_subexpr (&temp, expr, beg, end); - if (rc) - return false; + struct tib_expr temp; + int rc = tib_subexpr(&temp, expr, beg, end); + if (rc) + return false; - return tib_eval_isnum (&temp); + return tib_eval_isnum(&temp); } bool -tib_eval_ismatrix (const struct tib_expr *expr) +tib_eval_ismatrix(const struct tib_expr *expr) { - int len = expr->len; - - if (len > 4 && '[' == expr->data[0] && '[' == expr->data[1] - && ']' == expr->data[len - 1]) - { - int i = 2; - int open_brackets = i, fdim = 1, dim = 1, beg = i, end = i; - bool first = true; - - for (; i < len; ++i) - { - int c = expr->data[i]; - - switch (c) - { - case '[': - ++open_brackets; - beg = i + 1; - break; - - case ']': - --open_brackets; - - if (!first && dim != fdim) - return false; - - first = false; - dim = 1; - end = i - 1; - - if (!sub_isnum (expr, beg, end)) - return false; - break; - - case ',': - if (first) - ++fdim; - else - ++dim; - - end = i - 1; - if (!sub_isnum (expr, beg, end)) - return false; - beg = i + 1; - break; - } - - if ((0 == open_brackets && i != len-1) || open_brackets > 2) - return false; - } - - return true; - } - - return false; + int len = expr->len; + + if (len > 4 && '[' == expr->data[0] && '[' == expr->data[1] + && ']' == expr->data[len - 1]) + { + int i = 2; + int open_brackets = i, fdim = 1, dim = 1, beg = i, end = i; + bool first = true; + + for (; i < len; ++i) + { + int c = expr->data[i]; + + switch (c) + { + case '[': + ++open_brackets; + beg = i + 1; + break; + + case ']': + --open_brackets; + + if (!first && dim != fdim) + return false; + + first = false; + dim = 1; + end = i - 1; + + if (!sub_isnum(expr, beg, end)) + return false; + break; + + case ',': + if (first) + ++fdim; + else + ++dim; + + end = i - 1; + if (!sub_isnum(expr, beg, end)) + return false; + beg = i + 1; + break; + } + + if ((0 == open_brackets && i != len - 1) + || open_brackets > 2) + return false; + } + + return true; + } + + return false; } int -tib_eval_close_parens (struct tib_expr *expr) +tib_eval_close_parens(struct tib_expr *expr) { - int count = 0, len = expr->len; - bool str = false; - - for (int i = 0; i < len; ++i) - { - int c = expr->data[i]; - - if ('"' == c) - str = !str; - - if (!str) - { - if (tib_is_func (c)) - ++count; - - if (')' == c) - --count; - } - } - - while (count--) - { - int rc = tib_expr_push (expr, ')'); - if (rc) - return rc; - } - - return 0; + int count = 0, len = expr->len; + bool str = false; + + for (int i = 0; i < len; ++i) + { + int c = expr->data[i]; + + if ('"' == c) + str = !str; + + if (!str) + { + if (tib_is_func(c)) + ++count; + + if (')' == c) + --count; + } + } + + while (count--) + { + int rc = tib_expr_push(expr, ')'); + if (rc) + return rc; + } + + return 0; } diff --git a/src/tibeval.h b/src/tibeval.h index 0257aae..c1b1f83 100644 --- a/src/tibeval.h +++ b/src/tibeval.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,36 +24,36 @@ #include "tibtype.h" bool -is_sign_operator (int c); +is_sign_operator(int c); bool -is_math_operator (int c); +is_math_operator(int c); unsigned int -sign_count (const struct tib_expr *expr); +sign_count(const struct tib_expr *expr); bool -contains_i (const struct tib_expr *expr); +contains_i(const struct tib_expr *expr); TIB * -tib_eval (const struct tib_expr *expr); +tib_eval(const struct tib_expr *expr); int -tib_eval_surrounded (const struct tib_expr *expr); +tib_eval_surrounded(const struct tib_expr *expr); bool -tib_eval_isnum (const struct tib_expr *expr); +tib_eval_isnum(const struct tib_expr *expr); bool -tib_eval_isstr (const struct tib_expr *expr); +tib_eval_isstr(const struct tib_expr *expr); bool -tib_eval_islist (const struct tib_expr *expr); +tib_eval_islist(const struct tib_expr *expr); bool -tib_eval_ismatrix (const struct tib_expr *expr); +tib_eval_ismatrix(const struct tib_expr *expr); int -tib_eval_close_parens (struct tib_expr *expr); +tib_eval_close_parens(struct tib_expr *expr); #endif diff --git a/src/tibexpr.c b/src/tibexpr.c index 7ab48b8..2f122d2 100644 --- a/src/tibexpr.c +++ b/src/tibexpr.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -26,267 +26,267 @@ #define BUFFER_BLOCK_SIZE 16 int -tib_expr_init (struct tib_expr *self) +tib_expr_init(struct tib_expr *self) { - self->data = malloc (BUFFER_BLOCK_SIZE * sizeof (int)); - if (!self->data) - return TIB_EALLOC; + self->data = malloc(BUFFER_BLOCK_SIZE * sizeof(int)); + if (!self->data) + return TIB_EALLOC; - self->bufsize = BUFFER_BLOCK_SIZE; - self->len = 0; + self->bufsize = BUFFER_BLOCK_SIZE; + self->len = 0; - return 0; + return 0; } void -tib_expr_destroy (struct tib_expr *self) +tib_expr_destroy(struct tib_expr *self) { - if (self->bufsize) - { - free (self->data); - - self->data = NULL; - self->bufsize = 0; - self->len = 0; - } + if (self->bufsize) + { + free(self->data); + + self->data = NULL; + self->bufsize = 0; + self->len = 0; + } } int -tib_exprcpy (struct tib_expr *dest, const struct tib_expr *src) +tib_exprcpy(struct tib_expr *dest, const struct tib_expr *src) { - dest->len = 0; - return tib_exprcat (dest, src); + dest->len = 0; + return tib_exprcat(dest, src); } int -tib_exprcat (struct tib_expr *dest, const struct tib_expr *src) +tib_exprcat(struct tib_expr *dest, const struct tib_expr *src) { - int rc; - - if (!dest->bufsize) - { - rc = tib_expr_init (dest); - if (rc) - return rc; - } - - int i; - tib_expr_foreach (src, i) - { - rc = tib_expr_push (dest, src->data[i]); - if (rc) - { - tib_expr_destroy (dest); - return rc; - } - } - - return 0; + int rc; + + if (!dest->bufsize) + { + rc = tib_expr_init(dest); + if (rc) + return rc; + } + + int i; + tib_expr_foreach(src, i) + { + rc = tib_expr_push(dest, src->data[i]); + if (rc) + { + tib_expr_destroy(dest); + return rc; + } + } + + return 0; } char * -tib_expr_tostr_f (const struct tib_expr *self, - const char *(*get_special) (int)) +tib_expr_tostr_f(const struct tib_expr *self, const char *(*get_special)(int)) { - if (!self->data) - { - tib_errno = TIB_ENULLPTR; - return NULL; - } - - int i, len = 1; - tib_expr_foreach (self, i) - { - const char *special = get_special (self->data[i]); - if (special) - len += strlen (special); - else - ++len; - } - - char *out = malloc (len * sizeof (char)); - if (!out) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - int bump = 0; - tib_expr_foreach (self, i) - { - const char *special = get_special (self->data[i]); - if (special) - { - out[i + bump] = '\0'; - strcat (out, special); - bump += strlen (special) - 1; - } - else - { - out[i + bump] = self->data[i]; - } - } - - out[i + bump] = '\0'; - return out; + if (!self->data) + { + tib_errno = TIB_ENULLPTR; + return NULL; + } + + int i, len = 1; + tib_expr_foreach(self, i) + { + const char *special = get_special(self->data[i]); + if (special) + len += strlen(special); + else + ++len; + } + + char *out = malloc(len * sizeof(char)); + if (!out) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + int bump = 0; + tib_expr_foreach(self, i) + { + const char *special = get_special(self->data[i]); + if (special) + { + out[i + bump] = '\0'; + strcat(out, special); + bump += strlen(special) - 1; + } + else + { + out[i + bump] = self->data[i]; + } + } + + out[i + bump] = '\0'; + return out; } char * -tib_expr_tostr (const struct tib_expr *self) +tib_expr_tostr(const struct tib_expr *self) { - return tib_expr_tostr_f (self, tib_special_char_text); + return tib_expr_tostr_f(self, tib_special_char_text); } int -tib_expr_parse_complex (const struct tib_expr *self, gsl_complex *out) +tib_expr_parse_complex(const struct tib_expr *self, gsl_complex *out) { - if (!tib_eval_isnum (self)) - return TIB_ESYNTAX; - - const int len = self->len; - char s[len + 1]; - - for (int i = 0; i < len; ++i) - s[i] = self->data[i]; - - s[len] = '\0'; - - char *i_start = NULL; - if (contains_i (self)) - { - int num_operators = sign_count (self); - for (int i = 0; i < len; ++i) - { - int c = self->data[i]; - - if ('i' == c) - { - i_start = s; - break; - } - else if (is_sign_operator (c) && --num_operators == 0) - { - i_start = &s[i]; - break; - } - } - } - - GSL_SET_REAL (out, s == i_start ? 0 : strtod (s, NULL)); - - if (i_start) - { - if (is_sign_operator (i_start[0]) && 'i' == i_start[1]) - i_start[1] = '1'; - else if ('i' == i_start[0]) - i_start[0] = '1'; - } - - GSL_SET_IMAG (out, i_start ? strtod (i_start, NULL) : 0); - - return 0; + if (!tib_eval_isnum(self)) + return TIB_ESYNTAX; + + const int len = self->len; + char s[len + 1]; + + for (int i = 0; i < len; ++i) + s[i] = self->data[i]; + + s[len] = '\0'; + + char *i_start = NULL; + if (contains_i(self)) + { + int num_operators = sign_count(self); + for (int i = 0; i < len; ++i) + { + int c = self->data[i]; + + if ('i' == c) + { + i_start = s; + break; + } + else if (is_sign_operator(c) && --num_operators == 0) + { + i_start = &s[i]; + break; + } + } + } + + GSL_SET_REAL(out, s == i_start ? 0 : strtod(s, NULL)); + + if (i_start) + { + if (is_sign_operator(i_start[0]) && 'i' == i_start[1]) + i_start[1] = '1'; + else if ('i' == i_start[0]) + i_start[0] = '1'; + } + + GSL_SET_IMAG(out, i_start ? strtod(i_start, NULL) : 0); + + return 0; } int -tib_expr_delete (struct tib_expr *self, int i) +tib_expr_delete(struct tib_expr *self, int i) { - if (i > self->len) - return TIB_EINDEX; + if (i > self->len) + return TIB_EINDEX; - --self->len; + --self->len; - for (; i < self->len; ++i) - self->data[i] = self->data[i + 1]; + for (; i < self->len; ++i) + self->data[i] = self->data[i + 1]; - return 0; + return 0; } int -tib_expr_insert (struct tib_expr *self, int i, int c) +tib_expr_insert(struct tib_expr *self, int i, int c) { - if (i > ++self->len) - { - --self->len; - return TIB_EINDEX; - } - - if (!self->bufsize) - { - struct tib_expr temp = { .bufsize = 0 }; - --self->len; - - int rc = tib_exprcpy (&temp, self); - if (rc) - return rc; - - *self = temp; - ++self->len; - } - else if (self->len > self->bufsize) - { - if (16384 == self->bufsize) - { - return TIB_EALLOC; - } - else - { - int *old = self->data; - self->bufsize *= 2; - - self->data = realloc (self->data, self->bufsize * sizeof (int)); - if (!self->data) - { - self->bufsize /= 2; - --self->len; - self->data = old; - return TIB_EALLOC; - } - } - } - - for (int j = self->len - 1; j > i; --j) - self->data[j] = self->data[j - 1]; - - self->data[i] = c; - return 0; + if (i > ++self->len) + { + --self->len; + return TIB_EINDEX; + } + + if (!self->bufsize) + { + struct tib_expr temp = { .bufsize = 0 }; + --self->len; + + int rc = tib_exprcpy(&temp, self); + if (rc) + return rc; + + *self = temp; + ++self->len; + } + else if (self->len > self->bufsize) + { + if (16384 == self->bufsize) + { + return TIB_EALLOC; + } + else + { + int *old = self->data; + self->bufsize *= 2; + + self->data = realloc(self->data, + self->bufsize * sizeof(int)); + if (!self->data) + { + self->bufsize /= 2; + --self->len; + self->data = old; + return TIB_EALLOC; + } + } + } + + for (int j = self->len - 1; j > i; --j) + self->data[j] = self->data[j - 1]; + + self->data[i] = c; + return 0; } int -tib_expr_push (struct tib_expr *self, int c) +tib_expr_push(struct tib_expr *self, int c) { - return tib_expr_insert (self, self->len, c); + return tib_expr_insert(self, self->len, c); } int -tib_expr_indexof (const struct tib_expr *self, int c) +tib_expr_indexof(const struct tib_expr *self, int c) { - for (int i = 0; i < self->len; ++i) - if (c == self->data[i]) - return i; + for (int i = 0; i < self->len; ++i) + if (c == self->data[i]) + return i; - return -1; + return -1; } int -tib_expr_indexof_r (const struct tib_expr *self, int c) +tib_expr_indexof_r(const struct tib_expr *self, int c) { - for (int i = self->len - 1; i >= 0; --i) - if (c == self->data[i]) - return i; + for (int i = self->len - 1; i >= 0; --i) + if (c == self->data[i]) + return i; - return -1; + return -1; } int -tib_subexpr (struct tib_expr *dest, const struct tib_expr *src, int beg, - int end) +tib_subexpr(struct tib_expr *dest, const struct tib_expr *src, int beg, + int end) { - if (end > src->len || end < beg) - return TIB_EINDEX; + if (end > src->len || end < beg) + return TIB_EINDEX; - dest->len = end - beg; - dest->bufsize = 0; - dest->data = &src->data[beg]; + dest->len = end - beg; + dest->bufsize = 0; + dest->data = &src->data[beg]; - return 0; + return 0; } diff --git a/src/tibexpr.h b/src/tibexpr.h index 41195a9..9905a67 100644 --- a/src/tibexpr.h +++ b/src/tibexpr.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,50 +24,49 @@ struct tib_expr { - int *data; - int len; - int bufsize; + int *data; + int len; + int bufsize; }; int -tib_expr_init (struct tib_expr *self); +tib_expr_init(struct tib_expr *self); void -tib_expr_destroy (struct tib_expr *self); +tib_expr_destroy(struct tib_expr *self); int -tib_exprcpy (struct tib_expr *dest, const struct tib_expr *src); +tib_exprcpy(struct tib_expr *dest, const struct tib_expr *src); int -tib_exprcat (struct tib_expr *dest, const struct tib_expr *src); +tib_exprcat(struct tib_expr *dest, const struct tib_expr *src); char * -tib_expr_tostr_f (const struct tib_expr *self, - const char *(*get_special) (int)); +tib_expr_tostr_f(const struct tib_expr *self, const char *(*get_special)(int)); char * -tib_expr_tostr (const struct tib_expr *self); +tib_expr_tostr(const struct tib_expr *self); int -tib_expr_parse_complex (const struct tib_expr *self, gsl_complex *out); +tib_expr_parse_complex(const struct tib_expr *self, gsl_complex *out); int -tib_expr_delete (struct tib_expr *self, int i); +tib_expr_delete(struct tib_expr *self, int i); int -tib_expr_insert (struct tib_expr *self, int i, int c); +tib_expr_insert(struct tib_expr *self, int i, int c); int -tib_expr_push (struct tib_expr *self, int c); +tib_expr_push(struct tib_expr *self, int c); int -tib_expr_indexof (const struct tib_expr *self, int c); +tib_expr_indexof(const struct tib_expr *self, int c); int -tib_expr_indexof_r (const struct tib_expr *self, int c); +tib_expr_indexof_r(const struct tib_expr *self, int c); int -tib_subexpr (struct tib_expr *dest, const struct tib_expr *src, int beg, - int end); +tib_subexpr(struct tib_expr *dest, const struct tib_expr *src, int beg, + int end); #endif diff --git a/src/tibfunction.c b/src/tibfunction.c index d2085f5..b1d59fc 100644 --- a/src/tibfunction.c +++ b/src/tibfunction.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -30,267 +30,266 @@ struct registry_node { - int key; - tib_Function f; + int key; + tib_Function f; }; struct registry { - size_t len; - struct registry_node *nodes; + size_t len; + struct registry_node *nodes; }; static gsl_rng *rng = NULL; -static struct registry registry = - { - .len = 0, - .nodes = NULL - }; +static struct registry registry = { + .len = 0, + .nodes = NULL +}; static TIB * -func_paren (const struct tib_expr *expr) +func_paren(const struct tib_expr *expr) { - return tib_eval (expr); + return tib_eval(expr); } static int -split_number_args (const struct tib_expr *expr, int num_params, ...) +split_number_args(const struct tib_expr *expr, int num_params, ...) { - const int *beg, *end; - int rc = 0, numpar = 0; - va_list ap; - - va_start (ap, num_params); - for (beg = expr->data, end = beg; end < expr->data + expr->len; ++end) - { - if (tib_is_func (*end)) - { - ++numpar; - } - else if (')' == *end) - { - if (--numpar < 0) - { - rc = TIB_ESYNTAX; - break; - } - } - else if (0 == numpar && - (',' == *end || end + 1 == expr->data + expr->len)) - { - if (num_params-- == 0) - { - rc = TIB_EARGNUM; - break; - } - - int start = beg - expr->data, stop = end - expr->data; - if (end + 1 == expr->data + expr->len) - ++stop; - - struct tib_expr arg; - tib_subexpr (&arg, expr, start, stop); - - TIB *t = tib_eval (&arg); - if (!t) - { - rc = tib_errno; - break; - } - - if (tib_type (t) != TIB_TYPE_COMPLEX) - { - tib_decref (t); - tib_errno = TIB_ETYPE; - break; - } - - gsl_complex *out = va_arg (ap, gsl_complex *); - *out = tib_complex_value (t); - tib_decref (t); - - beg = end + 1; - } - } - va_end (ap); - - return rc; + const int *beg, *end; + int rc = 0, numpar = 0; + va_list ap; + + va_start(ap, num_params); + for (beg = expr->data, end = beg; end < expr->data + expr->len; ++end) + { + if (tib_is_func(*end)) + { + ++numpar; + } + else if (')' == *end) + { + if (--numpar < 0) + { + rc = TIB_ESYNTAX; + break; + } + } + else if (0 == numpar && + (',' == *end || end + 1 == expr->data + expr->len)) + { + if (num_params-- == 0) + { + rc = TIB_EARGNUM; + break; + } + + int start = beg - expr->data, stop = end - expr->data; + if (end + 1 == expr->data + expr->len) + ++stop; + + struct tib_expr arg; + tib_subexpr(&arg, expr, start, stop); + + TIB *t = tib_eval(&arg); + if (!t) + { + rc = tib_errno; + break; + } + + if (tib_type(t) != TIB_TYPE_COMPLEX) + { + tib_decref(t); + tib_errno = TIB_ETYPE; + break; + } + + gsl_complex *out = va_arg(ap, gsl_complex *); + *out = tib_complex_value(t); + tib_decref(t); + + beg = end + 1; + } + } + va_end(ap); + + return rc; } static TIB * -single_parameter_function (const struct tib_expr *expr, - gsl_complex (*f) (gsl_complex)) +single_parameter_function(const struct tib_expr *expr, + gsl_complex(*f)(gsl_complex)) { - gsl_complex z; + gsl_complex z; - tib_errno = split_number_args (expr, 1, &z); - if (tib_errno) - return NULL; + tib_errno = split_number_args(expr, 1, &z); + if (tib_errno) + return NULL; - z = f (z); - return tib_new_complex (GSL_REAL (z), GSL_IMAG (z)); + z = f(z); + return tib_new_complex(GSL_REAL(z), GSL_IMAG(z)); } static TIB * -func_sin (const struct tib_expr *expr) +func_sin(const struct tib_expr *expr) { - return single_parameter_function (expr, gsl_complex_sin); + return single_parameter_function(expr, gsl_complex_sin); } static TIB * -func_cos (const struct tib_expr *expr) +func_cos(const struct tib_expr *expr) { - return single_parameter_function (expr, gsl_complex_cos); + return single_parameter_function(expr, gsl_complex_cos); } static TIB * -func_tan (const struct tib_expr *expr) +func_tan(const struct tib_expr *expr) { - return single_parameter_function (expr, gsl_complex_tan); + return single_parameter_function(expr, gsl_complex_tan); } static int -is_int (gsl_complex z) +is_int(gsl_complex z) { - return GSL_IMAG (z) == 0 && fmod (GSL_REAL (z), 1.0) == 0; + return GSL_IMAG(z) == 0 && fmod(GSL_REAL(z), 1.0) == 0; } static TIB * -func_randint (const struct tib_expr *expr) +func_randint(const struct tib_expr *expr) { - int len = expr->len, num_commas = 0; - - for (int i = 0; i < len; ++i) - { - if (',' == expr->data[i]) - { - if (++num_commas > 2) - break; - } - } - - if (num_commas != 2) - { - tib_errno = TIB_EARGNUM; - return NULL; - } - - gsl_complex min, max, count; - tib_errno = split_number_args (expr, 3, &min, &max, &count); - if (tib_errno) - return NULL; - - if (!(is_int (min) && is_int (max) && is_int (count)) - || GSL_REAL (count) < 0) - return NULL; - - double diff = GSL_REAL (max) - GSL_REAL (min); - - len = (unsigned int) GSL_REAL (count); - gsl_complex vals[len]; - - for (int i = 0; i < len; ++i) - { - GSL_SET_COMPLEX (&vals[i], (double) gsl_rng_get (rng), 0); - - while (GSL_REAL (vals[i]) < GSL_REAL (min)) - GSL_SET_REAL (&vals[i], GSL_REAL (vals[i]) + diff); - while (GSL_REAL (vals[i]) > GSL_REAL (max)) - GSL_SET_REAL (&vals[i], GSL_REAL (vals[i]) - diff); - } - - return tib_new_list (vals, len); + int len = expr->len, num_commas = 0; + + for (int i = 0; i < len; ++i) + { + if (',' == expr->data[i]) + { + if (++num_commas > 2) + break; + } + } + + if (num_commas != 2) + { + tib_errno = TIB_EARGNUM; + return NULL; + } + + gsl_complex min, max, count; + tib_errno = split_number_args(expr, 3, &min, &max, &count); + if (tib_errno) + return NULL; + + if (!(is_int(min) && is_int(max) && is_int(count)) + || GSL_REAL(count) < 0) + return NULL; + + double diff = GSL_REAL(max) - GSL_REAL(min); + + len = (unsigned int) GSL_REAL(count); + gsl_complex vals[len]; + + for (int i = 0; i < len; ++i) + { + GSL_SET_COMPLEX(&vals[i], (double) gsl_rng_get(rng), 0); + + while (GSL_REAL(vals[i]) < GSL_REAL(min)) + GSL_SET_REAL(&vals[i], GSL_REAL(vals[i]) + diff); + + while (GSL_REAL(vals[i]) > GSL_REAL(max)) + GSL_SET_REAL(&vals[i], GSL_REAL(vals[i]) - diff); + } + + return tib_new_list(vals, len); } int -tib_registry_init () +tib_registry_init() { - int rc; + int rc; - if (registry.nodes != NULL || rng != NULL) - tib_registry_free (); + if (registry.nodes != NULL || rng != NULL) + tib_registry_free(); - rng = gsl_rng_alloc (gsl_rng_taus2); - if (NULL == rng) - return TIB_EALLOC; + rng = gsl_rng_alloc(gsl_rng_taus2); + if (NULL == rng) + return TIB_EALLOC; - gsl_rng_set (rng, (unsigned long) time (NULL)); + gsl_rng_set(rng, (unsigned long) time(NULL)); -#define ADD(K,F) rc = tib_registry_add (K, F); if (rc) goto fail; +#define ADD(K,F) rc = tib_registry_add(K, F); if (rc) goto fail; - ADD ('(', func_paren); - ADD (TIB_CHAR_SIN, func_sin); - ADD (TIB_CHAR_COS, func_cos); - ADD (TIB_CHAR_TAN, func_tan); - ADD (TIB_CHAR_RANDINT, func_randint); + ADD('(', func_paren); + ADD(TIB_CHAR_SIN, func_sin); + ADD(TIB_CHAR_COS, func_cos); + ADD(TIB_CHAR_TAN, func_tan); + ADD(TIB_CHAR_RANDINT, func_randint); #undef ADD fail: - if (rc) - tib_registry_free (); + if (rc) + tib_registry_free(); - return rc; + return rc; } void -tib_registry_free () +tib_registry_free() { - if (registry.nodes) - free (registry.nodes); - if (rng) - gsl_rng_free (rng); - - registry.len = 0; - registry.nodes = NULL; - rng = NULL; + if (registry.nodes) + free(registry.nodes); + if (rng) + gsl_rng_free(rng); + + registry.len = 0; + registry.nodes = NULL; + rng = NULL; } int -tib_registry_add (int key, tib_Function f) +tib_registry_add(int key, tib_Function f) { - struct registry_node *old = registry.nodes; - - ++registry.len; - registry.nodes = realloc (registry.nodes, - registry.len * sizeof (struct registry_node)); - if (NULL == registry.nodes) - { - registry.nodes = old; - --registry.len; - return TIB_EALLOC; - } - - struct registry_node new = - { - .key = key, - .f = f - }; - - registry.nodes[registry.len - 1] = new; - return 0; + struct registry_node *old = registry.nodes; + + ++registry.len; + registry.nodes = realloc(registry.nodes, + registry.len * sizeof(struct registry_node)); + if (NULL == registry.nodes) + { + registry.nodes = old; + --registry.len; + return TIB_EALLOC; + } + + struct registry_node new = { + .key = key, + .f = f + }; + + registry.nodes[registry.len - 1] = new; + return 0; } bool -tib_is_func (int key) +tib_is_func(int key) { - size_t i; - for (i = 0; i < registry.len; ++i) - if (key == registry.nodes[i].key) - return true; + size_t i; + for (i = 0; i < registry.len; ++i) + if (key == registry.nodes[i].key) + return true; - return false; + return false; } TIB * -tib_call (int key, const struct tib_expr *expr) +tib_call(int key, const struct tib_expr *expr) { - size_t i; - for (i = 0; i < registry.len; ++i) - if (key == registry.nodes[i].key) - return registry.nodes[i].f (expr); + size_t i; + for (i = 0; i < registry.len; ++i) + if (key == registry.nodes[i].key) + return registry.nodes[i].f(expr); - tib_errno = TIB_EBADFUNC; - return NULL; + tib_errno = TIB_EBADFUNC; + return NULL; } diff --git a/src/tibfunction.h b/src/tibfunction.h index e3383dc..29d80b7 100644 --- a/src/tibfunction.h +++ b/src/tibfunction.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -23,21 +23,21 @@ #include "tibexpr.h" #include "tibtype.h" -typedef TIB *(*tib_Function) (const struct tib_expr *); +typedef TIB *(*tib_Function)(const struct tib_expr *); int -tib_registry_init (void); +tib_registry_init(void); void -tib_registry_free (void); +tib_registry_free(void); int -tib_registry_add (int key, tib_Function f); +tib_registry_add(int key, tib_Function f); bool -tib_is_func (int key); +tib_is_func(int key); TIB * -tib_call (int key, const struct tib_expr *expr); +tib_call(int key, const struct tib_expr *expr); #endif diff --git a/src/tiblst.c b/src/tiblst.c index c908c92..c11ab01 100644 --- a/src/tiblst.c +++ b/src/tiblst.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,125 +21,125 @@ #include "tiblst.h" struct tib_lst * -tib_new_lst () +tib_new_lst() { - struct tib_lst *out = malloc (sizeof (struct tib_lst)); - out->beg = NULL; - out->end = NULL; + struct tib_lst *out = malloc(sizeof(struct tib_lst)); + out->beg = NULL; + out->end = NULL; - return out; + return out; } static struct tib_el * -el_ref (const struct tib_lst *lst, int index) +el_ref(const struct tib_lst *lst, int index) { - for (struct tib_el *el = lst->beg; el != NULL; el = el->next, --index) - if (0 == index) - return el; + for (struct tib_el *el = lst->beg; el != NULL; el = el->next, --index) + if (0 == index) + return el; - return NULL; + return NULL; } void -tib_free_lst (struct tib_lst *lst) +tib_free_lst(struct tib_lst *lst) { - while (tib_lst_len (lst)) - tib_lst_remove (lst, 0); + while (tib_lst_len(lst)) + tib_lst_remove(lst, 0); - free (lst); + free(lst); } int -tib_lst_insert (struct tib_lst *lst, TIB *t, int index) +tib_lst_insert(struct tib_lst *lst, TIB *t, int index) { - int len = tib_lst_len (lst); + int len = tib_lst_len(lst); - if (index > len) - return TIB_EINDEX; + if (index > len) + return TIB_EINDEX; - struct tib_el *new = malloc (sizeof (struct tib_el)); - if (NULL == new) - return TIB_EALLOC; + struct tib_el *new = malloc(sizeof(struct tib_el)); + if (NULL == new) + return TIB_EALLOC; - tib_incref (t); - new->val = t; + tib_incref(t); + new->val = t; - if (0 == index) - new->prev = NULL; - else - new->prev = el_ref (lst, index - 1); + if (0 == index) + new->prev = NULL; + else + new->prev = el_ref(lst, index - 1); - if (index == len) - new->next = NULL; - else - new->next = el_ref (lst, index); + if (index == len) + new->next = NULL; + else + new->next = el_ref(lst, index); - if (new->next) - new->next->prev = new; - else - lst->end = new; + if (new->next) + new->next->prev = new; + else + lst->end = new; - if (new->prev) - new->prev->next = new; - else - lst->beg = new; + if (new->prev) + new->prev->next = new; + else + lst->beg = new; - return 0; + return 0; } int -tib_lst_push (struct tib_lst *lst, TIB *t) +tib_lst_push(struct tib_lst *lst, TIB *t) { - return tib_lst_insert (lst, t, tib_lst_len (lst)); + return tib_lst_insert(lst, t, tib_lst_len(lst)); } void -tib_lst_remove (struct tib_lst *lst, int index) +tib_lst_remove(struct tib_lst *lst, int index) { - struct tib_el *e = el_ref (lst, index); - if (!e) - return; - - if (e->next) - e->next->prev = e->prev; - else - lst->end = e->prev; - - if (e->prev) - e->prev->next = e->next; - else - lst->beg = e->next; - - tib_decref (e->val); - free (e); + struct tib_el *e = el_ref(lst, index); + if (!e) + return; + + if (e->next) + e->next->prev = e->prev; + else + lst->end = e->prev; + + if (e->prev) + e->prev->next = e->next; + else + lst->beg = e->next; + + tib_decref(e->val); + free(e); } int -tib_lst_len (const struct tib_lst *lst) +tib_lst_len(const struct tib_lst *lst) { - int i = 0; - struct tib_el *e = lst->beg; + int i = 0; + struct tib_el *e = lst->beg; - while (e != NULL) - { - ++i; - e = e->next; - } + while (e != NULL) + { + ++i; + e = e->next; + } - return i; + return i; } TIB * -tib_lst_ref (const struct tib_lst *lst, int index) +tib_lst_ref(const struct tib_lst *lst, int index) { - struct tib_el *i; - int looped = 0; + struct tib_el *i; + int looped = 0; - for (i = lst->beg; i != NULL; i = i->next) - { - if (looped++ == index) - return i->val; - } + for (i = lst->beg; i != NULL; i = i->next) + { + if (looped++ == index) + return i->val; + } - return NULL; + return NULL; } diff --git a/src/tiblst.h b/src/tiblst.h index ea1f82c..593a645 100644 --- a/src/tiblst.h +++ b/src/tiblst.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -20,40 +20,40 @@ #include "tibtype.h" -#define tib_foreachlst(L,I) for (I = 0; i < tib_lst_len (L); ++I) +#define tib_foreachlst(L,I) for ((I) = 0; (I) < tib_lst_len (L); ++(I)) struct tib_el { - TIB *val; - struct tib_el *next; - struct tib_el *prev; + TIB *val; + struct tib_el *next; + struct tib_el *prev; }; struct tib_lst { - struct tib_el *beg; - struct tib_el *end; + struct tib_el *beg; + struct tib_el *end; }; struct tib_lst * -tib_new_lst (void); +tib_new_lst(void); void -tib_free_lst (struct tib_lst *lst); +tib_free_lst(struct tib_lst *lst); int -tib_lst_insert (struct tib_lst *lst, TIB *t, int index); +tib_lst_insert(struct tib_lst *lst, TIB *t, int index); int -tib_lst_push (struct tib_lst *lst, TIB *t); +tib_lst_push(struct tib_lst *lst, TIB *t); void -tib_lst_remove (struct tib_lst *lst, int index); +tib_lst_remove(struct tib_lst *lst, int index); int -tib_lst_len (const struct tib_lst *lst); +tib_lst_len(const struct tib_lst *lst); TIB * -tib_lst_ref (const struct tib_lst *lst, int index); +tib_lst_ref(const struct tib_lst *lst, int index); #endif diff --git a/src/tibtranscode.c b/src/tibtranscode.c index 103f14b..b0b814c 100644 --- a/src/tibtranscode.c +++ b/src/tibtranscode.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -23,877 +23,879 @@ #include "tiberr.h" static int -need_next (int c, int *err, FILE *program, unsigned long *parsed) +need_next(int c, int *err, FILE *program, unsigned long *parsed) { - int next; + int next; - if ((next = fgetc (program)) == EOF) - { - *err = TIB_EBADCHAR; - return EOF; - } + if ((next = fgetc(program)) == EOF) + { + *err = TIB_EBADCHAR; + return EOF; + } - ++(*parsed); + ++(*parsed); - switch (c) - { - case -69: - if (10 == next) - return TIB_CHAR_RANDINT; + switch (c) + { + case -69: + if (10 == next) + return TIB_CHAR_RANDINT; - *err = TIB_EBADCHAR; - return EOF; + *err = TIB_EBADCHAR; + return EOF; - case 92: - if (next >= 0 && next <= 8) - return next + TIB_CHAR_MATA; + case 92: + if (next >= 0 && next <= 8) + return next + TIB_CHAR_MATA; - *err = TIB_EBADCHAR; - return EOF; + *err = TIB_EBADCHAR; + return EOF; - case 93: - if (next >= 0 && next <= 8) - return next + TIB_CHAR_L1; + case 93: + if (next >= 0 && next <= 8) + return next + TIB_CHAR_L1; - *err = TIB_EBADCHAR; - return EOF; + *err = TIB_EBADCHAR; + return EOF; - case 96: - if (0 == next) - return TIB_CHAR_PIC1; + case 96: + if (0 == next) + return TIB_CHAR_PIC1; - *err = TIB_EBADCHAR; - return EOF; + *err = TIB_EBADCHAR; + return EOF; - case 99: - switch (next) - { - case 10: - return TIB_CHAR_XMIN; + case 99: + switch (next) + { + case 10: + return TIB_CHAR_XMIN; - case 11: - return TIB_CHAR_XMAX; + case 11: + return TIB_CHAR_XMAX; - case 12: - return TIB_CHAR_YMIN; + case 12: + return TIB_CHAR_YMIN; - case 13: - return TIB_CHAR_YMAX; + case 13: + return TIB_CHAR_YMAX; - default: - *err = TIB_EBADCHAR; - return EOF; - } + default: + *err = TIB_EBADCHAR; + return EOF; + } - case 126: - if (9 == c) - return TIB_CHAR_AXESOFF; + case 126: + if (9 == c) + return TIB_CHAR_AXESOFF; - *err = TIB_EBADCHAR; - return EOF; + *err = TIB_EBADCHAR; + return EOF; - default: - *err = TIB_EBADCHAR; - return EOF; - } + default: + *err = TIB_EBADCHAR; + return EOF; + } } static int -trans_from (int c, int *err, FILE *program, unsigned long *parsed) +trans_from(int c, int *err, FILE *program, unsigned long *parsed) { - if (c > SCHAR_MAX) - c -= 256; + if (c > SCHAR_MAX) + c -= 256; - /* The original author of LibreCalc's TI emulator had several comments in - this conversion case analysis where he was unsure of the legitimacy of - some character conversions. Be wary of the following: 91, 109 or 14, 114, - 98, 24, 127 or -40, 95 */ - switch (c) - { - case -126: - return '*'; + /* The original author of LibreCalc's TI emulator had several comments + * in this conversion case analysis where he was unsure of the + * legitimacy of some character converstion. Be wary of the following: + * 91, 109 or 14, 114, 98, 24, 127 or -40, 95 + */ + switch (c) + { + case -126: + return '*'; - case -125: - return '/'; + case -125: + return '/'; - case -123: - return TIB_CHAR_CLEARDRAW; + case -123: + return TIB_CHAR_CLEARDRAW; - case -109: - return TIB_CHAR_TEXT; + case -109: + return TIB_CHAR_TEXT; - case -104: - return TIB_CHAR_STOREPIC; + case -104: + return TIB_CHAR_STOREPIC; - case -103: - return TIB_CHAR_RECALLPIC; + case -103: + return TIB_CHAR_RECALLPIC; - case -100: - return TIB_CHAR_LINE; + case -100: + return TIB_CHAR_LINE; - case -85: - return TIB_CHAR_RAND; + case -85: + return TIB_CHAR_RAND; - case -84: - return TIB_CHAR_PI; + case -84: + return TIB_CHAR_PI; - case -83: - return TIB_CHAR_GETKEY; + case -83: + return TIB_CHAR_GETKEY; - case -81: - return '?'; + case -81: + return '?'; - case -80: - return TIB_CHAR_SMALL_MINUS; + case -80: + return TIB_CHAR_SMALL_MINUS; - case -79: - return TIB_CHAR_INT; + case -79: + return TIB_CHAR_INT; - case -75: - return TIB_CHAR_DIM; + case -75: + return TIB_CHAR_DIM; - case -72: - return TIB_CHAR_NOT; + case -72: + return TIB_CHAR_NOT; - case -69: - return need_next (c, err, program, parsed); + case -69: + return need_next(c, err, program, parsed); - case -50: - return TIB_CHAR_IF; + case -50: + return TIB_CHAR_IF; - case -49: - return TIB_CHAR_THEN; + case -49: + return TIB_CHAR_THEN; - case -48: - return TIB_CHAR_ELSE; + case -48: + return TIB_CHAR_ELSE; - case -47: - return TIB_CHAR_WHILE; + case -47: + return TIB_CHAR_WHILE; - case -46: - return TIB_CHAR_REPEAT; + case -46: + return TIB_CHAR_REPEAT; - case -45: - return TIB_CHAR_FOR; + case -45: + return TIB_CHAR_FOR; - case -44: - return TIB_CHAR_END; + case -44: + return TIB_CHAR_END; - case -43: - return TIB_CHAR_RETURN; + case -43: + return TIB_CHAR_RETURN; - case -42: - return TIB_CHAR_LABEL; + case -42: + return TIB_CHAR_LABEL; - case -41: - return TIB_CHAR_GOTO; + case -41: + return TIB_CHAR_GOTO; - case -40: - return TIB_CHAR_PAUSE; + case -40: + return TIB_CHAR_PAUSE; - case -39: - return TIB_CHAR_STOP; + case -39: + return TIB_CHAR_STOP; - case -36: - return TIB_CHAR_INPUT; + case -36: + return TIB_CHAR_INPUT; - case -34: - return TIB_CHAR_DISP; + case -34: + return TIB_CHAR_DISP; - case -32: - return TIB_CHAR_OUTPUT; + case -32: + return TIB_CHAR_OUTPUT; - case -31: - return TIB_CHAR_CLEARHOME; + case -31: + return TIB_CHAR_CLEARHOME; - case -30: - return TIB_CHAR_FILL; + case -30: + return TIB_CHAR_FILL; - case -26: - return TIB_CHAR_MENU; + case -26: + return TIB_CHAR_MENU; - case -21: - return TIB_CHAR_LUSER; + case -21: + return TIB_CHAR_LUSER; - case -16: - return '^'; + case -16: + return '^'; - case -6: - return TIB_CHAR_CLRLIST; + case -6: + return TIB_CHAR_CLRLIST; - case 4: - return TIB_CHAR_STO; + case 4: + return TIB_CHAR_STO; - case 6: - return '['; + case 6: + return '['; - case 7: - return ']'; + case 7: + return ']'; - case 8: - return '{'; + case 8: + return '{'; - case 9: - return '}'; + case 9: + return '}'; - case 11: - return TIB_CHAR_DEGREE; + case 11: + return TIB_CHAR_DEGREE; - case 14: - return 'T'; + case 14: + return 'T'; - case 16: - return '('; + case 16: + return '('; - case 17: - return ')'; + case 17: + return ')'; - case 18: - return TIB_CHAR_ROUND; + case 18: + return TIB_CHAR_ROUND; - case 19: - return TIB_CHAR_PIXEL_TEST; + case 19: + return TIB_CHAR_PIXEL_TEST; - case 22: - return '|'; + case 22: + return '|'; - /* 24 was simply skipped in the original emulator; could cause problems */ - case 24: - return 0; + // 24 was simply skipped in the original emulator; could cause problems + case 24: + return 0; - case 41: - return ' '; + case 41: + return ' '; - case 42: - return '"'; + case 42: + return '"'; - case 43: - return ','; + case 43: + return ','; - case 45: - return '!'; + case 45: + return '!'; - case 58: - return '.'; + case 58: + return '.'; - case 59: - return TIB_CHAR_EPOW10; + case 59: + return TIB_CHAR_EPOW10; - case 60: - return TIB_CHAR_OR; + case 60: + return TIB_CHAR_OR; - case 62: - case 63: - return '\n'; + case 62: + case 63: + return '\n'; - case 64: - return TIB_CHAR_AND; + case 64: + return TIB_CHAR_AND; - case 91: - return TIB_CHAR_THETA; + case 91: + return TIB_CHAR_THETA; - case 92: - case 93: - return need_next (c, err, program, parsed); + case 92: + case 93: + return need_next(c, err, program, parsed); - /* 95 was not evaluated, but it printed "Pause " to stdout */ + // 95 was not evaluated, but it printed "Pause " to stdout - case 96: - return need_next (c, err, program, parsed); + case 96: + return need_next(c, err, program, parsed); - case 98: - return 'c'; + case 98: + return 'c'; - case 99: - return need_next (c, err, program, parsed); + case 99: + return need_next(c, err, program, parsed); - case 106: - return '='; + case 106: + return '='; - case 107: - return '<'; + case 107: + return '<'; - case 108: - return '>'; + case 108: + return '>'; - case 109: - return TIB_CHAR_LESSEQUAL; + case 109: + return TIB_CHAR_LESSEQUAL; - case 110: - return TIB_CHAR_GREATEREQUAL; + case 110: + return TIB_CHAR_GREATEREQUAL; - case 111: - return TIB_CHAR_DIFFERENT; + case 111: + return TIB_CHAR_DIFFERENT; - case 112: - return '+'; + case 112: + return '+'; - case 113: - return '-'; + case 113: + return '-'; - case 114: - return TIB_CHAR_ANS; + case 114: + return TIB_CHAR_ANS; - case 126: - return need_next (c, err, program, parsed); + case 126: + return need_next(c, err, program, parsed); - case 127: - return '['; + case 127: + return '['; - default: - if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) - { - return c; - } - else if (fgetc (program) != EOF || fgetc (program) != EOF) - { - *err = 0; - *parsed += 2; - return EOF; - } + default: + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) + { + return c; + } + else if (fgetc(program) != EOF || fgetc(program) != EOF) + { + *err = 0; + *parsed += 2; + return EOF; + } - *err = TIB_EBADCHAR; - return EOF; - } + *err = TIB_EBADCHAR; + return EOF; + } } int -tib_fread (struct tib_expr *out, FILE *program, unsigned long *parsed) +tib_fread(struct tib_expr *out, FILE *program, unsigned long *parsed) { - int rc, c; - - rc = tib_expr_init (out); - if (rc) - return rc; - - *parsed = 0; - while ((c = fgetc (program)) != EOF && *parsed < 71) - ++(*parsed); - - if (*parsed != 71) - { - rc = TIB_EBADFILE; - goto end; - } - - while ((c = fgetc (program)) != EOF) - { - ++(*parsed); - - int trans = trans_from ((char) c, &rc, program, parsed); - if (EOF == trans) - break; - - if (trans) - { - rc = tib_expr_push (out, trans); - if (rc) - break; - } - } + int rc, c; + + rc = tib_expr_init(out); + if (rc) + return rc; + + *parsed = 0; + while ((c = fgetc(program)) != EOF && *parsed < 71) + ++(*parsed); + + if (*parsed != 71) + { + rc = TIB_EBADFILE; + goto end; + } + + while ((c = fgetc(program)) != EOF) + { + ++(*parsed); + + int trans = trans_from((char) c, &rc, program, parsed); + if (EOF == trans) + break; + + if (trans) + { + rc = tib_expr_push(out, trans); + if (rc) + break; + } + } end: - if (rc) - tib_expr_destroy (out); + if (rc) + tib_expr_destroy(out); - return rc; + return rc; } int -tib_fwrite (FILE *out, const struct tib_expr *program, unsigned long *written) +tib_fwrite(FILE *out, const struct tib_expr *program, unsigned long *written) { - int rc, i; - - for (*written = 0; *written <= 71; ++(*written)) - { - rc = fputc (0, out); - if (rc) - return TIB_EWRITE; - } - - tib_expr_foreach (program, i) - { - int c = program->data[i]; - /* The original conversion table had a "TODO transpose" comment. May be - an incomplete table. */ - switch (c) - { - case '\n': - rc = fputc (62, out); - break; - - case ' ': - rc = fputc (41, out); - break; - - case '!': - rc = fputc (45, out); - break; - - case '"': - rc = fputc (42, out); - break; - - case '(': - rc = fputc (16, out); - break; - - case ')': - rc = fputc (17, out); - break; - - case '*': - rc = fputc (-126, out); - break; - - case '+': - rc = fputc (112, out); - break; - - case ',': - rc = fputc (43, out); - break; - - case '-': - rc = fputc (113, out); - break; - - case '.': - rc = fputc (58, out); - break; - - case '/': - rc = fputc (-125, out); - break; - - case '<': - rc = fputc (107, out); - break; - - case '=': - rc = fputc (106, out); - break; - - case '>': - rc = fputc (108, out); - break; - - case '?': - rc = fputc (-81, out); - break; - - case '[': - rc = fputc (6, out); - break; - - case ']': - rc = fputc (7, out); - break; - - case '^': - rc = fputc (-16, out); - break; - - case '{': - rc = fputc (8, out); - break; - - case '|': - rc = fputc (22, out); - break; - - case '}': - rc = fputc (9, out); - break; - - case TIB_CHAR_AND: - rc = fputc (64, out); - break; - - case TIB_CHAR_ANS: - rc = fputc (114, out); - break; - - case TIB_CHAR_AXESOFF: - rc = fputc (126, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (9, out); - break; - - case TIB_CHAR_CLEARHOME: - rc = fputc (-31, out); - break; - - case TIB_CHAR_CLEARDRAW: - rc = fputc (-123, out); - break; - - case TIB_CHAR_CLRLIST: - rc = fputc (-6, out); - break; - - case TIB_CHAR_DEGREE: - rc = fputc (11, out); - break; - - case TIB_CHAR_DIFFERENT: - rc = fputc (111, out); - break; - - case TIB_CHAR_DIM: - rc = fputc (-75, out); - break; - - case TIB_CHAR_DISP: - rc = fputc (-34, out); - break; - - case TIB_CHAR_ELSE: - rc = fputc (-48, out); - break; - - case TIB_CHAR_END: - rc = fputc (-44, out); - break; - - case TIB_CHAR_EPOW10: - rc = fputc (59, out); - break; - - case TIB_CHAR_FILL: - rc = fputc (-30, out); - break; - - case TIB_CHAR_FOR: - rc = fputc (-45, out); - break; - - case TIB_CHAR_GETKEY: - rc = fputc (-83, out); - break; - - case TIB_CHAR_GOTO: - rc = fputc (-41, out); - break; - - case TIB_CHAR_GREATEREQUAL: - rc = fputc (110, out); - break; - - case TIB_CHAR_IF: - rc = fputc (-50, out); - break; - - case TIB_CHAR_INPUT: - rc = fputc (-36, out); - break; - - case TIB_CHAR_INT: - rc = fputc (-79, out); - break; - - case TIB_CHAR_L1: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (0, out); - break; - - case TIB_CHAR_L2: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (1, out); - break; - - case TIB_CHAR_L3: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (2, out); - break; - - case TIB_CHAR_L4: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (3, out); - break; - - case TIB_CHAR_L5: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (4, out); - break; - - case TIB_CHAR_L6: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (5, out); - break; - - case TIB_CHAR_L7: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (6, out); - break; - - case TIB_CHAR_L8: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (7, out); - break; - - case TIB_CHAR_L9: - rc = fputc (93, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (8, out); - break; - - case TIB_CHAR_LABEL: - rc = fputc (-42, out); - break; - - case TIB_CHAR_LESSEQUAL: - rc = fputc (109, out); - break; - - case TIB_CHAR_LINE: - rc = fputc (-100, out); - break; - - case TIB_CHAR_LUSER: - rc = fputc (-21, out); - break; - - case TIB_CHAR_MATA: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (0, out); - break; - - case TIB_CHAR_MATB: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (1, out); - break; - - case TIB_CHAR_MATC: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (2, out); - break; - - case TIB_CHAR_MATD: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (3, out); - break; - - case TIB_CHAR_MATE: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (4, out); - break; - - case TIB_CHAR_MATF: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (5, out); - break; - - case TIB_CHAR_MATG: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (6, out); - break; - - case TIB_CHAR_MATH: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (7, out); - break; - - case TIB_CHAR_MATI: - rc = fputc (92, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (8, out); - break; - - case TIB_CHAR_MENU: - rc = fputc (-26, out); - break; - - case TIB_CHAR_NOT: - rc = fputc (-72, out); - break; - - case TIB_CHAR_OUTPUT: - rc = fputc (-32, out); - break; - - case TIB_CHAR_OR: - rc = fputc (60, out); - break; - - case TIB_CHAR_PAUSE: - rc = fputc (-40, out); - break; - - case TIB_CHAR_PI: - rc = fputc (-84, out); - break; - - case TIB_CHAR_PIC1: - rc = fputc (96, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (0, out); - break; - - case TIB_CHAR_PIXEL_TEST: - rc = fputc (19, out); - break; - - case TIB_CHAR_RAND: - rc = fputc (-85, out); - break; - - case TIB_CHAR_RANDINT: - rc = fputc (-69, out); - if (EOF == rc) - break; - rc = fputc (10, out); - break; - - case TIB_CHAR_RECALLPIC: - rc = fputc (-103, out); - break; - - case TIB_CHAR_REPEAT: - rc = fputc (-46, out); - break; - - case TIB_CHAR_RETURN: - rc = fputc (-43, out); - break; - - case TIB_CHAR_ROUND: - rc = fputc (18, out); - break; - - case TIB_CHAR_SMALL_MINUS: - rc = fputc (-80, out); - break; - - case TIB_CHAR_STO: - rc = fputc (4, out); - break; - - case TIB_CHAR_STOP: - rc = fputc (-39, out); - break; - - case TIB_CHAR_STOREPIC: - rc = fputc (-104, out); - break; - - case TIB_CHAR_TEXT: - rc = fputc (-109, out); - break; - - case TIB_CHAR_THEN: - rc = fputc (-49, out); - break; - - case TIB_CHAR_THETA: - rc = fputc (91, out); - break; - - case TIB_CHAR_WHILE: - rc = fputc (-47, out); - break; - - case TIB_CHAR_XMAX: - rc = fputc (99, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (11, out); - break; - - case TIB_CHAR_XMIN: - rc = fputc (99, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (10, out); - break; - - case TIB_CHAR_YMAX: - rc = fputc (99, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (13, out); - break; - - case TIB_CHAR_YMIN: - rc = fputc (99, out); - if (EOF == rc) - break; - ++(*written); - rc = fputc (12, out); - break; - - default: - if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) - rc = fputc (c, out); - else - rc = EOF; - break; - } - - if (EOF == rc) - return TIB_EWRITE; - - ++(*written); - } - - return 0; + int rc, i; + + for (*written = 0; *written <= 71; ++(*written)) + { + rc = fputc(0, out); + if (rc) + return TIB_EWRITE; + } + + tib_expr_foreach(program, i) + { + int c = program->data[i]; + /* The original conversion table had a "TODO transpose" + * comment. May be an incomplete table. + */ + switch (c) + { + case '\n': + rc = fputc(62, out); + break; + + case ' ': + rc = fputc(41, out); + break; + + case '!': + rc = fputc(45, out); + break; + + case '"': + rc = fputc(42, out); + break; + + case '(': + rc = fputc(16, out); + break; + + case ')': + rc = fputc(17, out); + break; + + case '*': + rc = fputc(-126, out); + break; + + case '+': + rc = fputc(112, out); + break; + + case ',': + rc = fputc(43, out); + break; + + case '-': + rc = fputc(113, out); + break; + + case '.': + rc = fputc(58, out); + break; + + case '/': + rc = fputc(-125, out); + break; + + case '<': + rc = fputc(107, out); + break; + + case '=': + rc = fputc(106, out); + break; + + case '>': + rc = fputc(108, out); + break; + + case '?': + rc = fputc(-81, out); + break; + + case '[': + rc = fputc(6, out); + break; + + case ']': + rc = fputc(7, out); + break; + + case '^': + rc = fputc(-16, out); + break; + + case '{': + rc = fputc(8, out); + break; + + case '|': + rc = fputc(22, out); + break; + + case '}': + rc = fputc(9, out); + break; + + case TIB_CHAR_AND: + rc = fputc(64, out); + break; + + case TIB_CHAR_ANS: + rc = fputc(114, out); + break; + + case TIB_CHAR_AXESOFF: + rc = fputc(126, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(9, out); + break; + + case TIB_CHAR_CLEARHOME: + rc = fputc(-31, out); + break; + + case TIB_CHAR_CLEARDRAW: + rc = fputc(-123, out); + break; + + case TIB_CHAR_CLRLIST: + rc = fputc(-6, out); + break; + + case TIB_CHAR_DEGREE: + rc = fputc(11, out); + break; + + case TIB_CHAR_DIFFERENT: + rc = fputc(111, out); + break; + + case TIB_CHAR_DIM: + rc = fputc(-75, out); + break; + + case TIB_CHAR_DISP: + rc = fputc(-34, out); + break; + + case TIB_CHAR_ELSE: + rc = fputc(-48, out); + break; + + case TIB_CHAR_END: + rc = fputc(-44, out); + break; + + case TIB_CHAR_EPOW10: + rc = fputc(59, out); + break; + + case TIB_CHAR_FILL: + rc = fputc(-30, out); + break; + + case TIB_CHAR_FOR: + rc = fputc(-45, out); + break; + + case TIB_CHAR_GETKEY: + rc = fputc(-83, out); + break; + + case TIB_CHAR_GOTO: + rc = fputc(-41, out); + break; + + case TIB_CHAR_GREATEREQUAL: + rc = fputc(110, out); + break; + + case TIB_CHAR_IF: + rc = fputc(-50, out); + break; + + case TIB_CHAR_INPUT: + rc = fputc(-36, out); + break; + + case TIB_CHAR_INT: + rc = fputc(-79, out); + break; + + case TIB_CHAR_L1: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(0, out); + break; + + case TIB_CHAR_L2: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(1, out); + break; + + case TIB_CHAR_L3: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(2, out); + break; + + case TIB_CHAR_L4: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(3, out); + break; + + case TIB_CHAR_L5: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(4, out); + break; + + case TIB_CHAR_L6: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(5, out); + break; + + case TIB_CHAR_L7: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(6, out); + break; + + case TIB_CHAR_L8: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(7, out); + break; + + case TIB_CHAR_L9: + rc = fputc(93, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(8, out); + break; + + case TIB_CHAR_LABEL: + rc = fputc(-42, out); + break; + + case TIB_CHAR_LESSEQUAL: + rc = fputc(109, out); + break; + + case TIB_CHAR_LINE: + rc = fputc(-100, out); + break; + + case TIB_CHAR_LUSER: + rc = fputc(-21, out); + break; + + case TIB_CHAR_MATA: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(0, out); + break; + + case TIB_CHAR_MATB: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(1, out); + break; + + case TIB_CHAR_MATC: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(2, out); + break; + + case TIB_CHAR_MATD: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(3, out); + break; + + case TIB_CHAR_MATE: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(4, out); + break; + + case TIB_CHAR_MATF: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(5, out); + break; + + case TIB_CHAR_MATG: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(6, out); + break; + + case TIB_CHAR_MATH: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(7, out); + break; + + case TIB_CHAR_MATI: + rc = fputc(92, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(8, out); + break; + + case TIB_CHAR_MENU: + rc = fputc(-26, out); + break; + + case TIB_CHAR_NOT: + rc = fputc(-72, out); + break; + + case TIB_CHAR_OUTPUT: + rc = fputc(-32, out); + break; + + case TIB_CHAR_OR: + rc = fputc(60, out); + break; + + case TIB_CHAR_PAUSE: + rc = fputc(-40, out); + break; + + case TIB_CHAR_PI: + rc = fputc(-84, out); + break; + + case TIB_CHAR_PIC1: + rc = fputc(96, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(0, out); + break; + + case TIB_CHAR_PIXEL_TEST: + rc = fputc(19, out); + break; + + case TIB_CHAR_RAND: + rc = fputc(-85, out); + break; + + case TIB_CHAR_RANDINT: + rc = fputc(-69, out); + if (EOF == rc) + break; + rc = fputc(10, out); + break; + + case TIB_CHAR_RECALLPIC: + rc = fputc(-103, out); + break; + + case TIB_CHAR_REPEAT: + rc = fputc(-46, out); + break; + + case TIB_CHAR_RETURN: + rc = fputc(-43, out); + break; + + case TIB_CHAR_ROUND: + rc = fputc(18, out); + break; + + case TIB_CHAR_SMALL_MINUS: + rc = fputc(-80, out); + break; + + case TIB_CHAR_STO: + rc = fputc(4, out); + break; + + case TIB_CHAR_STOP: + rc = fputc(-39, out); + break; + + case TIB_CHAR_STOREPIC: + rc = fputc(-104, out); + break; + + case TIB_CHAR_TEXT: + rc = fputc(-109, out); + break; + + case TIB_CHAR_THEN: + rc = fputc(-49, out); + break; + + case TIB_CHAR_THETA: + rc = fputc(91, out); + break; + + case TIB_CHAR_WHILE: + rc = fputc(-47, out); + break; + + case TIB_CHAR_XMAX: + rc = fputc(99, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(11, out); + break; + + case TIB_CHAR_XMIN: + rc = fputc(99, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(10, out); + break; + + case TIB_CHAR_YMAX: + rc = fputc(99, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(13, out); + break; + + case TIB_CHAR_YMIN: + rc = fputc(99, out); + if (EOF == rc) + break; + ++(*written); + rc = fputc(12, out); + break; + + default: + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z')) + rc = fputc(c, out); + else + rc = EOF; + break; + } + + if (EOF == rc) + return TIB_EWRITE; + + ++(*written); + } + + return 0; } diff --git a/src/tibtranscode.h b/src/tibtranscode.h index bf9356c..e0530cd 100644 --- a/src/tibtranscode.h +++ b/src/tibtranscode.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,9 +21,9 @@ #include "tibexpr.h" int -tib_fread (struct tib_expr *out, FILE *program, unsigned long *parsed); +tib_fread(struct tib_expr *out, FILE *program, unsigned long *parsed); int -tib_fwrite (FILE *out, const struct tib_expr *program, unsigned long *written); +tib_fwrite(FILE *out, const struct tib_expr *program, unsigned long *written); #endif diff --git a/src/tibtype.c b/src/tibtype.c index 1351dec..8dc8773 100644 --- a/src/tibtype.c +++ b/src/tibtype.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -30,1086 +30,1119 @@ #include "util.h" TIB * -tib_empty () +tib_empty() { - TIB *out = malloc (sizeof (TIB)); - if (NULL == out) - { - tib_errno = TIB_EALLOC; - return NULL; - } + TIB *out = malloc(sizeof(TIB)); + if (NULL == out) + { + tib_errno = TIB_EALLOC; + return NULL; + } - out->type = TIB_TYPE_NONE; - out->refs = 1; + out->type = TIB_TYPE_NONE; + out->refs = 1; - return out; + return out; } TIB * -tib_copy (const TIB *t) +tib_copy(const TIB *t) { - TIB *temp; - - if (NULL == t) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - switch (t->type) - { - case TIB_TYPE_NONE: - return tib_empty (); - - case TIB_TYPE_COMPLEX: - return tib_new_complex (GSL_REAL (t->value.number), - GSL_IMAG (t->value.number)); - - case TIB_TYPE_STRING: - return tib_new_str (t->value.string); - - case TIB_TYPE_LIST: - temp = tib_new_list (NULL, t->value.list->size); - if (NULL == temp) - return NULL; - - tib_errno = gsl_vector_complex_memcpy (temp->value.list, t->value.list); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - - case TIB_TYPE_MATRIX: - temp = tib_new_matrix (NULL, t->value.matrix->size1, - t->value.matrix->size2); - if (NULL == temp) - return NULL; - - tib_errno = gsl_matrix_complex_memcpy (temp->value.matrix, - t->value.matrix); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + TIB *temp; + + if (NULL == t) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + switch (t->type) + { + case TIB_TYPE_NONE: + return tib_empty(); + + case TIB_TYPE_COMPLEX: + return tib_new_complex(GSL_REAL(t->value.number), + GSL_IMAG(t->value.number)); + + case TIB_TYPE_STRING: + return tib_new_str(t->value.string); + + case TIB_TYPE_LIST: + temp = tib_new_list(NULL, t->value.list->size); + if (NULL == temp) + return NULL; + + tib_errno = gsl_vector_complex_memcpy(temp->value.list, + t->value.list); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + + case TIB_TYPE_MATRIX: + temp = tib_new_matrix(NULL, t->value.matrix->size1, + t->value.matrix->size2); + if (NULL == temp) + return NULL; + + tib_errno = gsl_matrix_complex_memcpy(temp->value.matrix, + t->value.matrix); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } void -tib_incref (TIB *t) +tib_incref(TIB *t) { - ++t->refs; + ++t->refs; } void -tib_decref (TIB *t) +tib_decref(TIB *t) { - if (0 == t->refs) - return; - - if (--t->refs == 0) - { - switch (t->type) - { - case TIB_TYPE_LIST: - gsl_vector_complex_free (t->value.list); - break; - - case TIB_TYPE_MATRIX: - gsl_matrix_complex_free (t->value.matrix); - break; - - case TIB_TYPE_STRING: - free (t->value.string); - break; - - default: - break; - } - - free (t); - } + if (0 == t->refs) + return; + + if (--t->refs == 0) + { + switch (t->type) + { + case TIB_TYPE_LIST: + gsl_vector_complex_free(t->value.list); + break; + + case TIB_TYPE_MATRIX: + gsl_matrix_complex_free(t->value.matrix); + break; + + case TIB_TYPE_STRING: + free(t->value.string); + break; + + default: + break; + } + + free(t); + } } TIB * -tib_new_complex (double real, double imaginary) +tib_new_complex(double real, double imaginary) { - TIB *out = malloc (sizeof (TIB)); - if (NULL == out) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - out->type = TIB_TYPE_COMPLEX; - out->refs = 1; - GSL_SET_COMPLEX (&out->value.number, real, imaginary); - - return out; + TIB *out = malloc(sizeof(TIB)); + if (NULL == out) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + out->type = TIB_TYPE_COMPLEX; + out->refs = 1; + GSL_SET_COMPLEX(&out->value.number, real, imaginary); + + return out; } TIB * -tib_new_str (const char *value) +tib_new_str(const char *value) { - if (NULL == value) - return NULL; - - TIB *out = malloc (sizeof (TIB)); - if (NULL == out) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - out->type = TIB_TYPE_STRING; - out->refs = 1; - out->value.string = malloc ((strlen (value) + 1) * sizeof (char)); - if (NULL == out->value.string) - { - tib_errno = TIB_EALLOC; - free (out); - return NULL; - } - - strcpy (out->value.string, value); - return out; + if (NULL == value) + return NULL; + + TIB *out = malloc(sizeof(TIB)); + if (NULL == out) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + out->type = TIB_TYPE_STRING; + out->refs = 1; + out->value.string = malloc((strlen(value) + 1) * sizeof(char)); + if (NULL == out->value.string) + { + tib_errno = TIB_EALLOC; + free(out); + return NULL; + } + + strcpy(out->value.string, value); + return out; } TIB * -tib_new_list (const gsl_complex *value, size_t len) +tib_new_list(const gsl_complex *value, size_t len) { - TIB *out = malloc (sizeof (TIB)); - if (NULL == out) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - out->type = TIB_TYPE_LIST; - out->refs = 1; - out->value.list = gsl_vector_complex_alloc (len); - if (!out->value.list) - { - tib_errno = TIB_EALLOC; - free (out); - return NULL; - } - - size_t i; - if (value != NULL) - for (i = 0; i < len; ++i) - gsl_vector_complex_set (out->value.list, i, value[i]); - - return out; + TIB *out = malloc(sizeof(TIB)); + if (NULL == out) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + out->type = TIB_TYPE_LIST; + out->refs = 1; + out->value.list = gsl_vector_complex_alloc(len); + if (!out->value.list) + { + tib_errno = TIB_EALLOC; + free(out); + return NULL; + } + + size_t i; + if (value != NULL) + for (i = 0; i < len; ++i) + gsl_vector_complex_set(out->value.list, i, value[i]); + + return out; } TIB * -tib_new_matrix (const gsl_complex **value, size_t w, size_t h) +tib_new_matrix(const gsl_complex **value, size_t w, size_t h) { - TIB *out = malloc (sizeof (TIB)); - if (NULL == out) - { - tib_errno = TIB_EALLOC; - return NULL; - } - - out->type = TIB_TYPE_MATRIX; - out->refs = 1; - out->value.matrix = gsl_matrix_complex_alloc (h, w); - if (!out->value.matrix) - { - tib_errno = TIB_EALLOC; - free (out); - return NULL; - } - - size_t i, j; - if (value != NULL) - for (i = 0; i < h; ++i) - for (j = 0; j < w; ++j) - gsl_matrix_complex_set (out->value.matrix, i, j, value[i][j]); - - return out; + TIB *out = malloc(sizeof(TIB)); + if (NULL == out) + { + tib_errno = TIB_EALLOC; + return NULL; + } + + out->type = TIB_TYPE_MATRIX; + out->refs = 1; + out->value.matrix = gsl_matrix_complex_alloc(h, w); + if (!out->value.matrix) + { + tib_errno = TIB_EALLOC; + free(out); + return NULL; + } + + size_t i, j; + if (value != NULL) + for (i = 0; i < h; ++i) + for (j = 0; j < w; ++j) + gsl_matrix_complex_set(out->value.matrix, i, j, + value[i][j]); + + return out; } enum tib_type -tib_type (const TIB *t) +tib_type(const TIB *t) { - return t->type; + return t->type; } gsl_complex -tib_complex_value (const TIB *t) +tib_complex_value(const TIB *t) { - if (t->type == TIB_TYPE_COMPLEX) - return t->value.number; + if (t->type == TIB_TYPE_COMPLEX) + return t->value.number; - tib_errno = TIB_ETYPE; - return (gsl_complex) {.dat = {0, 0}}; + tib_errno = TIB_ETYPE; + return (gsl_complex) { .dat = { 0, 0 } }; } const char * -tib_str_value (const TIB *t) +tib_str_value(const TIB *t) { - if (t->type == TIB_TYPE_STRING) - return t->value.string; + if (t->type == TIB_TYPE_STRING) + return t->value.string; - tib_errno = TIB_ETYPE; - return NULL; + tib_errno = TIB_ETYPE; + return NULL; } const gsl_vector_complex * -tib_list_value (const TIB *t) +tib_list_value(const TIB *t) { - if (t->type == TIB_TYPE_LIST) - return t->value.list; + if (t->type == TIB_TYPE_LIST) + return t->value.list; - tib_errno = TIB_ETYPE; - return NULL; + tib_errno = TIB_ETYPE; + return NULL; } const gsl_matrix_complex * -tib_matrix_value (const TIB *t) +tib_matrix_value(const TIB *t) { - if (t->type == TIB_TYPE_MATRIX) - return t->value.matrix; + if (t->type == TIB_TYPE_MATRIX) + return t->value.matrix; - tib_errno = TIB_ETYPE; - return NULL; + tib_errno = TIB_ETYPE; + return NULL; } static void -format_double_str (char *buf, double value) +format_double_str(char *buf, double value) { - snprintf (buf, 17, "%.*g", 10, value); + snprintf(buf, 17, "%.*g", 10, value); } static bool -abs_too_big (double value) +abs_too_big(double value) { - return fabs (value) > 10e100; + return fabs(value) > 10e100; } static int -complex_toexpr (struct tib_expr *dest, gsl_complex value) +complex_toexpr(struct tib_expr *dest, gsl_complex value) { - int rc; - char buf[17]; - - if (abs_too_big (GSL_REAL (value)) || abs_too_big (GSL_IMAG (value))) - return TIB_EOVER; - - dest->len = 0; - - if (GSL_REAL (value)) - { - format_double_str (buf, GSL_REAL (value)); - - rc = load_expr_num (dest, buf); - if (rc) - return rc; - } - - if (GSL_IMAG (value)) - { - if (GSL_IMAG (value) > 0 && GSL_REAL (value)) - { - rc = tib_expr_push (dest, '+'); - if (rc) - return rc; - } - - if (GSL_IMAG (value) != 1.0) - { - format_double_str (buf, GSL_IMAG (value)); - rc = load_expr_num (dest, buf); - if (rc) - return rc; - } - - rc = tib_expr_push (dest, 'i'); - if (rc) - return rc; - } - else if (!GSL_REAL (value)) - { - rc = tib_expr_push (dest, '0'); - if (rc) - return rc; - } - - return 0; + int rc; + char buf[17]; + + if (abs_too_big(GSL_REAL(value)) || abs_too_big(GSL_IMAG(value))) + return TIB_EOVER; + + dest->len = 0; + + if (GSL_REAL(value)) + { + format_double_str(buf, GSL_REAL(value)); + + rc = load_expr_num(dest, buf); + if (rc) + return rc; + } + + if (GSL_IMAG(value)) + { + if (GSL_IMAG(value) > 0 && GSL_REAL(value)) + { + rc = tib_expr_push(dest, '+'); + if (rc) + return rc; + } + + if (GSL_IMAG(value) != 1.0) + { + format_double_str(buf, GSL_IMAG(value)); + rc = load_expr_num(dest, buf); + if (rc) + return rc; + } + + rc = tib_expr_push(dest, 'i'); + if (rc) + return rc; + } + else if (!GSL_REAL(value)) + { + rc = tib_expr_push(dest, '0'); + if (rc) + return rc; + } + + return 0; } int -tib_toexpr (struct tib_expr *dest, const TIB *src) +tib_toexpr(struct tib_expr *dest, const TIB *src) { - int rc = tib_expr_init (dest); - if (rc) - return rc; - - size_t i; - switch (src->type) - { - case TIB_TYPE_NONE: - rc = load_expr (dest, "Error"); - break; - - case TIB_TYPE_COMPLEX: - rc = complex_toexpr (dest, tib_complex_value (src)); - break; - - case TIB_TYPE_STRING: - rc = load_expr (dest, tib_str_value (src)); - break; - - case TIB_TYPE_LIST: - rc = tib_expr_push (dest, '{'); - if (rc) - break; - - for (i = 0; i < src->value.list->size; ++i) - { - gsl_complex z = gsl_vector_complex_get (src->value.list, i); - rc = complex_toexpr (dest, z); - if (rc) - goto end; - - rc = tib_expr_push (dest, ','); - if (rc) - goto end; - } - - if (i) - dest->data[dest->len - 1] = '}'; - else - rc = tib_expr_push (dest, '}'); - break; - - case TIB_TYPE_MATRIX: - rc = tib_expr_push (dest, '['); - if (rc) - break; - - for (i = 0; i < src->value.matrix->size1; ++i) - { - size_t j; - - rc = tib_expr_push (dest, '['); - if (rc) - goto end; - - for (j = 0; j < src->value.matrix->size2; ++j) - { - gsl_complex z = gsl_matrix_complex_get (src->value.matrix, i, j); - rc = complex_toexpr (dest, z); - if (rc) - goto end; - - rc = tib_expr_push (dest, ','); - if (rc) - goto end; - } - - if (j) - { - dest->data[dest->len - 1] = ']'; - } - else - { - rc = tib_expr_push (dest, ']'); - if (rc) - goto end; - } - - rc = tib_expr_push (dest, ','); - if (rc) - goto end; - } - - if (i) - dest->data[dest->len - 1] = ']'; - else - rc = tib_expr_push (dest, ']'); - break; - } + int rc = tib_expr_init(dest); + if (rc) + return rc; + + size_t i; + switch (src->type) + { + case TIB_TYPE_NONE: + rc = load_expr(dest, "Error"); + break; + + case TIB_TYPE_COMPLEX: + rc = complex_toexpr(dest, tib_complex_value(src)); + break; + + case TIB_TYPE_STRING: + rc = load_expr(dest, tib_str_value(src)); + break; + + case TIB_TYPE_LIST: + rc = tib_expr_push(dest, '{'); + if (rc) + break; + + for (i = 0; i < src->value.list->size; ++i) + { + gsl_complex z = gsl_vector_complex_get(src->value.list, + i); + rc = complex_toexpr(dest, z); + if (rc) + goto end; + + rc = tib_expr_push(dest, ','); + if (rc) + goto end; + } + + if (i) + dest->data[dest->len - 1] = '}'; + else + rc = tib_expr_push(dest, '}'); + break; + + case TIB_TYPE_MATRIX: + rc = tib_expr_push(dest, '['); + if (rc) + break; + + for (i = 0; i < src->value.matrix->size1; ++i) + { + size_t j; + + rc = tib_expr_push(dest, '['); + if (rc) + goto end; + + for (j = 0; j < src->value.matrix->size2; ++j) + { + gsl_complex z; + z = gsl_matrix_complex_get(src->value.matrix, + i, j); + rc = complex_toexpr(dest, z); + if (rc) + goto end; + + rc = tib_expr_push(dest, ','); + if (rc) + goto end; + } + + if (j) + { + dest->data[dest->len - 1] = ']'; + } + else + { + rc = tib_expr_push(dest, ']'); + if (rc) + goto end; + } + + rc = tib_expr_push(dest, ','); + if (rc) + goto end; + } + + if (i) + dest->data[dest->len - 1] = ']'; + else + rc = tib_expr_push(dest, ']'); + break; + } end: - if (rc) - tib_expr_destroy (dest); + if (rc) + tib_expr_destroy(dest); - return rc; + return rc; } TIB * -tib_add (const TIB *t1, const TIB *t2) +tib_add(const TIB *t1, const TIB *t2) { - if (t1->type != t2->type - && !(TIB_TYPE_COMPLEX == t1->type && TIB_TYPE_LIST == t2->type) - && !(TIB_TYPE_LIST == t1->type && TIB_TYPE_COMPLEX == t2->type)) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - char *s; - TIB *temp; - size_t i; - switch (t1->type) - { - case TIB_TYPE_COMPLEX: - if (TIB_TYPE_COMPLEX == t2->type) - { - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - temp->value.number = gsl_complex_add (t1->value.number, - t2->value.number); - - return temp; - } - else - { - temp = tib_copy (t2); - if (NULL == temp) - return NULL; - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t2->value.list, i); - gsl_complex sum = gsl_complex_add (a, t1->value.number); - gsl_vector_complex_set (temp->value.list, i, sum); - } - - return temp; - } - - case TIB_TYPE_STRING: - s = malloc ((strlen (t1->value.string) + strlen (t2->value.string) + 1) - * sizeof (char)); - sprintf (s, "%s%s", t1->value.string, t2->value.string); - temp = tib_new_str (s); - free (s); - return temp; - - case TIB_TYPE_LIST: - if (TIB_TYPE_LIST == t2->type) - { - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - tib_errno = gsl_vector_complex_add (temp->value.list, - t2->value.list); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - } - else - { - return tib_add (t2, t1); - } - - case TIB_TYPE_MATRIX: - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - tib_errno = gsl_matrix_complex_add (temp->value.matrix, - t2->value.matrix); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + if (t1->type != t2->type + && !(TIB_TYPE_COMPLEX == t1->type && TIB_TYPE_LIST == t2->type) + && !(TIB_TYPE_LIST == t1->type && TIB_TYPE_COMPLEX == t2->type)) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + char *s; + TIB *temp; + size_t i; + switch (t1->type) + { + case TIB_TYPE_COMPLEX: + if (TIB_TYPE_COMPLEX == t2->type) + { + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + temp->value.number = gsl_complex_add(t1->value.number, + t2->value.number); + + return temp; + } + else + { + temp = tib_copy(t2); + if (NULL == temp) + return NULL; + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, sum; + a = gsl_vector_complex_get(t2->value.list, i); + sum = gsl_complex_add(a, t1->value.number); + gsl_vector_complex_set(temp->value.list, i, + sum); + } + + return temp; + } + + case TIB_TYPE_STRING: + s = malloc((strlen(t1->value.string) + + strlen(t2->value.string) + 1) * sizeof(char)); + sprintf(s, "%s%s", t1->value.string, t2->value.string); + temp = tib_new_str(s); + free(s); + return temp; + + case TIB_TYPE_LIST: + if (TIB_TYPE_LIST == t2->type) + { + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + tib_errno = gsl_vector_complex_add(temp->value.list, + t2->value.list); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + } + else + { + return tib_add(t2, t1); + } + + case TIB_TYPE_MATRIX: + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + tib_errno = gsl_matrix_complex_add(temp->value.matrix, + t2->value.matrix); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } TIB * -tib_sub (const TIB *t1, const TIB *t2) +tib_sub(const TIB *t1, const TIB *t2) { - if (t1->type != t2->type - && !(TIB_TYPE_COMPLEX == t1->type && TIB_TYPE_LIST == t2->type) - && !(TIB_TYPE_LIST == t1->type && TIB_TYPE_COMPLEX == t2->type)) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - TIB *temp; - size_t i; - switch (t1->type) - { - case TIB_TYPE_COMPLEX: - if (TIB_TYPE_COMPLEX == t2->type) - { - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - temp->value.number = gsl_complex_sub (t1->value.number, - t2->value.number); - - return temp; - } - else - { - temp = tib_copy (t2); - if (NULL == temp) - return NULL; - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t2->value.list, i); - gsl_complex diff = gsl_complex_sub (a, t1->value.number); - gsl_vector_complex_set (temp->value.list, i, diff); - } - - return temp; - } - - case TIB_TYPE_LIST: - if (TIB_TYPE_LIST == t2->type) - { - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - tib_errno = gsl_vector_complex_sub (temp->value.list, - t2->value.list); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - } - else - { - temp = tib_copy (t2); - if (NULL == temp) - return NULL; - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t2->value.list, i); - gsl_complex diff = gsl_complex_sub (t1->value.number, a); - gsl_vector_complex_set (temp->value.list, i, diff); - } - - return temp; - } - - case TIB_TYPE_MATRIX: - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - tib_errno = gsl_matrix_complex_sub (temp->value.matrix, - t2->value.matrix); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + if (t1->type != t2->type + && !(TIB_TYPE_COMPLEX == t1->type && TIB_TYPE_LIST == t2->type) + && !(TIB_TYPE_LIST == t1->type && TIB_TYPE_COMPLEX == t2->type)) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + TIB *temp; + size_t i; + switch (t1->type) + { + case TIB_TYPE_COMPLEX: + if (TIB_TYPE_COMPLEX == t2->type) + { + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + temp->value.number = gsl_complex_sub(t1->value.number, + t2->value.number); + + return temp; + } + else + { + temp = tib_copy(t2); + if (NULL == temp) + return NULL; + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, diff; + a = gsl_vector_complex_get(t2->value.list, i); + diff = gsl_complex_sub(a, t1->value.number); + gsl_vector_complex_set(temp->value.list, i, + diff); + } + + return temp; + } + + case TIB_TYPE_LIST: + if (TIB_TYPE_LIST == t2->type) + { + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + tib_errno = gsl_vector_complex_sub(temp->value.list, + t2->value.list); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + } + else + { + temp = tib_copy(t2); + if (NULL == temp) + return NULL; + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, diff; + a = gsl_vector_complex_get(t2->value.list, i); + diff = gsl_complex_sub(t1->value.number, a); + gsl_vector_complex_set(temp->value.list, i, + diff); + } + + return temp; + } + + case TIB_TYPE_MATRIX: + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + tib_errno = gsl_matrix_complex_sub(temp->value.matrix, + t2->value.matrix); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } static int -matrix_mul (gsl_matrix_complex *out, const gsl_matrix_complex *m1, - const gsl_matrix_complex *m2) +matrix_mul(gsl_matrix_complex *out, const gsl_matrix_complex *m1, + const gsl_matrix_complex *m2) { - gsl_complex a = { .dat={1, 1} }, b = { .dat={0, 0} }; - return gsl_blas_zgemm (CblasNoTrans, CblasNoTrans, a, m1, m2, b, out); + gsl_complex a = { .dat = {1, 1} }, b = { .dat = { 0, 0 } }; + return gsl_blas_zgemm(CblasNoTrans, CblasNoTrans, a, m1, m2, b, out); } TIB * -tib_mul (const TIB *t1, const TIB *t2) +tib_mul(const TIB *t1, const TIB *t2) { - if (t1->type != t2->type) - { - switch (t1->type) - { - case TIB_TYPE_COMPLEX: - if (TIB_TYPE_NONE == t2->type || TIB_TYPE_STRING == t2->type) - { - tib_errno = TIB_ETYPE; - return NULL; - } - break; - - case TIB_TYPE_LIST: - case TIB_TYPE_MATRIX: - if (TIB_TYPE_COMPLEX != t2->type) - { - tib_errno = TIB_ETYPE; - return NULL; - } - break; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } - } - - TIB *temp; - size_t i, j; - switch (t1->type) - { - case TIB_TYPE_COMPLEX: - if (TIB_TYPE_COMPLEX == t2->type) - { - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - temp->value.number = gsl_complex_mul (t1->value.number, - t2->value.number); - - return temp; - } - else - { - temp = tib_copy (t2); - if (NULL == temp) - return NULL; - - gsl_complex a, product; - if (TIB_TYPE_LIST == t2->type) - { - for (i = 0; i < t2->value.list->size; ++i) - { - a = gsl_vector_complex_get (t2->value.list, i); - product = gsl_complex_mul (t1->value.number, a); - gsl_vector_complex_set (temp->value.list, i, product); - } - } - else /* must be matrix */ - { - for (i = 0; i < t2->value.matrix->size1; ++i) - for (j = 0; j < t2->value.matrix->size2; ++j) - { - a = gsl_matrix_complex_get (t2->value.matrix, i, j); - product = gsl_complex_mul (t1->value.number, a); - gsl_matrix_complex_set (temp->value.matrix, i, j, product); - } - } - - return temp; - } - - case TIB_TYPE_LIST: - if (TIB_TYPE_LIST == t2->type) - { - if (t1->value.list->size != t2->value.list->size) - { - tib_errno = TIB_EDIM; - return NULL; - } - - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t1->value.list, i); - gsl_complex b = gsl_vector_complex_get (t2->value.list, i); - gsl_complex product = gsl_complex_mul (a, b); - gsl_vector_complex_set (temp->value.list, i, product); - } - - return temp; - } - else /* must be complex */ - { - return tib_mul (t2, t1); - } - - case TIB_TYPE_MATRIX: - if (TIB_TYPE_MATRIX == t2->type) - { - if (t1->value.matrix->size2 != t2->value.matrix->size1) - { - tib_errno = TIB_EDIM; - return NULL; - } - - temp = tib_new_matrix (NULL, t1->value.matrix->size1, - t2->value.matrix->size2); - if (NULL == temp) - return NULL; - - tib_errno = matrix_mul (temp->value.matrix, t1->value.matrix, - t2->value.matrix); - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - } - else /* must be complex */ - { - return tib_mul (t2, t1); - } - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + if (t1->type != t2->type) + { + switch (t1->type) + { + case TIB_TYPE_COMPLEX: + if (TIB_TYPE_NONE == t2->type + || TIB_TYPE_STRING == t2->type) + { + tib_errno = TIB_ETYPE; + return NULL; + } + break; + + case TIB_TYPE_LIST: + case TIB_TYPE_MATRIX: + if (TIB_TYPE_COMPLEX != t2->type) + { + tib_errno = TIB_ETYPE; + return NULL; + } + break; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } + } + + TIB *temp; + size_t i, j; + switch (t1->type) + { + case TIB_TYPE_COMPLEX: + if (TIB_TYPE_COMPLEX == t2->type) + { + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + temp->value.number = gsl_complex_mul(t1->value.number, + t2->value.number); + + return temp; + } + else + { + temp = tib_copy(t2); + if (NULL == temp) + return NULL; + + gsl_complex a, product; + if (TIB_TYPE_LIST == t2->type) + { + for (i = 0; i < t2->value.list->size; ++i) + { + a = gsl_vector_complex_get(t2->value. + list, i); + product = + gsl_complex_mul(t1->value.number, + a); + gsl_vector_complex_set(temp->value.list, + i, product); + } + } + else // must be matrix + { + for (i = 0; i < t2->value.matrix->size1; ++i) + for (j = 0; j < t2->value.matrix->size2; + ++j) + { + a = gsl_matrix_complex_get(t2->value.matrix, + i, j); + product = gsl_complex_mul(t1->value.number, + a); + gsl_matrix_complex_set(temp->value.matrix, + i, j, + product); + } + } + + return temp; + } + + case TIB_TYPE_LIST: + if (TIB_TYPE_LIST == t2->type) + { + if (t1->value.list->size != t2->value.list->size) + { + tib_errno = TIB_EDIM; + return NULL; + } + + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, b, product; + a = gsl_vector_complex_get(t1->value.list, i); + b = gsl_vector_complex_get(t2->value.list, i); + product = gsl_complex_mul(a, b); + gsl_vector_complex_set(temp->value.list, i, + product); + } + + return temp; + } + else // must be complex + { + return tib_mul(t2, t1); + } + + case TIB_TYPE_MATRIX: + if (TIB_TYPE_MATRIX == t2->type) + { + if (t1->value.matrix->size2 != t2->value.matrix->size1) + { + tib_errno = TIB_EDIM; + return NULL; + } + + temp = tib_new_matrix(NULL, t1->value.matrix->size1, + t2->value.matrix->size2); + if (NULL == temp) + return NULL; + + tib_errno = matrix_mul(temp->value.matrix, + t1->value.matrix, t2->value.matrix); + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + } + else // must be complex + { + return tib_mul(t2, t1); + } + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } static bool -less_than_0 (gsl_complex x) +less_than_0(gsl_complex x) { - return gsl_complex_abs (x) < 0; + return gsl_complex_abs(x) < 0; } #define COMPLEX_ONE ((gsl_complex) { .dat = { 1, 0 } }) static TIB * -inverse (const TIB *t) +inverse(const TIB *t) { - TIB *temp = tib_copy (t); - if (NULL == temp) - return NULL; - - size_t i; - switch (t->type) - { - case TIB_TYPE_COMPLEX: - temp->value.number = gsl_complex_div (COMPLEX_ONE, t->value.number); - return temp; - - case TIB_TYPE_LIST: - for (i = 0; i < t->value.list->size; ++i) - { - gsl_complex z = gsl_vector_complex_get (t->value.list, i); - gsl_vector_complex_set (temp->value.list, i, - gsl_complex_div (COMPLEX_ONE, z)); - } - - return temp; - - case TIB_TYPE_MATRIX: - // SPILLS OVER! - - default: - tib_decref (temp); - tib_errno = TIB_ETYPE; - return NULL; - } + TIB *temp = tib_copy(t); + if (NULL == temp) + return NULL; + + size_t i; + switch (t->type) + { + case TIB_TYPE_COMPLEX: + temp->value.number = gsl_complex_div(COMPLEX_ONE, + t->value.number); + return temp; + + case TIB_TYPE_LIST: + for (i = 0; i < t->value.list->size; ++i) + { + gsl_complex z = gsl_vector_complex_get(t->value.list, + i); + gsl_vector_complex_set(temp->value.list, i, + gsl_complex_div(COMPLEX_ONE, z)); + } + + return temp; + + case TIB_TYPE_MATRIX: + // SPILLS OVER! + + default: + tib_decref(temp); + tib_errno = TIB_ETYPE; + return NULL; + } } static bool -is_zero (gsl_complex z) +is_zero(gsl_complex z) { - return 0 == GSL_REAL (z) && 0 == GSL_IMAG (z); + return 0 == GSL_REAL(z) && 0 == GSL_IMAG(z); } TIB * -tib_div (const TIB *t1, const TIB *t2) +tib_div(const TIB *t1, const TIB *t2) { - if (!(TIB_TYPE_COMPLEX == t1->type || TIB_TYPE_LIST == t1->type) - || !(TIB_TYPE_COMPLEX == t2->type || TIB_TYPE_LIST == t2->type)) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - TIB *temp; - size_t i; - switch (t1->type) - { - case TIB_TYPE_COMPLEX: - if (TIB_TYPE_COMPLEX == t2->type) - { - if (is_zero (t2->value.number)) - { - tib_errno = TIB_DBYZERO; - return NULL; - } - - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - temp->value.number = gsl_complex_div (t1->value.number, - t2->value.number); - } - else /* must be list */ - { - temp = tib_copy (t2); - if (NULL == temp) - return NULL; - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t2->value.list, i); - if (is_zero (a)) - { - tib_decref (temp); - tib_errno = TIB_DBYZERO; - return NULL; - } - - gsl_complex quotient = gsl_complex_div (t1->value.number, a); - gsl_vector_complex_set (temp->value.list, i, quotient); - } - } - - return temp; - - case TIB_TYPE_LIST: - temp = tib_copy (t1); - if (NULL == temp) - return NULL; - - if (TIB_TYPE_LIST == t2->type) - { - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t1->value.list, i); - gsl_complex b = gsl_vector_complex_get (t2->value.list, i); - if (is_zero (b)) - { - tib_decref (temp); - tib_errno = TIB_DBYZERO; - return NULL; - } - - gsl_complex quotient = gsl_complex_div (a, b); - gsl_vector_complex_set (temp->value.list, i, quotient); - } - } - else /* must be complex */ - { - if (is_zero (t2->value.number)) - { - tib_decref (temp); - tib_errno = TIB_DBYZERO; - return NULL; - } - - for (i = 0; i < temp->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t1->value.list, i); - gsl_complex quotient = gsl_complex_div (a, t2->value.number); - gsl_vector_complex_set (temp->value.list, i, quotient); - } - } - - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + if (!(TIB_TYPE_COMPLEX == t1->type || TIB_TYPE_LIST == t1->type) + || !(TIB_TYPE_COMPLEX == t2->type || TIB_TYPE_LIST == t2->type)) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + TIB *temp; + size_t i; + switch (t1->type) + { + case TIB_TYPE_COMPLEX: + if (TIB_TYPE_COMPLEX == t2->type) + { + if (is_zero(t2->value.number)) + { + tib_errno = TIB_DBYZERO; + return NULL; + } + + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + temp->value.number = gsl_complex_div(t1->value.number, + t2->value.number); + } + else // must be list + { + temp = tib_copy(t2); + if (NULL == temp) + return NULL; + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, q; + a = gsl_vector_complex_get(t2->value.list, i); + if (is_zero(a)) + { + tib_decref(temp); + tib_errno = TIB_DBYZERO; + return NULL; + } + + q = gsl_complex_div(t1->value.number, a); + gsl_vector_complex_set(temp->value.list, i, q); + } + } + + return temp; + + case TIB_TYPE_LIST: + temp = tib_copy(t1); + if (NULL == temp) + return NULL; + + if (TIB_TYPE_LIST == t2->type) + { + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, b, q; + a = gsl_vector_complex_get(t1->value.list, i); + b = gsl_vector_complex_get(t2->value.list, i); + if (is_zero(b)) + { + tib_decref(temp); + tib_errno = TIB_DBYZERO; + return NULL; + } + + q = gsl_complex_div(a, b); + gsl_vector_complex_set(temp->value.list, i, q); + } + } + else // must be complex + { + if (is_zero(t2->value.number)) + { + tib_decref(temp); + tib_errno = TIB_DBYZERO; + return NULL; + } + + for (i = 0; i < temp->value.list->size; ++i) + { + gsl_complex a, q; + a = gsl_vector_complex_get(t1->value.list, i); + q = gsl_complex_div(a, t2->value.number); + gsl_vector_complex_set(temp->value.list, i, q); + } + } + + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } static gsl_complex -complex_root (gsl_complex z, gsl_complex root) +complex_root(gsl_complex z, gsl_complex root) { - return gsl_complex_pow (z, gsl_complex_div (COMPLEX_ONE, root)); + return gsl_complex_pow(z, gsl_complex_div(COMPLEX_ONE, root)); } TIB * -tib_root (const TIB *t, gsl_complex root) +tib_root(const TIB *t, gsl_complex root) { - TIB *temp; - size_t i; - - if (TIB_TYPE_COMPLEX != t->type && TIB_TYPE_LIST != t->type) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - temp = tib_copy (t); - if (NULL == temp) - return NULL; - - switch (t->type) - { - case TIB_TYPE_COMPLEX: - temp->value.number = complex_root (t->value.number, root); - return temp; - - case TIB_TYPE_LIST: - for (i = 0; i < t->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t->value.list, i); - gsl_vector_complex_set (temp->value.list, i, complex_root (a, root)); - } - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + TIB *temp; + size_t i; + + if (TIB_TYPE_COMPLEX != t->type && TIB_TYPE_LIST != t->type) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + temp = tib_copy(t); + if (NULL == temp) + return NULL; + + switch (t->type) + { + case TIB_TYPE_COMPLEX: + temp->value.number = complex_root(t->value.number, root); + return temp; + + case TIB_TYPE_LIST: + for (i = 0; i < t->value.list->size; ++i) + { + gsl_complex a = gsl_vector_complex_get(t->value.list, + i); + gsl_vector_complex_set(temp->value.list, i, + complex_root(a, root)); + } + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } static bool -is_int (gsl_complex z) +is_int(gsl_complex z) { - return fmod (GSL_REAL (z), 1.0) == 0 && fmod (GSL_IMAG (z), 1.0) == 0; + return fmod(GSL_REAL(z), 1.0) == 0 && fmod(GSL_IMAG(z), 1.0) == 0; } TIB * -tib_pow (const TIB *t, const TIB *power) +tib_pow(const TIB *t, const TIB *power) { - TIB *temp; - - if (TIB_TYPE_COMPLEX != power->type) - { - tib_errno = TIB_ETYPE; - return NULL; - } - - gsl_complex exp = tib_complex_value (power); - - if (less_than_0 (exp)) - { - temp = inverse (t); - exp = gsl_complex_negative (exp); - } - else - { - temp = tib_copy (t); - } - - if (NULL == temp) - { - tib_decref (temp); - return NULL; - } - - size_t i; - switch (t->type) - { - case TIB_TYPE_COMPLEX: - temp->value.number = gsl_complex_pow (t->value.number, exp); - return temp; - - case TIB_TYPE_LIST: - for (i = 0; i < t->value.list->size; ++i) - { - gsl_complex a = gsl_vector_complex_get (t->value.list, i); - gsl_vector_complex_set (temp->value.list, i, - gsl_complex_pow (a, exp)); - } - return temp; - - case TIB_TYPE_MATRIX: - if (t->value.matrix->size1 != t->value.matrix->size2) - { - tib_errno = TIB_EDIM; - tib_decref (temp); - return NULL; - } - - if (!is_int (exp)) - { - tib_errno = TIB_EDOMAIN; - tib_decref (temp); - return NULL; - } - - if (GSL_IMAG (exp)) - { - tib_errno = TIB_ETYPE; - tib_decref (temp); - return NULL; - } - - TIB *tempmat = tib_copy (temp); - if (NULL == tempmat) - { - tib_decref (temp); - return NULL; - } - - for (i = 0; i < GSL_REAL (exp); ++i) - { - tib_errno = matrix_mul (temp->value.matrix, tempmat->value.matrix, - t->value.matrix); - if (tib_errno) - break; - - tib_errno = gsl_matrix_complex_memcpy (tempmat->value.matrix, - temp->value.matrix); - if (tib_errno) - break; - } - - tib_decref (tempmat); - - if (tib_errno) - { - tib_decref (temp); - return NULL; - } - - return temp; - - default: - tib_errno = TIB_ETYPE; - return NULL; - } + TIB *temp; + + if (TIB_TYPE_COMPLEX != power->type) + { + tib_errno = TIB_ETYPE; + return NULL; + } + + gsl_complex exp = tib_complex_value(power); + + if (less_than_0(exp)) + { + temp = inverse(t); + exp = gsl_complex_negative(exp); + } + else + { + temp = tib_copy(t); + } + + if (NULL == temp) + { + tib_decref(temp); + return NULL; + } + + size_t i; + switch (t->type) + { + case TIB_TYPE_COMPLEX: + temp->value.number = gsl_complex_pow(t->value.number, exp); + return temp; + + case TIB_TYPE_LIST: + for (i = 0; i < t->value.list->size; ++i) + { + gsl_complex a = gsl_vector_complex_get(t->value.list, + i); + gsl_vector_complex_set(temp->value.list, i, + gsl_complex_pow(a, exp)); + } + return temp; + + case TIB_TYPE_MATRIX: + if (t->value.matrix->size1 != t->value.matrix->size2) + { + tib_errno = TIB_EDIM; + tib_decref(temp); + return NULL; + } + + if (!is_int(exp)) + { + tib_errno = TIB_EDOMAIN; + tib_decref(temp); + return NULL; + } + + if (GSL_IMAG(exp)) + { + tib_errno = TIB_ETYPE; + tib_decref(temp); + return NULL; + } + + TIB *tempmat = tib_copy(temp); + if (NULL == tempmat) + { + tib_decref(temp); + return NULL; + } + + for (i = 0; i < GSL_REAL(exp); ++i) + { + tib_errno = matrix_mul(temp->value.matrix, + tempmat->value.matrix, + t->value.matrix); + if (tib_errno) + break; + + tib_errno = + gsl_matrix_complex_memcpy(tempmat->value.matrix, + temp->value.matrix); + if (tib_errno) + break; + } + + tib_decref(tempmat); + + if (tib_errno) + { + tib_decref(temp); + return NULL; + } + + return temp; + + default: + tib_errno = TIB_ETYPE; + return NULL; + } } TIB * -tib_factorial (const TIB *t) +tib_factorial(const TIB *t) { - if (t->type != TIB_TYPE_COMPLEX || GSL_IMAG (t->value.number)) - { - tib_errno = TIB_ETYPE; - return NULL; - } + if (t->type != TIB_TYPE_COMPLEX || GSL_IMAG(t->value.number)) + { + tib_errno = TIB_ETYPE; + return NULL; + } - return tib_new_complex (gsl_sf_gamma (GSL_REAL (t->value.number) + 1), 0); + return tib_new_complex(gsl_sf_gamma(GSL_REAL(t->value.number) + 1), 0); } TIB * -tib_toradians (const TIB *t) +tib_toradians(const TIB *t) { - TIB *factor = tib_new_complex (3.141592653589793238462643383279502884 / 180, - 0); - if (!factor) - return NULL; + TIB *factor = tib_new_complex(3.141592653589793238462643383279502884 / 180, + 0); + if (!factor) + return NULL; - TIB *temp = tib_mul (t, factor); - tib_decref (factor); + TIB *temp = tib_mul(t, factor); + tib_decref(factor); - return temp; + return temp; } diff --git a/src/tibtype.h b/src/tibtype.h index 68549b7..9361687 100644 --- a/src/tibtype.h +++ b/src/tibtype.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015-2016 Delwink, LLC + * Copyright (C) 2015-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -27,96 +27,96 @@ #include "tibexpr.h" enum tib_type - { - TIB_TYPE_NONE=0, - TIB_TYPE_COMPLEX, - TIB_TYPE_STRING, - TIB_TYPE_LIST, - TIB_TYPE_MATRIX - }; +{ + TIB_TYPE_NONE = 0, + TIB_TYPE_COMPLEX, + TIB_TYPE_STRING, + TIB_TYPE_LIST, + TIB_TYPE_MATRIX +}; union variant { - gsl_complex number; - char *string; - gsl_vector_complex *list; - gsl_matrix_complex *matrix; + gsl_complex number; + char *string; + gsl_vector_complex *list; + gsl_matrix_complex *matrix; }; typedef struct { - enum tib_type type; - union variant value; - size_t refs; + enum tib_type type; + union variant value; + size_t refs; } TIB; TIB * -tib_empty (void); +tib_empty(void); TIB * -tib_copy (const TIB *t); +tib_copy(const TIB *t); void -tib_incref (TIB *t); +tib_incref(TIB *t); void -tib_decref (TIB *t); +tib_decref(TIB *t); TIB * -tib_new_complex (double real, double imaginary); +tib_new_complex(double real, double imaginary); TIB * -tib_new_str (const char *value); +tib_new_str(const char *value); TIB * -tib_new_list (const gsl_complex *value, size_t len); +tib_new_list(const gsl_complex *value, size_t len); TIB * -tib_new_matrix (const gsl_complex **value, size_t w, size_t h); +tib_new_matrix(const gsl_complex **value, size_t w, size_t h); enum tib_type -tib_type (const TIB *t); +tib_type(const TIB *t); gsl_complex -tib_complex_value (const TIB *t); +tib_complex_value(const TIB *t); const char * -tib_str_value (const TIB *t); +tib_str_value(const TIB *t); const gsl_vector_complex * -tib_list_value (const TIB *t); +tib_list_value(const TIB *t); const gsl_matrix_complex * -tib_matrix_value (const TIB *t); +tib_matrix_value(const TIB *t); int -tib_toexpr (struct tib_expr *dest, const TIB *src); +tib_toexpr(struct tib_expr *dest, const TIB *src); TIB * -tib_add (const TIB *t1, const TIB *t2); +tib_add(const TIB *t1, const TIB *t2); TIB * -tib_sub (const TIB *t1, const TIB *t2); +tib_sub(const TIB *t1, const TIB *t2); TIB * -tib_mul (const TIB *t1, const TIB *t2); +tib_mul(const TIB *t1, const TIB *t2); TIB * -tib_div (const TIB *t1, const TIB *t2); +tib_div(const TIB *t1, const TIB *t2); TIB * -tib_pow (const TIB *t, const TIB *power); +tib_pow(const TIB *t, const TIB *power); TIB * -tib_root (const TIB *t, gsl_complex root); +tib_root(const TIB *t, gsl_complex root); TIB * -tib_factorial (const TIB *t); +tib_factorial(const TIB *t); TIB * -tib_log (const TIB *t); +tib_log(const TIB *t); TIB * -tib_toradians (const TIB *t); +tib_toradians(const TIB *t); #endif diff --git a/src/tibvar.c b/src/tibvar.c index f25061a..c3a3fae 100644 --- a/src/tibvar.c +++ b/src/tibvar.c @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015 Delwink, LLC + * Copyright (C) 2015, 2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,127 +24,127 @@ struct varlist { - tib_Variable *vars; - int len; + tib_Variable *vars; + int len; }; -static struct varlist varlist = - { - .len = 0, - .vars = NULL - }; +static struct varlist varlist = { + .len = 0, + .vars = NULL +}; int -tib_var_init () +tib_var_init() { - int rc; - TIB *t; - -#define ADD(K,V) \ - { \ - t = (V); \ - if (t) \ - { \ - rc = tib_var_set ((K), t); \ - tib_decref (t); \ - } \ - else \ - { \ - rc = tib_errno; \ - } \ - \ - if (rc) \ - goto end; \ - } - - ADD ('e', tib_new_complex (2.718281828459045235360287471352662498, 0)); - ADD (TIB_CHAR_PI, - tib_new_complex (3.141592653589793238462643383279502884, 0)); + int rc; + TIB *t; + +#define ADD(K,V) \ + { \ + t = (V); \ + if (t) \ + { \ + rc = tib_var_set((K), t); \ + tib_decref(t); \ + } \ + else \ + { \ + rc = tib_errno; \ + } \ + \ + if (rc) \ + goto end; \ + } + + ADD('e', tib_new_complex(2.718281828459045235360287471352662498, 0)); + ADD(TIB_CHAR_PI, + tib_new_complex(3.141592653589793238462643383279502884, 0)); #undef ADD end: - return rc; + return rc; } void -tib_var_free () +tib_var_free() { - for (int i = 0; i < varlist.len; ++i) - tib_decref (varlist.vars[i].value); + for (int i = 0; i < varlist.len; ++i) + tib_decref(varlist.vars[i].value); - free (varlist.vars); + free(varlist.vars); - varlist.len = 0; - varlist.vars = NULL; + varlist.len = 0; + varlist.vars = NULL; } static int -add_var (int key, const TIB *value) +add_var(int key, const TIB *value) { - tib_Variable *old = varlist.vars; - - ++varlist.len; - varlist.vars = realloc (varlist.vars, varlist.len * sizeof (tib_Variable)); - if (NULL == varlist.vars) - { - varlist.vars = old; - --varlist.len; - return TIB_EALLOC; - } - - tib_errno = 0; - tib_Variable *new = varlist.vars + varlist.len - 1; - new->key = key; - new->value = tib_copy (value); - if (tib_errno) - --varlist.len; - - return tib_errno; + tib_Variable *old = varlist.vars; + + ++varlist.len; + varlist.vars = realloc(varlist.vars, + varlist.len * sizeof(tib_Variable)); + if (NULL == varlist.vars) + { + varlist.vars = old; + --varlist.len; + return TIB_EALLOC; + } + + tib_errno = 0; + tib_Variable *new = varlist.vars + varlist.len - 1; + new->key = key; + new->value = tib_copy(value); + if (tib_errno) + --varlist.len; + + return tib_errno; } int -tib_var_set (int key, const TIB *value) +tib_var_set(int key, const TIB *value) { - if (!tib_is_var (key)) - return add_var (key, value); - - for (int i = 0; i < varlist.len; ++i) - { - if (key == varlist.vars[i].key) - { - TIB *old = varlist.vars[i].value; - varlist.vars[i].value = tib_copy (value); - if (tib_errno) - { - varlist.vars[i].value = old; - return tib_errno; - } - - tib_decref (old); - return 0; - } - } - - return TIB_EINDEX; /* should be unreachable */ + if (!tib_is_var(key)) + return add_var(key, value); + + for (int i = 0; i < varlist.len; ++i) + { + if (key == varlist.vars[i].key) + { + TIB *old = varlist.vars[i].value; + varlist.vars[i].value = tib_copy(value); + if (tib_errno) + { + varlist.vars[i].value = old; + return tib_errno; + } + + tib_decref(old); + return 0; + } + } + + return TIB_EINDEX; // should be unreachable } TIB * -tib_var_get (int key) +tib_var_get(int key) { - for (int i = 0; i < varlist.len; ++i) - if (key == varlist.vars[i].key) - return tib_copy (varlist.vars[i].value); + for (int i = 0; i < varlist.len; ++i) + if (key == varlist.vars[i].key) + return tib_copy(varlist.vars[i].value); - return tib_new_complex (0, 0); + return tib_new_complex(0, 0); } bool -tib_is_var (int key) +tib_is_var(int key) { - for (int i = 0; i < varlist.len; ++i) - if (key == varlist.vars[i].key) - return true; + for (int i = 0; i < varlist.len; ++i) + if (key == varlist.vars[i].key) + return true; - return false; + return false; } diff --git a/src/tibvar.h b/src/tibvar.h index 134ad1b..84bafa6 100644 --- a/src/tibvar.h +++ b/src/tibvar.h @@ -1,6 +1,6 @@ /* * libtib - Read, write, and evaluate TI BASIC programs - * Copyright (C) 2015 Delwink, LLC + * Copyright (C) 2015, 2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -24,23 +24,23 @@ typedef struct { - int key; - TIB *value; + int key; + TIB *value; } tib_Variable; int -tib_var_init (void); +tib_var_init(void); void -tib_var_free (void); +tib_var_free(void); int -tib_var_set (int key, const TIB *value); +tib_var_set(int key, const TIB *value); TIB * -tib_var_get (int key); +tib_var_get(int key); bool -tib_is_var (int key); +tib_is_var(int key); #endif diff --git a/src/util.c b/src/util.c index cfa7fc0..a54288d 100644 --- a/src/util.c +++ b/src/util.c @@ -22,94 +22,93 @@ #include "util.h" int -load_expr (struct tib_expr *dest, const char *src) +load_expr(struct tib_expr *dest, const char *src) { - unsigned int len = strlen (src); - for (unsigned int i = 0; i < len; ++i) - { - int rc = tib_expr_push (dest, src[i]); - if (rc) - return rc; - } + unsigned int len = strlen(src); + for (unsigned int i = 0; i < len; ++i) + { + int rc = tib_expr_push(dest, src[i]); + if (rc) + return rc; + } - return 0; + return 0; } int -load_expr_num (struct tib_expr *dest, const char *src) +load_expr_num(struct tib_expr *dest, const char *src) { - int rc = load_expr (dest, src); - if (rc) - return rc; + int rc = load_expr(dest, src); + if (rc) + return rc; - int e = tib_expr_indexof_r (dest, 'e'); - if (e >= 0) - { - tib_expr_delete (dest, e); + int e = tib_expr_indexof_r(dest, 'e'); + if (e >= 0) + { + tib_expr_delete(dest, e); - if ('+' == dest->data[e]) - dest->data[e] = TIB_CHAR_EPOW10; - else - rc = tib_expr_insert (dest, e, TIB_CHAR_EPOW10); - } + if ('+' == dest->data[e]) + dest->data[e] = TIB_CHAR_EPOW10; + else + rc = tib_expr_insert(dest, e, TIB_CHAR_EPOW10); + } - return rc; + return rc; } const char * -display_special_char (int c) +display_special_char(int c) { - static const int SKIPS[] = - { - TIB_CHAR_DEGREE, - TIB_CHAR_EPOW10, - TIB_CHAR_GREATEREQUAL, - TIB_CHAR_L1, - TIB_CHAR_L2, - TIB_CHAR_L3, - TIB_CHAR_L4, - TIB_CHAR_L5, - TIB_CHAR_L6, - TIB_CHAR_L7, - TIB_CHAR_L8, - TIB_CHAR_L9, - TIB_CHAR_LESSEQUAL, - TIB_CHAR_PI, - TIB_CHAR_SMALL1, - TIB_CHAR_SMALL2, - TIB_CHAR_SMALL3, - TIB_CHAR_SMALL4, - TIB_CHAR_SMALL5, - TIB_CHAR_SMALL6, - TIB_CHAR_SMALL7, - TIB_CHAR_SMALL8, - TIB_CHAR_SMALL9, - TIB_CHAR_SMALL_MINUS, - TIB_CHAR_STO, - TIB_CHAR_THETA - }; + static const int SKIPS[] = { + TIB_CHAR_DEGREE, + TIB_CHAR_EPOW10, + TIB_CHAR_GREATEREQUAL, + TIB_CHAR_L1, + TIB_CHAR_L2, + TIB_CHAR_L3, + TIB_CHAR_L4, + TIB_CHAR_L5, + TIB_CHAR_L6, + TIB_CHAR_L7, + TIB_CHAR_L8, + TIB_CHAR_L9, + TIB_CHAR_LESSEQUAL, + TIB_CHAR_PI, + TIB_CHAR_SMALL1, + TIB_CHAR_SMALL2, + TIB_CHAR_SMALL3, + TIB_CHAR_SMALL4, + TIB_CHAR_SMALL5, + TIB_CHAR_SMALL6, + TIB_CHAR_SMALL7, + TIB_CHAR_SMALL8, + TIB_CHAR_SMALL9, + TIB_CHAR_SMALL_MINUS, + TIB_CHAR_STO, + TIB_CHAR_THETA + }; - for (unsigned int i = 0; i < (sizeof SKIPS / sizeof (int)); ++i) - if (SKIPS[i] == c) - return NULL; + for (unsigned int i = 0; i < (sizeof SKIPS / sizeof(int)); ++i) + if (SKIPS[i] == c) + return NULL; - return tib_special_char_text (c); + return tib_special_char_text(c); } char * -get_expr_display_str (const struct tib_expr *expr) +get_expr_display_str(const struct tib_expr *expr) { - return tib_expr_tostr_f (expr, display_special_char); + return tib_expr_tostr_f(expr, display_special_char); } int -max (int x, int y) +max(int x, int y) { - return (x > y) ? x : y; + return (x > y) ? x : y; } int -min (int x, int y) +min(int x, int y) { - return (x < y) ? x : y; + return (x < y) ? x : y; } diff --git a/src/util.h b/src/util.h index b8898a7..d11b4e8 100644 --- a/src/util.h +++ b/src/util.h @@ -1,6 +1,6 @@ /* * LiberTI - TI-like calculator designed for LibreCalc - * Copyright (C) 2016 Delwink, LLC + * Copyright (C) 2016-2017 Delwink, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by @@ -21,21 +21,21 @@ #include "tibexpr.h" int -load_expr (struct tib_expr *dest, const char *src); +load_expr(struct tib_expr *dest, const char *src); int -load_expr_num (struct tib_expr *dest, const char *src); +load_expr_num(struct tib_expr *dest, const char *src); const char * -display_special_char (int c); +display_special_char(int c); char * -get_expr_display_str (const struct tib_expr *expr); +get_expr_display_str(const struct tib_expr *expr); int -max (int x, int y); +max(int x, int y); int -min (int x, int y); +min(int x, int y); #endif -- cgit v1.2.3