use Gint + add terminal device
This commit is contained in:
commit
b50a84e47b
|
@ -0,0 +1,4 @@
|
|||
.idea
|
||||
build*
|
||||
*.g1a
|
||||
*.g3a
|
|
@ -0,0 +1,208 @@
|
|||
#! /usr/bin/make -f
|
||||
# Default Makefile for fxSDK add-ins. This file was probably copied there by
|
||||
# the [fxsdk] program.
|
||||
#---
|
||||
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
include project.cfg
|
||||
|
||||
# Compiler flags
|
||||
CFLAGSFX = $(CFLAGS) $(CFLAGS_FX) $(INCLUDE_FX)
|
||||
CFLAGSCG = $(CFLAGS) $(CFLAGS_CG) $(INCLUDE_CG)
|
||||
|
||||
# Linker flags
|
||||
LDFLAGSFX := $(LDFLAGS) $(LDFLAGS_FX)
|
||||
LDFLAGSCG := $(LDFLAGS) $(LDFLAGS_CG)
|
||||
|
||||
# Dependency list generation flags
|
||||
depflags = -MMD -MT $@ -MF $(@:.o=.d) -MP
|
||||
# ELF to binary flags
|
||||
BINFLAGS := -R .bss -R .gint_bss
|
||||
|
||||
# G1A and G3A generation flags
|
||||
NAME_G1A ?= $(NAME)
|
||||
NAME_G3A ?= $(NAME)
|
||||
G1AF := -i "$(ICON_FX)" -n "$(NAME_G1A)" --internal="$(INTERNAL)"
|
||||
G3AF := -n basic:"$(NAME_G3A)" -i uns:"$(ICON_CG_UNS)" -i sel:"$(ICON_CG_SEL)"
|
||||
|
||||
ifeq "$(TOOLCHAIN_FX)" ""
|
||||
TOOLCHAIN_FX := sh3eb-elf
|
||||
endif
|
||||
|
||||
ifeq "$(TOOLCHAIN_CG)" ""
|
||||
TOOLCHAIN_CG := sh4eb-elf
|
||||
endif
|
||||
|
||||
# fxconv flags
|
||||
FXCONVFX := --fx --toolchain=$(TOOLCHAIN_FX)
|
||||
FXCONVCG := --cg --toolchain=$(TOOLCHAIN_CG)
|
||||
|
||||
# Determine the compiler install and include path
|
||||
GCC_BASE_FX := $(shell $(TOOLCHAIN_FX)-gcc --print-search-dirs | grep install | sed 's/install: //')
|
||||
GCC_BASE_CG := $(shell $(TOOLCHAIN_CG)-gcc --print-search-dirs | grep install | sed 's/install: //')
|
||||
GCC_INCLUDE_FX := $(GCC_BASE_FX)/include
|
||||
GCC_INCLUDE_CG := $(GCC_BASE_CG)/include
|
||||
|
||||
#
|
||||
# File listings
|
||||
#
|
||||
|
||||
NULL :=
|
||||
TARGET := $(subst $(NULL) $(NULL),-,$(NAME))
|
||||
|
||||
ifeq "$(TARGET_FX)" ""
|
||||
TARGET_FX := $(TARGET).g1a
|
||||
endif
|
||||
|
||||
ifeq "$(TARGET_CG)" ""
|
||||
TARGET_CG := $(TARGET).g3a
|
||||
endif
|
||||
|
||||
ELF_FX := build-fx/$(shell basename "$(TARGET_FX)" .g1a).elf
|
||||
BIN_FX := $(ELF_FX:.elf=.bin)
|
||||
|
||||
ELF_CG := build-cg/$(shell basename "$(TARGET_CG)" .g3a).elf
|
||||
BIN_CG := $(ELF_CG:.elf=.bin)
|
||||
|
||||
# Source files
|
||||
src := $(wildcard src/*.[csS] \
|
||||
src/*/*.[csS] \
|
||||
src/*/*/*.[csS] \
|
||||
src/*/*/*/*.[csS])
|
||||
assets-fx := $(wildcard assets-fx/*/*)
|
||||
assets-cg := $(wildcard assets-cg/*/*)
|
||||
|
||||
# Object files
|
||||
obj-fx := $(src:%=build-fx/%.o) \
|
||||
$(assets-fx:assets-fx/%=build-fx/assets/%.o)
|
||||
obj-cg := $(src:%=build-cg/%.o) \
|
||||
$(assets-cg:assets-cg/%=build-cg/assets/%.o)
|
||||
|
||||
# Additional dependencies
|
||||
deps-fx := $(ICON_FX)
|
||||
deps-cg := $(ICON_CG_UNS) $(ICON_CG_SEL)
|
||||
|
||||
# All targets
|
||||
all :=
|
||||
ifneq "$(wildcard build-fx)" ""
|
||||
all += all-fx
|
||||
endif
|
||||
ifneq "$(wildcard build-cg)" ""
|
||||
all += all-cg
|
||||
endif
|
||||
|
||||
#
|
||||
# Build rules
|
||||
#
|
||||
|
||||
all: $(all)
|
||||
|
||||
all-fx: $(TARGET_FX)
|
||||
all-cg: $(TARGET_CG)
|
||||
|
||||
$(TARGET_FX): $(obj-fx) $(deps-fx)
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -o $(ELF_FX) $(obj-fx) $(CFLAGSFX) $(LDFLAGSFX)
|
||||
$(TOOLCHAIN_FX)-objcopy -O binary $(BINFLAGS) $(ELF_FX) $(BIN_FX)
|
||||
fxg1a $(BIN_FX) -o $@ $(G1AF)
|
||||
|
||||
$(TARGET_CG): $(obj-cg) $(deps-cg)
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -o $(ELF_CG) $(obj-cg) $(CFLAGSCG) $(LDFLAGSCG)
|
||||
$(TOOLCHAIN_CG)-objcopy -O binary $(BINFLAGS) $(ELF_CG) $(BIN_CG)
|
||||
mkg3a $(G3AF) $(BIN_CG) $@
|
||||
|
||||
# C sources
|
||||
build-fx/%.c.o: %.c
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(CFLAGSFX) $(depflags)
|
||||
build-cg/%.c.o: %.c
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(CFLAGSCG) $(depflags)
|
||||
|
||||
# Assembler sources
|
||||
build-fx/%.s.o: %.s
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@
|
||||
build-cg/%.s.o: %.s
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@
|
||||
|
||||
# Preprocessed assembler sources
|
||||
build-fx/%.S.o: %.S
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_FX)-gcc -c $< -o $@ $(INCLUDE_FX)
|
||||
build-cg/%.S.o: %.S
|
||||
@ mkdir -p $(dir $@)
|
||||
$(TOOLCHAIN_CG)-gcc -c $< -o $@ $(INCLUDE_CG)
|
||||
|
||||
# Images
|
||||
build-fx/assets/img/%.o: assets-fx/img/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv --bopti-image $< -o $@ $(FXCONVFX) name:img_$(basename $*) $(IMG.$*)
|
||||
build-cg/assets/img/%.o: assets-cg/img/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv --bopti-image $< -o $@ $(FXCONVCG) name:img_$(basename $*) $(IMG.$*)
|
||||
|
||||
# Fonts
|
||||
build-fx/assets/fonts/%.o: assets-fx/fonts/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -f $< -o $@ $(FXCONVFX) name:font_$(basename $*) $(FONT.$*)
|
||||
build-cg/assets/fonts/%.o: assets-cg/fonts/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -f $< -o $@ $(FXCONVCG) name:font_$(basename $*) $(FONT.$*)
|
||||
|
||||
# Binaries
|
||||
build-fx/assets/bin/%.o: assets-fx/bin/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -b $< -o $@ $(FXCONVFX) name:bin_$(basename $*) $(BIN.$*)
|
||||
build-cg/assets/bin/%.o: assets-cg/bin/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv -b $< -o $@ $(FXCONVCG) name:bin_$(basename $*) $(BIN.$*)
|
||||
|
||||
# Custom conversions
|
||||
build-fx/assets/%.o: assets-fx/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv --custom $< -o $@ $(FXCONVFX) type:$(subst /,,$(dir $*)) name:$(subst /,_,$(basename $*))
|
||||
build-cg/assets/%.o: assets-cg/%
|
||||
@ mkdir -p $(dir $@)
|
||||
fxconv --custom $< -o $@ $(FXCONVCG) type:$(subst /,,$(dir $*)) name:$(subst /,_,$(basename $*))
|
||||
|
||||
#
|
||||
# Cleaning and utilities
|
||||
#
|
||||
|
||||
# Dependency information
|
||||
-include $(shell find build* -name *.d 2> /dev/null)
|
||||
build-fx/%.d: ;
|
||||
build-cg/%.d: ;
|
||||
.PRECIOUS: build-fx build-cg build-fx/%.d build-cg/%.d %/
|
||||
|
||||
clean-fx:
|
||||
@ rm -rf build-fx/
|
||||
clean-cg:
|
||||
@ rm -rf build-cg/
|
||||
|
||||
distclean-fx: clean-fx
|
||||
@ rm -f $(TARGET_FX)
|
||||
distclean-cg: clean-cg
|
||||
@ rm -f $(TARGET_CG)
|
||||
|
||||
clean: clean-fx clean-cg
|
||||
|
||||
distclean: distclean-fx distclean-cg
|
||||
|
||||
install-fx: $(TARGET_FX)
|
||||
p7 send -f $<
|
||||
install-cg: $(TARGET_CG)
|
||||
@ while [[ ! -h /dev/Prizm1 ]]; do sleep 0.25; done
|
||||
@ while ! mount /dev/Prizm1; do sleep 0.25; done
|
||||
@ rm -f /mnt/prizm/$<
|
||||
@ cp $< /mnt/prizm
|
||||
@ umount /dev/Prizm1
|
||||
@- eject /dev/Prizm1
|
||||
|
||||
.PHONY: all all-fx all-cg clean distclean install-fx install-cg
|
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.3 KiB |
|
@ -0,0 +1,10 @@
|
|||
#ifndef __FXBOOT_PARSER_H__
|
||||
# define __FXBOOT_PARSER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern int parser_strtotab(int *argc, char ***argv, char const *str);
|
||||
extern void parser_strtotab_quit(int *argc, char ***argv);
|
||||
|
||||
#endif /*__FXBOOT_PARSER_H__*/
|
|
@ -0,0 +1,79 @@
|
|||
#ifndef __FXBOOT_TERMINAL_H__
|
||||
# define __FXBOOT_TERMINAL_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TERM_PRIVATE_WATERMARK (0xdeadbeef)
|
||||
#define TERM_RDBUFFER_NBLINE (32)
|
||||
|
||||
/* */
|
||||
#ifdef FXCG50
|
||||
#define FWIDTH 8
|
||||
#define FHEIGHT 9
|
||||
#endif
|
||||
#ifdef FX9860G
|
||||
#define FWIDTH 5
|
||||
#define FHEIGHT 7
|
||||
#endif
|
||||
|
||||
/* define offset type */
|
||||
typedef unsigned int off_t;
|
||||
|
||||
struct terminal {
|
||||
/* windows information */
|
||||
struct {
|
||||
unsigned short ws_col;
|
||||
unsigned short ws_row;
|
||||
unsigned short ws_xpixel;
|
||||
unsigned short ws_ypixel;
|
||||
unsigned short ft_xpixel;
|
||||
unsigned short ft_ypixel;
|
||||
} winsize;
|
||||
|
||||
/* cursor information */
|
||||
struct {
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
} cursor;
|
||||
|
||||
/* buffer information */
|
||||
struct {
|
||||
uint8_t *data;
|
||||
off_t cursor;
|
||||
size_t size;
|
||||
} buffer;
|
||||
|
||||
/* private information */
|
||||
struct {
|
||||
struct {
|
||||
int id;
|
||||
} timer;
|
||||
uint32_t watermark;
|
||||
struct {
|
||||
int fg;
|
||||
int bg;
|
||||
} color;
|
||||
} private;
|
||||
};
|
||||
|
||||
/* define the terminal */
|
||||
extern struct terminal terminal;
|
||||
|
||||
//---
|
||||
// User interface
|
||||
//---
|
||||
extern int terminal_open(void);
|
||||
extern int terminal_write(const char *format, ...);
|
||||
extern int terminal_read(void *buffer, size_t nb);
|
||||
extern int terminal_close(void);
|
||||
|
||||
//---
|
||||
// Internal interface
|
||||
//---
|
||||
extern void terminal_clear(void);
|
||||
extern int terminal_cursor_handler(void);
|
||||
extern void terminal_buffer_display(void);
|
||||
extern void terminal_buffer_insert(char *buffer, size_t nb);
|
||||
|
||||
#endif /*__FXBOOT_TERMINAL_H__*/
|
|
@ -0,0 +1,88 @@
|
|||
#---
|
||||
# fxSDK project configuration file for fxBoot
|
||||
#---
|
||||
|
||||
# Project name, should be at most 8 bytes long.
|
||||
# (You can also specify NAME_G1A or NAME_G3A to override individually.)
|
||||
NAME := fxBoot
|
||||
|
||||
# Internal name, should be '@' followed by at most 7 uppercase letters.
|
||||
# WARNING: If this convention is not followed, the add-in might not appear in
|
||||
# the main menu of the calculator!
|
||||
INTERNAL := @FXBOOT
|
||||
|
||||
# Output file name. The default is to take <NAME>, replace spaces with dashes,
|
||||
# and add .g1a (or .g3a). You can specify a different folder if you want.
|
||||
TARGET_FX :=
|
||||
TARGET_CG :=
|
||||
|
||||
# fx-9860G icon location
|
||||
ICON_FX = assets-fx/icon-fx.png
|
||||
# fx-CG 50 icon locations
|
||||
ICON_CG_UNS = assets-cg/icon-cg-uns.png
|
||||
ICON_CG_SEL = assets-cg/icon-cg-sel.png
|
||||
|
||||
#---
|
||||
# Toolchain selection
|
||||
#---
|
||||
|
||||
# Toolchain for fx9860g. Please see also CFLAGS_FX below.
|
||||
TOOLCHAIN_FX := sh-elf
|
||||
|
||||
# Toolchain for fxcg50. Please see also CFLAGS_CG below.
|
||||
TOOLCHAIN_CG := sh-elf
|
||||
|
||||
#---
|
||||
# Compiler flags
|
||||
#---
|
||||
|
||||
# Base compiler flags for the fxSDK, you usually want to keep these.
|
||||
CFLAGS := -mb -ffreestanding -nostdlib -fstrict-volatile-bitfields
|
||||
|
||||
# Platform-specific compiler flags.
|
||||
# <> If you are using sh3eb-elf, use -m3. (You can do this on both FX and CG.)
|
||||
# <> If you are using sh4eb-elf, use -m4-nofpu. (Not ideal on FX but works.)
|
||||
# <> If you are using sh4eb-nofpu-elf, then your compiler will likely use the
|
||||
# FPU and cause problems on the calculator. Consider another configuration.
|
||||
# <> If you are using an sh-elf with several targets, specify whichever you
|
||||
# support. I recommend -m3 on FX and -m4-nofpu on CG.
|
||||
# Please see also TOOLCHAIN_FX and TOOLCHAIN_CG above.
|
||||
CFLAGS_FX := -D FX9860G -m3
|
||||
CFLAGS_CG := -D FXCG50 -m4-nofpu
|
||||
|
||||
# Additional compiler flags, change to your own taste!
|
||||
CFLAGS += -Wall -Wextra -Wno-missing-field-initializers -Os
|
||||
|
||||
# Include paths. Add one -I option for each folder from which you want to
|
||||
# be able to include files with #include<>. The Makefile provides a variable
|
||||
# GCC_INCLUDE_FX/GCC_INCLUDE_CG that represents the default include folder,
|
||||
# which is useful for some libraries such as OpenLibm.
|
||||
INCLUDE_FX = -I include
|
||||
INCLUDE_CG = -I include
|
||||
|
||||
# Libraries. Add one -l option for each library you are using, and also
|
||||
# suitable -L options if you have library files in custom folders. To use
|
||||
# fxlib, add libfx.a to the project directory and use "-L . -lfx".
|
||||
LIBS_FX :=
|
||||
LIBS_CG :=
|
||||
|
||||
# Base linker flags for the fxSDK, you usually want to keep these.
|
||||
LDFLAGS_FX := -T fx9860g.ld -lgint-fx $(LIBS_FX) -lgint-fx -lgcc
|
||||
LDFLAGS_CG := -T fxcg50.ld -lgint-cg $(LIBS_CG) -lgint-cg -lgcc
|
||||
|
||||
# Additional linker flags, if you need any.
|
||||
LDFLAGS :=
|
||||
|
||||
# Additional platform-specific linker flags.
|
||||
LDFLAGS_FX += -Wl,-Map=build-fx/map
|
||||
LDFLAGS_CG += -Wl,-Map=build-cg/map
|
||||
|
||||
#---
|
||||
# File conversion parameters
|
||||
#---
|
||||
|
||||
# Here you can add fxconv options for each converted file, individually.
|
||||
# The syntax is "<type>.<file>". For example, to specify the parameters for a
|
||||
# font named "hexa.png", you might write:
|
||||
#
|
||||
# FONT.hexa.png = charset:print grid.size:3x5 grid.padding:1
|
|
@ -0,0 +1,66 @@
|
|||
#include "fxBoot/terminal.h"
|
||||
#include "fxBoot/parser.h"
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
/* internal builtin list */
|
||||
struct {
|
||||
const char *name;
|
||||
int (*f)(int argc, char **argv);
|
||||
} cmd_list[] = {
|
||||
{.name = "ls", NULL},
|
||||
{.name = NULL, NULL}
|
||||
};
|
||||
|
||||
/* try to find the appropriate command */
|
||||
static int (*check_cmd(char *cmd))(int, char**)
|
||||
{
|
||||
for (int i = 0; cmd_list[i].name != NULL; ++i) {
|
||||
if (strcmp(cmd, cmd_list[i].name) != 0)
|
||||
continue;
|
||||
if (cmd_list[i].f == NULL)
|
||||
terminal_write("command exist but not implemented\n");
|
||||
return (cmd_list[i].f);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int (*builtin)(int, char**);
|
||||
const char *usrline;
|
||||
char buff[128];
|
||||
char **argv;
|
||||
int argc;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
terminal_open();
|
||||
terminal_write("Welcome to fxBoot!\n");
|
||||
while (1) {
|
||||
/* get user command */
|
||||
usrline = "/>";
|
||||
if (ret != 0) {
|
||||
usrline = "/[%d]>";
|
||||
}
|
||||
terminal_write(usrline, ret);
|
||||
if (terminal_read(buff, 128) <= 1)
|
||||
continue;
|
||||
|
||||
/* parse and try to find the command */
|
||||
if (parser_strtotab(&argc, &argv, buff) != 0) {
|
||||
terminal_write("error when processing \"%s\"", buff);
|
||||
}
|
||||
builtin = check_cmd(argv[0]);
|
||||
if (builtin == NULL) {
|
||||
terminal_write("command \"%s\" not found...\n", argv[0]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* execute the command and free'd allocated memories */
|
||||
ret = builtin(argc, argv);
|
||||
parser_strtotab_quit(&argc, &argv);
|
||||
}
|
||||
return (1);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
//---
|
||||
// fxBoot:parser - Parser used to generate ARGC and ARGV
|
||||
//---
|
||||
#include "fxBoot/parser.h"
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/std/string.h>
|
||||
|
||||
/* define external symbols */
|
||||
extern int parser_strtotab(int *argc, char ***argv, char const *str);
|
||||
extern void parser_strtotab_quit(int *argc, char ***argv);
|
||||
|
||||
/* parser_get_word(): Get the word at the current cursor location. */
|
||||
static int parser_get_word(char ***tab, size_t *tab_pos,
|
||||
char const *str, int *counter)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* skip until separator */
|
||||
i = -1;
|
||||
while (str[++i] != '\0'
|
||||
&& str[i] != '\n'
|
||||
&& str[i] != ' '
|
||||
&& str[i] != '\t');
|
||||
|
||||
/* dump the word of needed */
|
||||
if (*tab != NULL) {
|
||||
(*tab)[*tab_pos] = (char*)calloc(i + 1, 1);
|
||||
if ((*tab)[*tab_pos] == NULL)
|
||||
return (-1);
|
||||
memset((*tab)[*tab_pos], 0, i + 1);
|
||||
strncpy((*tab)[(*tab_pos)++], str, i);
|
||||
}
|
||||
|
||||
/* update the internal counter */
|
||||
(*counter)++;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/* parser_get_inibitor()
|
||||
|
||||
This function will get the content of an inhibitor (and check if the
|
||||
inhibitor characteres are alone or not). */
|
||||
static int parser_get_inibitor(char ***tab, size_t *tab_pos,
|
||||
char const *str, int *counter)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* get the inibitor end */
|
||||
i = 0;
|
||||
while (str[++i] != '\0' && str[i] != '\"');
|
||||
if (str[i] != '\"')
|
||||
return (0);
|
||||
|
||||
/* dump the word if needed */
|
||||
if (*tab != NULL) {
|
||||
(*tab)[*tab_pos] = (char*)calloc(i + 1, 1);
|
||||
if ((*tab)[*tab_pos] == NULL)
|
||||
return (-1);
|
||||
memset((*tab)[*tab_pos], 0, i + 1);
|
||||
strncpy((*tab)[(*tab_pos)++], str + 1, i - 1);
|
||||
}
|
||||
|
||||
/* update the internal counter */
|
||||
(*counter)++;
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
/* parser_setup_arg()
|
||||
|
||||
This function removes useless spaces, tabs and handle '\"' inhibitor.
|
||||
Return the number of word(s) stored in "str". */
|
||||
static int parser_entry(char ***tab, char const *str)
|
||||
{
|
||||
size_t tab_pos;
|
||||
int counter;
|
||||
int sz;
|
||||
|
||||
str--;
|
||||
sz = 0;
|
||||
counter = 0;
|
||||
tab_pos = 0;
|
||||
while (*(++str) != '\0' && *str != '\n' && sz >= 0) {
|
||||
if (*str == '\"') {
|
||||
sz = parser_get_inibitor(tab, &tab_pos, str, &counter);
|
||||
if (sz > 0) {
|
||||
str = &str[sz];
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (*str != ' ' && *str != '\t') {
|
||||
sz = parser_get_word(tab, &tab_pos, str, &counter) - 1;
|
||||
if (sz > 0)
|
||||
str = &str[sz];
|
||||
}
|
||||
}
|
||||
return (counter);
|
||||
}
|
||||
|
||||
/* parser_strtotab()
|
||||
Generate word table and indicated the number of word find in the string. */
|
||||
int parser_strtotab(int *argc, char ***argv, char const *str)
|
||||
{
|
||||
if (argc == NULL || argv == NULL || str == NULL)
|
||||
return (-1);
|
||||
|
||||
/* Get the number of word. */
|
||||
*argv = NULL;
|
||||
*argc = parser_entry(argv, str);
|
||||
if (*argc <= 0)
|
||||
return (-2);
|
||||
|
||||
*argv = (char **)calloc(sizeof(char *) * (*argc + 1), 1);
|
||||
if (*argv == NULL)
|
||||
return (-3);
|
||||
|
||||
/* Dump all word. */
|
||||
if (parser_entry(argv, str) != *argc) {
|
||||
parser_strtotab_quit(argc, argv);
|
||||
return (-4);
|
||||
}
|
||||
(*argv)[*argc] = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* parser_strtotab_quit(): Free all allocated memory generated by "strtotab()"*/
|
||||
void parser_strtotab_quit(int *argc, char ***argv)
|
||||
{
|
||||
if (argc == NULL || argv == NULL)
|
||||
return;
|
||||
if (*argv == NULL) {
|
||||
*argc = 0;
|
||||
return;
|
||||
}
|
||||
while (--(*argc) >= 0) {
|
||||
if ((*argv)[*argc] != NULL)
|
||||
free((*argv)[*argc]);
|
||||
}
|
||||
free(*argv);
|
||||
*argv = NULL;
|
||||
*argc = 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
//---
|
||||
// fxBoot:terminal:close - Close primitive for the terminal
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/timer.h>
|
||||
|
||||
/* internal symbols */
|
||||
extern struct terminal terminal;
|
||||
|
||||
/* terminal_close(): Uninitialize the terminal */
|
||||
int terminal_close(void)
|
||||
{
|
||||
if (terminal.private.watermark != TERM_PRIVATE_WATERMARK)
|
||||
return (-1);
|
||||
if (terminal.private.timer.id >= 0)
|
||||
timer_stop(terminal.private.timer.id);
|
||||
if (terminal.buffer.data != NULL)
|
||||
free(terminal.buffer.data);
|
||||
terminal.private.watermark = TERM_PRIVATE_WATERMARK;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//---
|
||||
// fxBoot:terminal:open - Open primitive for the terminal
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/std/stdlib.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/timer.h>
|
||||
|
||||
/* internal symbols */
|
||||
struct terminal terminal;
|
||||
|
||||
/* terminal_open(): Initialize and open the terminal */
|
||||
int terminal_open(void)
|
||||
{
|
||||
if (terminal.private.watermark == TERM_PRIVATE_WATERMARK)
|
||||
terminal_close();
|
||||
memset(&terminal, 0x00, sizeof(struct terminal));
|
||||
terminal.private.timer.id = -1;
|
||||
terminal.winsize.ws_xpixel = DWIDTH;
|
||||
terminal.winsize.ws_ypixel = DHEIGHT;
|
||||
terminal.winsize.ft_xpixel = FWIDTH + 1;
|
||||
terminal.winsize.ft_ypixel = FHEIGHT + 1;
|
||||
terminal.winsize.ws_col = DWIDTH / terminal.winsize.ft_xpixel;
|
||||
terminal.winsize.ws_row = DHEIGHT / terminal.winsize.ft_ypixel;
|
||||
terminal.buffer.size = terminal.winsize.ws_row
|
||||
* terminal.winsize.ws_col
|
||||
* TERM_RDBUFFER_NBLINE
|
||||
* sizeof(uint8_t);
|
||||
terminal.buffer.data = calloc(terminal.buffer.size, 1);
|
||||
if (terminal.buffer.data == NULL) {
|
||||
terminal_close();
|
||||
return (-1);
|
||||
}
|
||||
terminal.private.timer.id = timer_setup(TIMER_ANY, 250000,
|
||||
(void*)&terminal_cursor_handler);
|
||||
if (terminal.private.timer.id < 0) {
|
||||
terminal_close();
|
||||
return (-1);
|
||||
}
|
||||
terminal.private.color.bg = C_BLACK;
|
||||
terminal.private.color.fg = C_WHITE;
|
||||
terminal.private.watermark = TERM_PRIVATE_WATERMARK;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
//---
|
||||
// fxBoot:terminal:read - Read primitive for the terminal device
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/timer.h>
|
||||
|
||||
/* internal structure used to store many information */
|
||||
struct {
|
||||
struct {
|
||||
unsigned short x;
|
||||
unsigned short y;
|
||||
int visible;
|
||||
off_t saved;
|
||||
} cursor;
|
||||
struct {
|
||||
uint8_t alpha: 1;
|
||||
uint8_t shift: 1;
|
||||
uint8_t ctrl: 1;
|
||||
uint8_t exit: 1;
|
||||
uint8_t const: 4;
|
||||
} mode;
|
||||
struct {
|
||||
size_t max;
|
||||
size_t size;
|
||||
off_t cursor;
|
||||
char *data;
|
||||
} buffer;
|
||||
} term_rdinfo;
|
||||
|
||||
//---
|
||||
//
|
||||
//---
|
||||
void term_display_all(void)
|
||||
{
|
||||
/* stop the timer too avoid interrupt-loop */
|
||||
if (terminal.private.timer.id >= 0)
|
||||
timer_pause(terminal.private.timer.id);
|
||||
|
||||
/* mark special characte that the cursor is here */
|
||||
if (term_rdinfo.cursor.visible == 1)
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor] |= 0x80;
|
||||
|
||||
/* restore terminal context */
|
||||
terminal.cursor.x = term_rdinfo.cursor.x;
|
||||
terminal.cursor.y = term_rdinfo.cursor.y;
|
||||
terminal.buffer.cursor = term_rdinfo.cursor.saved;
|
||||
terminal_buffer_insert(term_rdinfo.buffer.data,
|
||||
term_rdinfo.buffer.size);
|
||||
|
||||
/* display management */
|
||||
dclear(terminal.private.color.bg);
|
||||
terminal_buffer_display();
|
||||
dupdate();
|
||||
|
||||
/* remove cursor mark */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor] &= ~0x80;
|
||||
|
||||
/* restart the timer */
|
||||
if (terminal.private.timer.id >= 0)
|
||||
timer_start(terminal.private.timer.id);
|
||||
}
|
||||
|
||||
//---
|
||||
// Callback function
|
||||
//---
|
||||
|
||||
int terminal_cursor_handler(void)
|
||||
{
|
||||
term_rdinfo.cursor.visible ^= 1;
|
||||
term_display_all();
|
||||
return (0);
|
||||
}
|
||||
|
||||
//---
|
||||
// buffer functions
|
||||
//---
|
||||
|
||||
/* term_buffer_remove(): Remove character based on current cursor position */
|
||||
static void term_buffer_remove(void)
|
||||
{
|
||||
/* check if this action is possible */
|
||||
if (term_rdinfo.buffer.cursor == 0)
|
||||
return;
|
||||
/* move data if needed */
|
||||
if (term_rdinfo.buffer.cursor < term_rdinfo.buffer.size - 1) {
|
||||
memcpy(
|
||||
&term_rdinfo.buffer.data[term_rdinfo.buffer.cursor - 1],
|
||||
&term_rdinfo.buffer.data[term_rdinfo.buffer.cursor],
|
||||
term_rdinfo.buffer.size - term_rdinfo.buffer.cursor
|
||||
);
|
||||
}
|
||||
/* force NULL-char and update cursor/size */
|
||||
term_rdinfo.buffer.cursor = term_rdinfo.buffer.cursor - 1;
|
||||
term_rdinfo.buffer.data[--term_rdinfo.buffer.size - 1] = '\0';
|
||||
}
|
||||
|
||||
/* term_buffer_insert() - Insert character based on current cursor position */
|
||||
static int term_buffer_insert(char n)
|
||||
{
|
||||
/* save space for the "\n\0" (EOL) */
|
||||
if (term_rdinfo.buffer.size + 1 >= term_rdinfo.buffer.max)
|
||||
return (-1);
|
||||
/* move data if needed */
|
||||
if (term_rdinfo.buffer.cursor < term_rdinfo.buffer.size - 1) {
|
||||
off_t i = term_rdinfo.buffer.size + 1;
|
||||
while (--i >= term_rdinfo.buffer.cursor) {
|
||||
term_rdinfo.buffer.data[i] =
|
||||
term_rdinfo.buffer.data[i - 1];
|
||||
}
|
||||
}
|
||||
/* insert the character and force NULL-char */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.cursor++] = n;
|
||||
term_rdinfo.buffer.data[++term_rdinfo.buffer.size] = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
//---
|
||||
// key handling
|
||||
//---
|
||||
|
||||
// TODO
|
||||
// - F_UP -> history
|
||||
// - F_DOWN -> history
|
||||
static int term_key_handle_special(key_event_t key_event)
|
||||
{
|
||||
switch (key_event.key) {
|
||||
case KEY_SHIFT: term_rdinfo.mode.shift ^= 1; return (1);
|
||||
case KEY_ALPHA: term_rdinfo.mode.alpha ^= 1; return (1);
|
||||
case KEY_OPTN: term_rdinfo.mode.ctrl ^= 1; return (1);
|
||||
case KEY_DOT: term_buffer_insert(' '); return (1);
|
||||
case KEY_DEL: term_buffer_remove(); return (1);
|
||||
case KEY_EXE:
|
||||
/* Add End Of Line character */
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.size - 1] = '\n';
|
||||
term_rdinfo.buffer.data[term_rdinfo.buffer.size] = '\0';
|
||||
|
||||
/* indicate that the EXE key has been pressed. */
|
||||
term_rdinfo.mode.exit = 1;
|
||||
return (1);
|
||||
case KEY_LEFT:
|
||||
if (term_rdinfo.buffer.cursor > 0)
|
||||
term_rdinfo.buffer.cursor -= 1;
|
||||
return (1);
|
||||
case KEY_RIGHT:
|
||||
if (term_rdinfo.buffer.cursor < term_rdinfo.buffer.size - 1)
|
||||
term_rdinfo.buffer.cursor += 1;
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/* term_buffer_update() - Update the internal buffer with the given key code */
|
||||
static int term_key_buffer_update(key_event_t key_event)
|
||||
{
|
||||
static const uint8_t keylist_alpha[] = {
|
||||
KEY_XOT, KEY_LOG, KEY_LN, KEY_SIN, KEY_COS, KEY_TAN,
|
||||
KEY_FRAC, KEY_FD, KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_ARROW,
|
||||
KEY_7, KEY_8, KEY_9,
|
||||
KEY_4, KEY_5, KEY_6, KEY_MUL, KEY_DIV,
|
||||
KEY_1, KEY_2, KEY_3, KEY_PLUS, KEY_MINUS,
|
||||
KEY_0, 0xff
|
||||
};
|
||||
static const uint8_t keylist_num[] = {
|
||||
KEY_0, KEY_1, KEY_2, KEY_3, KEY_4,
|
||||
KEY_5, KEY_6, KEY_7, KEY_8, KEY_9,
|
||||
KEY_PLUS, KEY_MINUS, KEY_MUL, KEY_DIV,
|
||||
KEY_LEFTP, KEY_RIGHTP, KEY_COMMA, KEY_POWER,
|
||||
KEY_DOT, KEY_FD, KEY_ARROW, 0xff
|
||||
};
|
||||
static const char keylist_num_char[] = "0123456789+-x/(),^.|_";
|
||||
const uint8_t *keycode_list;
|
||||
char character;
|
||||
int i;
|
||||
|
||||
/* Get the appropriate key list. */
|
||||
keycode_list = keylist_alpha;
|
||||
if (term_rdinfo.mode.shift == 1)
|
||||
keycode_list = keylist_num;
|
||||
|
||||
/* Try to find the pressed key. */
|
||||
i = -1;
|
||||
while (keycode_list[++i] != 0xff && keycode_list[i] != key_event.key);
|
||||
if (keycode_list[i] != key_event.key)
|
||||
return (0);
|
||||
|
||||
/* handle mode then update the buffer */
|
||||
if (term_rdinfo.mode.shift == 0) {
|
||||
character = 'a' + i;
|
||||
if (term_rdinfo.mode.alpha == 1)
|
||||
character = 'A' + i;;
|
||||
} else {
|
||||
character = keylist_num_char[i];
|
||||
}
|
||||
term_buffer_insert(character);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//---
|
||||
// primitive
|
||||
//---
|
||||
int terminal_read(void *buffer, size_t nb)
|
||||
{
|
||||
key_event_t key;
|
||||
|
||||
/* check obvious error */
|
||||
if (buffer == NULL || nb == 0)
|
||||
return (0);
|
||||
|
||||
/* initialize internal data */
|
||||
memset(&term_rdinfo, 0x00, sizeof(term_rdinfo));
|
||||
memset(buffer, 0x00, nb);
|
||||
|
||||
/* save terminal information */
|
||||
term_rdinfo.cursor.saved = terminal.buffer.cursor;
|
||||
term_rdinfo.cursor.x = terminal.cursor.x;
|
||||
term_rdinfo.cursor.y = terminal.cursor.y;
|
||||
term_rdinfo.buffer.data = buffer;
|
||||
term_rdinfo.buffer.size = 1;
|
||||
term_rdinfo.buffer.max = nb;
|
||||
|
||||
/* start cursor blink timer */
|
||||
if (terminal.private.timer.id >= 0)
|
||||
timer_start(terminal.private.timer.id);
|
||||
|
||||
/* keyboard handling */
|
||||
while (term_rdinfo.mode.exit == 0) {
|
||||
/* handle pressed keys */
|
||||
key = getkey_opt(GETKEY_REP_ALL | GETKEY_MENU, NULL);
|
||||
if (term_key_handle_special(key) == 0)
|
||||
term_key_buffer_update(key);
|
||||
|
||||
/* display */
|
||||
term_display_all();
|
||||
}
|
||||
|
||||
/* stop the timer */
|
||||
if (terminal.private.timer.id >= 0)
|
||||
timer_pause(terminal.private.timer.id);
|
||||
return (term_rdinfo.buffer.size);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
//---
|
||||
// fxBoot:terminal:util - usefull function for handle the terminal device
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
|
||||
//---
|
||||
// Update the internal buffer
|
||||
//---
|
||||
void terminal_buffer_insert(char *buffer, size_t nb)
|
||||
{
|
||||
size_t dump;
|
||||
void *start;
|
||||
|
||||
/* calculate the "real" number of byte to dump into the buffer */
|
||||
dump = nb;
|
||||
start = &buffer[0];
|
||||
if (dump > terminal.buffer.size) {
|
||||
dump -= terminal.buffer.size;
|
||||
start = &buffer[nb - dump];
|
||||
}
|
||||
|
||||
/* dump the buffer (be carful with the circular effect) */
|
||||
if (terminal.buffer.cursor + dump > terminal.buffer.size) {
|
||||
memcpy(
|
||||
&terminal.buffer.data[terminal.buffer.cursor],
|
||||
start,
|
||||
terminal.buffer.size - terminal.buffer.cursor
|
||||
);
|
||||
dump -= terminal.buffer.size - terminal.buffer.cursor;
|
||||
terminal.buffer.cursor = 0;
|
||||
}
|
||||
memcpy(&terminal.buffer.data[terminal.buffer.cursor], start, dump);
|
||||
terminal.buffer.cursor += dump;
|
||||
}
|
||||
|
||||
|
||||
//---
|
||||
// Display the internal buffer
|
||||
//---
|
||||
|
||||
/* terminal_vertical_update() - Update vertical cursor */
|
||||
static void terminal_vertical_update(void)
|
||||
{
|
||||
if (terminal.cursor.y + 1 < terminal.winsize.ws_col) {
|
||||
terminal.cursor.y = terminal.cursor.y + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* earlyterm_horizontal_update() - Update horizotal cursor */
|
||||
static int terminal_horizontal_update(void)
|
||||
{
|
||||
terminal.cursor.x = terminal.cursor.x + 1;
|
||||
if (terminal.cursor.x >= terminal.winsize.ws_col) {
|
||||
terminal_vertical_update();
|
||||
terminal.cursor.x = 0;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* line_discipline() - Check "special" char */
|
||||
static int terminal_line_discipline(char n)
|
||||
{
|
||||
int offset;
|
||||
|
||||
switch (n) {
|
||||
case '\0':
|
||||
return (1);
|
||||
case '\n':
|
||||
terminal.cursor.x = 0;
|
||||
terminal_vertical_update();
|
||||
return (1);
|
||||
case '\b':
|
||||
if (terminal.cursor.x > 0)
|
||||
terminal.cursor.x = terminal.cursor.x - 1;
|
||||
return (1);
|
||||
case '\v':
|
||||
terminal_vertical_update();
|
||||
return (1);
|
||||
case '\r':
|
||||
terminal.cursor.x = 0;
|
||||
return (1);
|
||||
case '\t':
|
||||
/* Check if we need a new line or not. */
|
||||
offset = terminal.cursor.x - ((terminal.cursor.x / 5) * 5);
|
||||
offset = 5 - offset;
|
||||
while (--offset >= 0)
|
||||
terminal_horizontal_update();
|
||||
return (1);
|
||||
default:
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
void terminal_buffer_display(void)
|
||||
{
|
||||
uint8_t *buffer;
|
||||
uint16_t tmp;
|
||||
int cursor;
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
|
||||
/* Due to potential special char, we sould find the "real" starting
|
||||
index for the internal buffer */
|
||||
terminal.cursor.x = 0;
|
||||
terminal.cursor.y = 0;
|
||||
i = terminal.buffer.cursor - 1;
|
||||
buffer = &terminal.buffer.data[0];
|
||||
while (1) {
|
||||
/* decrease the cursor and avoid circular effect */
|
||||
if (--i < 0)
|
||||
i = terminal.buffer.size - 1;
|
||||
|
||||
/* check loop condition */
|
||||
if (i == (int)terminal.buffer.cursor)
|
||||
break;
|
||||
|
||||
/* check EOL */
|
||||
if (buffer[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
/* handle the character (only to force update cursors) */
|
||||
if (terminal_line_discipline(buffer[i] & 0x7f) == 0)
|
||||
terminal_horizontal_update();
|
||||
if (terminal.cursor.y >= terminal.winsize.ws_row)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Display character per character because we need to check special
|
||||
behaviour (like cariege return, line feed, ...) */
|
||||
terminal.cursor.x = 0;
|
||||
terminal.cursor.y = 0;
|
||||
while (1) {
|
||||
/* update the index */
|
||||
if (++i >= (int)terminal.buffer.size)
|
||||
i = 0;
|
||||
if (i == (int)terminal.buffer.cursor)
|
||||
break;
|
||||
|
||||
/* get the cursor and remove the potential cursor marker */
|
||||
cursor = ((buffer[i] & 0x80) != 0);
|
||||
buffer[i] &= 0x7f;
|
||||
|
||||
/* display part (character + cursor if needed) */
|
||||
x = terminal.cursor.x * terminal.winsize.ft_xpixel;
|
||||
y = terminal.cursor.y * terminal.winsize.ft_ypixel;
|
||||
if (terminal_line_discipline(buffer[i]) == 0) {
|
||||
tmp = buffer[i] << 8;
|
||||
dtext(x, y, terminal.private.color.fg, (void*)&tmp);
|
||||
terminal_horizontal_update();
|
||||
}
|
||||
if (cursor != 0) {
|
||||
dline(x,
|
||||
y + terminal.winsize.ft_ypixel,
|
||||
x + terminal.winsize.ft_xpixel - 2,
|
||||
y + terminal.winsize.ft_ypixel,
|
||||
terminal.private.color.fg);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//---
|
||||
// fxBoot:terminal:write - Write primitive for terminal device
|
||||
//---
|
||||
#include "fxBoot/terminal.h"
|
||||
#include <gint/std/stdio.h>
|
||||
#include <gint/std/string.h>
|
||||
#include <gint/display.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* terminal_write() - printf wrapper for the terminal device */
|
||||
int terminal_write(const char *format, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
va_list ap;
|
||||
int nb;
|
||||
|
||||
/* process the format */
|
||||
va_start(ap, format);
|
||||
nb = vsnprintf(buffer, 1024, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* update the internal buffer */
|
||||
terminal_buffer_insert(buffer, nb);
|
||||
|
||||
/* display the internal buffer */
|
||||
dclear(terminal.private.color.bg);
|
||||
terminal_buffer_display();
|
||||
dupdate();
|
||||
return (nb);
|
||||
}
|
Loading…
Reference in New Issue