Initial commit
This commit is contained in:
commit
1cfa9d733b
|
@ -0,0 +1,4 @@
|
|||
/Makefile.cfg
|
||||
/obj
|
||||
/libg1m.so*
|
||||
/man
|
|
@ -0,0 +1,206 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include variables and message subsystem #
|
||||
#******************************************************************************#
|
||||
include Makefile.vars
|
||||
include Makefile.msg
|
||||
|
||||
#******************************************************************************#
|
||||
# General targets #
|
||||
#******************************************************************************#
|
||||
# Build everything.
|
||||
all: all-lib all-doc
|
||||
|
||||
# Mostly clean everything. (remove everything but the end results)
|
||||
mostlyclean: mostlyclean-lib mostlyclean-doc
|
||||
mclean: mostlyclean
|
||||
|
||||
# Clean everything.
|
||||
clean: clean-lib clean-doc
|
||||
fclean: clean
|
||||
|
||||
# Remake everything. (clean and build)
|
||||
re: clean all
|
||||
|
||||
# Install everything.
|
||||
install: install-lib $(if $(INSTALL_MANPAGES),install-doc)
|
||||
|
||||
# Uninstall everything. (EXPERIMENTAL)
|
||||
uninstall: uninstall-lib uninstall-doc
|
||||
|
||||
# Reinstall everything. (EXPERIMENTAL)
|
||||
reinstall: uninstall install
|
||||
|
||||
.PHONY: all mostlyclean mclean clean fclean re install uninstall reinstall
|
||||
#******************************************************************************#
|
||||
# Configuration (version) checking dependencies #
|
||||
#******************************************************************************#
|
||||
# Define the dependencies.
|
||||
CHECKCFG := $(if $(shell test -f Makefile.cfg || echo y),check-config, \
|
||||
$(if $(shell [ "$(VERSION)" = "$(CONFIG_VERSION)" ] || echo y), \
|
||||
check-config-version))
|
||||
|
||||
# Define the rules.
|
||||
check-config:
|
||||
@echo -e "\033[1;31mNo configuration file found!"
|
||||
@echo -e "You should configure before re-running this target.\033[0m"
|
||||
@false
|
||||
check-config-version:
|
||||
@echo -e "\033[1;31mConfiguration version is incorrect!"
|
||||
@echo -e "You should re-configure before re-running this target.\033[0m"
|
||||
@false
|
||||
|
||||
.PHONY: check-config check-config-version
|
||||
#******************************************************************************#
|
||||
# Information getting from the Makefile variables #
|
||||
#******************************************************************************#
|
||||
# Get the project name.
|
||||
getname:
|
||||
@echo lib$(NAME)
|
||||
|
||||
# Get the project author.
|
||||
getauthor:
|
||||
@echo $(AUTHOR)
|
||||
|
||||
# Get the project author email.
|
||||
getmail:
|
||||
@echo $(AUTHOR_MAIL)
|
||||
|
||||
# Get the project version.
|
||||
getversion:
|
||||
@echo $(VERSION)
|
||||
|
||||
.PHONY: getname getauthor getmail getversion
|
||||
#******************************************************************************#
|
||||
# Library-specific targets #
|
||||
#******************************************************************************#
|
||||
# Make the library.
|
||||
all-lib: $(CHECKCFG) lib$(NAME).so
|
||||
|
||||
# Make the objects directory.
|
||||
$(OBJDIR):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make an object out of a source file.
|
||||
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR)
|
||||
$(call bcmd,cc,$@,$(CC) -c -o $@ $< $(CFLAGS))
|
||||
|
||||
# Make the (shared) library.
|
||||
lib$(NAME).so: $(SRC:%=$(OBJDIR)/%.o)
|
||||
$(call bcmd,ld,$@,$(LD) -o $@ $^ $(LDFLAGS))
|
||||
|
||||
# Remove the objects directory.
|
||||
mostlyclean-lib:
|
||||
$(call rmsg,Removing the objects directory.)
|
||||
$(call rcmd,$(OBJDIR),$(RM) -r $(OBJDIR))
|
||||
mclean-lib: mostlyclean-lib
|
||||
|
||||
# Clean and remove the built library
|
||||
clean-lib: mclean-lib
|
||||
$(call rmsg,Removing the built library.)
|
||||
$(call rcmd,lib$(NAME).so,$(RM) lib$(NAME).so)
|
||||
|
||||
# Remake the library
|
||||
re-lib: clean-lib all-lib
|
||||
|
||||
# Install the library and development files.
|
||||
install-lib: $(CHECKCFG) lib$(NAME).so
|
||||
$(call imsg,Installing the library.)
|
||||
$(call qcmd,$(INST) -m 755 -d "$(ILIBDIR)")
|
||||
$(call icmd,lib$(NAME).so.$(VERSION_MAJOR),\
|
||||
$(INST) -m 755 lib$(NAME).so "$(ILIBDIR)/lib$(NAME).so.$(VERSION_MAJOR)")
|
||||
|
||||
$(if $(INSTALL_DEVEL),\
|
||||
$(call imsg,Linking lib$(NAME).so to lib$(NAME).so.$(VERSION_MAJOR).))
|
||||
$(if $(INSTALL_DEVEL),\
|
||||
$(call qcmd,$(LN) lib$(NAME).so.$(VERSION_MAJOR) \
|
||||
"$(ILIBDIR)/lib$(NAME).so"))
|
||||
|
||||
$(if $(INSTALL_DEVEL),\
|
||||
$(call imsg,Installing development files.))
|
||||
$(if $(INSTALL_DEVEL),\
|
||||
$(call qcmd,$(INST) -m 755 -d $(patsubst %,"$(IINCDIR)/%",\
|
||||
$(sort $(dir $(INCPUB))))))
|
||||
$(if $(INSTALL_DEVEL),\
|
||||
$(foreach i,$(INCPUB),$(call icmd,$(i).h,\
|
||||
$(INST) -m 644 $(INCDIR)/$(i).h "$(IINCDIR)/$(i).h"$(\n))))
|
||||
|
||||
# Uninstall the library and development files. (EXPERIMENTAL)
|
||||
uninstall-lib: $(CHECKCFG)
|
||||
$(call rmsg,Uninstalling the library.)
|
||||
$(call rcmd,lib$(NAME).a)
|
||||
$(call rcmd,lib$(NAME).so.*)
|
||||
$(call qcmd,$(RM) "$(ILIBDIR)/lib$(NAME).a" "$(ILIBDIR)/lib$(NAME).so"*)
|
||||
$(call rcmd,include/lib$(NAME).h)
|
||||
$(call rcmd,include/lib$(NAME))
|
||||
$(call qcmd,$(RM) "$(IINCDIR)/lib$(NAME).h")
|
||||
$(call qcmd,$(RM) -r "$(IINCDIR)/lib$(NAME)")
|
||||
|
||||
.PHONY: all-lib mostlyclean-lib mclean-lib clean-lib re-lib
|
||||
.PHONY: install-lib uninstall-lib
|
||||
#******************************************************************************#
|
||||
# Documentation-related #
|
||||
#******************************************************************************#
|
||||
# Make all manpages.
|
||||
all-doc: $(foreach s,$(MAN_SECTIONS), $(MAN_$(s):%=$(MANDIR)/man$(s)/%.$(s)))
|
||||
|
||||
# Make manpages directories.
|
||||
$(MAN_SECTIONS:%=$(MANDIR)/man%):
|
||||
$(call bcmd,mkdir,$@,$(MD) $@)
|
||||
|
||||
# Make a manpage.
|
||||
define make-manpage-rule
|
||||
$(MANDIR)/man$1/%.$1: $(DOCDIR)/%.$1.txt | $(MANDIR)/man$1
|
||||
$(call bcmd,a2x,$$<,$(A2X) -f manpage -D $$| $$< 2>/dev/null)
|
||||
endef
|
||||
$(foreach section, $(MAN_SECTIONS), \
|
||||
$(eval $(call make-manpage-rule,$(section))))
|
||||
|
||||
# Mostly clean (do nothing, really)
|
||||
mostlyclean-doc:
|
||||
mclean-doc: mostlyclean-doc
|
||||
|
||||
# Remove all built manpages.
|
||||
clean-doc:
|
||||
$(call rmsg,Removing manpages directory.)
|
||||
$(call rcmd,$(MANDIR),$(RM) -r $(MANDIR))
|
||||
|
||||
# Remake all manpages.
|
||||
# (I don't really know why some people would want to do that though)
|
||||
re-doc: clean-doc all-doc
|
||||
|
||||
# Install a manpages section.
|
||||
define make-installmansection-rule
|
||||
install-doc-$1: $(MAN_$1:%=$(MANDIR)/man$1/%.$1)
|
||||
$(call imsg,Installing manpages section $1.)
|
||||
$(call qcmd,$(INST) -m 755 -d "$(IMANDIR)/man$1")
|
||||
$(foreach i,$(MAN_$1),$(call icmd,man$1/$(i).$1))
|
||||
$(call qcmd,$(INST) -m 644 -t "$(IMANDIR)/man$1" \
|
||||
$(MAN_$1:%=$(MANDIR)/man$1/%.$1))
|
||||
$(call qcmd,$(GZIP) $(MAN_$1:%="$(IMANDIR)/man$1/%.$1"))
|
||||
endef
|
||||
$(foreach section, $(MAN_SECTIONS), \
|
||||
$(eval $(call make-installmansection-rule,$(section))))
|
||||
|
||||
# Install manpages.
|
||||
install-doc: $(CHECKCFG) $(MAN_SECTIONS:%=install-doc-%)
|
||||
|
||||
# Clean a manpages section.
|
||||
define make-uninstall-doc-rule
|
||||
uninstall-doc-$1:
|
||||
$(call rmsg,Uninstalling manpages section $1.)
|
||||
$(call rcmd,man$1/lib$(NAME).$1)
|
||||
$(call rcmd,man$1/$(NAME)_*.$1)
|
||||
$(call qcmd,$(RM) "$(IMANDIR)/man$1/lib$(NAME).$1"* \
|
||||
"$(IMANDIR)/man$1/$(NAME)_"*".$1"*)
|
||||
endef
|
||||
$(foreach sec,$(MAN_SECTIONS), \
|
||||
$(eval $(call make-uninstall-doc-rule,$(sec))))
|
||||
|
||||
# Uninstall manpages
|
||||
uninstall-doc: $(CHECKCFG) $(MAN_SECTIONS:%=uninstall-doc-%)
|
||||
|
||||
.PHONY: all-doc mostlyclean-doc mclean-doc clean-doc re-doc
|
||||
.PHONY: install-doc uninstall-doc
|
||||
.PHONY: $(foreach s,$(MAN_SECTIONS),install-doc-$(s) uninstall-doc-$(s))
|
||||
# End of file.
|
|
@ -0,0 +1,66 @@
|
|||
#!/usr/bin/make -f
|
||||
# The Makefile message subsystem.
|
||||
# For nice logs. 5 dollars per log only.
|
||||
#******************************************************************************#
|
||||
# Colors and misc #
|
||||
#******************************************************************************#
|
||||
# Used colors ANSI modifiers escape codes
|
||||
color_green := 32
|
||||
color_red := 31
|
||||
color_yellow := 33
|
||||
|
||||
# Newline - comes handy in some situations
|
||||
define \n
|
||||
|
||||
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# General messages #
|
||||
#******************************************************************************#
|
||||
# Command message - display basic info about the command, and run it.
|
||||
define cmd
|
||||
@$(if $(MAKE_FULL_LOG),,printf "\033[1;""$4""m>\033[0m \033[1m%s\033[0m %s\n" "$1" "$2";)
|
||||
$(if $(MAKE_FULL_LOG),,@)$3
|
||||
endef
|
||||
|
||||
# Quiet command - make it non-quiet if full log is enabled.
|
||||
define qcmd
|
||||
$(if $(MAKE_FULL_LOG),,@)$1
|
||||
endef
|
||||
|
||||
# Normal message - display it.
|
||||
define msg
|
||||
$(if $(MAKE_FULL_LOG),,@printf "\033[1;""$2""m>\033[0m \033[1m%s\033[0m\n" "$1")
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Commands #
|
||||
#******************************************************************************#
|
||||
# Build command
|
||||
define bcmd
|
||||
$(call cmd,$1,$2,$3,$(color_green))
|
||||
endef
|
||||
|
||||
# Remove command
|
||||
define rcmd
|
||||
$(call cmd,rm,$1,$2,$(color_red))
|
||||
endef
|
||||
|
||||
# Install command
|
||||
define icmd
|
||||
$(call cmd,install,$1,$2,$(color_yellow))
|
||||
endef
|
||||
|
||||
#******************************************************************************#
|
||||
# Messages #
|
||||
#******************************************************************************#
|
||||
# Remove message
|
||||
define rmsg
|
||||
$(call msg,$1,$(color_red))
|
||||
endef
|
||||
|
||||
# Install message
|
||||
define imsg
|
||||
$(call msg,$1,$(color_yellow))
|
||||
endef
|
|
@ -0,0 +1,118 @@
|
|||
#!/usr/bin/make -f
|
||||
#******************************************************************************#
|
||||
# Include configuration #
|
||||
#******************************************************************************#
|
||||
-include Makefile.cfg
|
||||
|
||||
#******************************************************************************#
|
||||
# Project main information #
|
||||
#******************************************************************************#
|
||||
# Project name
|
||||
NAME := g1m
|
||||
|
||||
# Author information
|
||||
AUTHOR := Thomas \"Cakeisalie5\" Touhey
|
||||
AUTHOR_MAIL := thomas@touhey.fr
|
||||
|
||||
# Project license
|
||||
LICENSE := GPLv2
|
||||
|
||||
# Project version
|
||||
VERSION_MAJOR := 0
|
||||
VERSION_MINOR := 1
|
||||
INDEV := yes
|
||||
VERSION := $(VERSION_MAJOR).$(VERSION_MINOR)$(if $(INDEV),-indev)
|
||||
|
||||
#******************************************************************************#
|
||||
# Project directories #
|
||||
#******************************************************************************#
|
||||
# Headers directory - where all the headers are.
|
||||
INCDIR := ./include
|
||||
|
||||
# Sources directory - where all the sources are.
|
||||
SRCDIR := ./src
|
||||
|
||||
# Objects directory - where the objects will be put.
|
||||
OBJDIR := ./obj
|
||||
|
||||
# Documentation directory - where the asciidoc sources for the manpages are.
|
||||
DOCDIR := ./doc
|
||||
|
||||
# Manpages directory - where the manpages will be put.
|
||||
MANDIR := ./man
|
||||
|
||||
#******************************************************************************#
|
||||
# Binary utilities #
|
||||
#******************************************************************************#
|
||||
# Compiler
|
||||
CC := gcc
|
||||
# - Check flags (warnings)
|
||||
CHKFLAGS := -Wall -Wextra -Wno-attributes
|
||||
# - For random manipulations (profiling, ...)
|
||||
CMOREFLAGS :=
|
||||
# - All C compiling flags
|
||||
CFLAGS := -I $(INCDIR) $(CHKFLAGS) -std=gnu11 -fPIC -O2 \
|
||||
-fstack-protector-strong -D LOGLEVEL="ll_$(LOG_LEVEL)" \
|
||||
-D_GNU_SOURCE -D_USE_GNU \
|
||||
-D AUTHOR="$(AUTHOR)" -D AUTHOR_MAIL="$(AUTHOR_MAIL)" \
|
||||
-D LICENSE="$(LICENSE)" -D VERSION="$(VERSION)" \
|
||||
$(CMOREFLAGS)
|
||||
|
||||
# Linker
|
||||
LD := gcc
|
||||
# - Linker flags
|
||||
LDFLAGS := -shared -lusb-1.0 \
|
||||
-e __lib$(NAME)_version \
|
||||
-Wl,-soname,lib$(NAME).so.$(VERSION_MAJOR) \
|
||||
-Wl,-z,relro -Wl,-z,combreloc -Wl,-z,defs
|
||||
|
||||
# Directory maker
|
||||
MD := mkdir -p
|
||||
# Symbolic link maker
|
||||
LN := ln -sf
|
||||
# File remover
|
||||
RM := rm -f
|
||||
# Documentation creator
|
||||
A2X := a2x
|
||||
# Installer
|
||||
INST := install
|
||||
# GZipper
|
||||
GZIP := gzip -f
|
||||
|
||||
#******************************************************************************#
|
||||
# Look for sources #
|
||||
#******************************************************************************#
|
||||
SRC := $(basename $(shell find $(SRCDIR) -name "*.c" -printf "%P\n"))
|
||||
|
||||
#******************************************************************************#
|
||||
# Look for public headers (not internals.h or internals/**/*.h #
|
||||
#******************************************************************************#
|
||||
INCPUB := $(basename $(shell find $(INCDIR) \
|
||||
-name "*.h" -and -not -path "*internals*" -printf "%P\n" | sort))
|
||||
|
||||
#******************************************************************************#
|
||||
# Look for manpages #
|
||||
#******************************************************************************#
|
||||
# Get the manpages sections and contents
|
||||
MAN_SECTIONS :=
|
||||
define check-man
|
||||
MAN_SECTIONS += $1
|
||||
MAN_$1 += $2
|
||||
endef
|
||||
$(foreach doc, $(basename $(shell find $(DOCDIR) \
|
||||
-maxdepth 1 -mindepth 1 -printf "%P\n" -type f -or -type l -name "*.*.txt")), \
|
||||
$(eval $(call check-man,$(patsubst .%,%,$(suffix $(doc))),$(basename $(doc)))))
|
||||
|
||||
# Remove duplicate sections.
|
||||
MAN_SECTIONS := $(sort $(MAN_SECTIONS))
|
||||
|
||||
#******************************************************************************#
|
||||
# Check for DESTDIR (add as prefix to installation root) #
|
||||
#******************************************************************************#
|
||||
define add-dest-dir
|
||||
$1 = $(DESTDIR)$($1)
|
||||
endef
|
||||
$(if $(DESTDIR), $(foreach idir,ILIBDIR IINCDIR IMANDIR UDEVDIR, \
|
||||
$(eval $(call add-dest-dir,$(idir)))))
|
||||
|
||||
# END OF FILE
|
|
@ -0,0 +1,140 @@
|
|||
#!/bin/sh
|
||||
# Defaults
|
||||
name="$(make -sC $(dirname $0) getname)"
|
||||
author="$(make -sC $(dirname $0) getauthor)"
|
||||
complete_author="$author <$(make -sC $(dirname $0) getmail)>"
|
||||
version="$(make -sC $(dirname $0) getversion)"
|
||||
# - Platform
|
||||
platform="$(gcc --print-multiarch)"
|
||||
platform="$([ "$platform" ] && echo "/$platform")"
|
||||
# - Basic things
|
||||
make_full_log=
|
||||
loglevel=none # none, info, warn, error, fatal
|
||||
root=''
|
||||
# - main things
|
||||
prefix='${root}/usr'
|
||||
bindir='${prefix}/bin'
|
||||
libdir='${prefix}/lib'"$platform"
|
||||
includedir='${prefix}/include'"$platform"
|
||||
mandir='${prefix}/share/man'
|
||||
# - misc
|
||||
install_manpages=yes
|
||||
install_devel=yes
|
||||
|
||||
# Help
|
||||
usage() {
|
||||
cat <<EOF
|
||||
\`configure\` configures ${name} to adapt to systems that aren't mine.
|
||||
Usage: $0 [OPTION]
|
||||
|
||||
Defaults for the options are specified in brackets.
|
||||
|
||||
General options:
|
||||
--help display this help and exit
|
||||
--version display version information and quit
|
||||
--make-full-log display full commands while making
|
||||
|
||||
Build options:
|
||||
--loglevel library log level [$loglevel]
|
||||
|
||||
Installation options:
|
||||
--noinstall-manpages should not install manpages
|
||||
--noinstall-devel should not install developement files
|
||||
|
||||
Installation directories:
|
||||
--root=ROOT installation root [$root]
|
||||
--prefix=PREFIX main installation prefix [$prefix]
|
||||
|
||||
Fine tuning of the installation directories:
|
||||
--bindir=DIR executables [$bindir]
|
||||
--libdir=DIR library files of the linker [$libdir]
|
||||
--includedir=DIR include files for the compiler [$includedir]
|
||||
--mandir=DIR man root [$mandir]
|
||||
|
||||
Report bugs to ${complete_author}.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Version
|
||||
version() {
|
||||
cat <<EOF
|
||||
${name} configure script v${version}
|
||||
Hand-written by ${author}.
|
||||
|
||||
This configure script is free software.
|
||||
There is NO warranty; not even for MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE.
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Args parsing
|
||||
# - check for help and version
|
||||
put_version=
|
||||
put_help=
|
||||
for arg ; do case "$arg" in
|
||||
--help|-h) put_help=1 ;;
|
||||
--version|-v) put_version=1 ;;
|
||||
esac; done
|
||||
if [ $put_version ]; then version; fi
|
||||
if [ $put_help ]; then usage; fi
|
||||
|
||||
# - get options
|
||||
for arg ; do case "$arg" in
|
||||
--make-full-log) make_full_log=yes ;;
|
||||
--loglevel=*)
|
||||
level="${arg#*=}"
|
||||
# check if is in array
|
||||
if ! [ $level = "info" ] && ! [ $level = "warn" ] \
|
||||
&& ! [ $level = "error" ] && ! [ $level = "fatal" ] \
|
||||
&& ! [ $level = "none" ]; then
|
||||
echo \
|
||||
"$0 : --loglevel: expected one of [info, warn, error, fatal, none], \
|
||||
got '$level'"
|
||||
continue
|
||||
fi
|
||||
# then set
|
||||
loglevel=$level ;;
|
||||
--noinstall-manpages) install_manpages= ;;
|
||||
--noinstall-devel) install_devel= ;;
|
||||
--root=*) root="${arg#*=}" ;;
|
||||
--prefix=*) prefix="${arg#*=}" ;;
|
||||
--bindir=*) bindir="${arg#*=}" ;;
|
||||
--libdir=*) libdir="${arg#*=}" ;;
|
||||
--includedir=*) includedir="${arg#*=}" ;;
|
||||
--mandir=*) mandir="${arg#*=}" ;;
|
||||
*) echo "$arg: didn't read" ;;
|
||||
esac; done
|
||||
|
||||
# Evaluate
|
||||
for var in prefix sysconfdir bindir libdir includedir mandir udevrulesdir; do
|
||||
eval $var'='$(eval 'echo $'$var)
|
||||
done
|
||||
|
||||
# Create Makefile configuration
|
||||
exec 3>&1 1>"$(dirname $0)/Makefile.cfg"
|
||||
|
||||
cat <<EOF
|
||||
#!/usr/bin/make -f
|
||||
# Makefile configuration generated by ./configure
|
||||
# - Configuration version
|
||||
CONFIG_VERSION = $version
|
||||
MAKE_FULL_LOG = $make_full_log
|
||||
# - Build options
|
||||
LOG_LEVEL = $loglevel
|
||||
# - Install options
|
||||
INSTALL_MANPAGES = $install_manpages
|
||||
INSTALL_DEVEL = $install_devel
|
||||
# - Install prefix and directories
|
||||
IBINDIR = $bindir
|
||||
ILIBDIR = $libdir
|
||||
IINCDIR = $includedir
|
||||
IMANDIR = $mandir
|
||||
EOF
|
||||
|
||||
exec 1>&3 3>&-
|
||||
chmod +x "$(dirname $0)/Makefile.cfg"
|
||||
|
||||
# We're done
|
||||
echo "Configuration loaded, you can make now."
|
|
@ -0,0 +1,25 @@
|
|||
LIBG1M(3)
|
||||
=========
|
||||
Thomas "Cakeisalie5" Touhey
|
||||
:Email: thomas@touhey.fr
|
||||
:man source: libg1m
|
||||
:man manual: libg1m manual
|
||||
|
||||
NAME
|
||||
----
|
||||
libg1m - manipulation library for casio's standard format
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
[source,c]
|
||||
----
|
||||
#include <libg1m.h>
|
||||
----
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
libg1m enables reading (parsing) and writing of g** files : g1m, g1a.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
*g1m_open(3)*
|
|
@ -0,0 +1,59 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* libg1m.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/03 23:23:56 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef LIBG1M_H
|
||||
# define LIBG1M_H
|
||||
# include <stdio.h>
|
||||
# include <libg1m/compiler.h>
|
||||
# ifdef __cplusplus
|
||||
extern "C" {
|
||||
# endif
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Errors */
|
||||
/* ************************************************************************** */
|
||||
/* main enumeration */
|
||||
typedef enum {
|
||||
g1m_noerror,
|
||||
|
||||
/* check errno for more info */
|
||||
g1m_error_errno,
|
||||
/* no stream sent */
|
||||
g1m_error_nostream,
|
||||
/* could not read from stream */
|
||||
g1m_error_noread,
|
||||
/* could not seek in stream */
|
||||
g1m_error_noseek,
|
||||
/* magic or control problem */
|
||||
g1m_error_magic,
|
||||
/* memory allocation problem */
|
||||
g1m_error_alloc,
|
||||
} g1m_error_t;
|
||||
|
||||
/* Message getting macro */
|
||||
extern const char *g1m_error_strings[];
|
||||
#define g1m_strerror(N) g1m_error_strings[N]
|
||||
#define g1m_geterror(N) g1m_error_strings[N]
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main types and functions */
|
||||
/* ************************************************************************** */
|
||||
/* handle */
|
||||
struct g1m;
|
||||
typedef struct g1m g1m_t;
|
||||
|
||||
/* open and close handles */
|
||||
int g1m_open(g1m_t **handle, const char *path);
|
||||
int g1m_fopen(g1m_t **handle, FILE *stream);
|
||||
void g1m_close(g1m_t *handle);
|
||||
|
||||
# ifdef __cplusplus
|
||||
}
|
||||
# endif
|
||||
#endif /* LIBG1M_H */
|
|
@ -0,0 +1,18 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* libg1m/compiler.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/05 13:22:50 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef LIBG1M_COMPILER_H
|
||||
# define LIBG1M_COMPILER_H
|
||||
|
||||
# ifndef __unused
|
||||
# define __unused __attribute__((unused))
|
||||
# endif
|
||||
|
||||
#endif /* LIBG1M_COMPILER_H */
|
|
@ -0,0 +1,30 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* internals.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/03 23:24:04 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef LIBG1M_INTERNALS_H
|
||||
# define LIBG1M_INTERNALS_H
|
||||
# include <libg1m.h>
|
||||
# include <libg1m/internals/log.h>
|
||||
# include <libg1m/internals/format.h>
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Main handle type */
|
||||
/* ************************************************************************** */
|
||||
/* Handle */
|
||||
struct g1m {
|
||||
FILE *stream;
|
||||
};
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Utilities */
|
||||
/* ************************************************************************** */
|
||||
/* Parsing */
|
||||
int g1m_parse(g1m_t *handle);
|
||||
|
||||
#endif /* LIBG1M_INTERNALS_H */
|
|
@ -0,0 +1,155 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* libg1m/internals/format.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/10/30 17:29:42 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#ifndef LIBG1M_INTERNALS_FORMAT_H
|
||||
# define LIBG1M_INTERNALS_FORMAT_H
|
||||
# include <libg1m/compiler.h>
|
||||
# include <stdint.h>
|
||||
|
||||
/* Welcome on this new episode of Monster Circus! Today we'll present to you
|
||||
* something that you might not be able to forget: the G1M format.
|
||||
* This format is used by CASIO on its calculators for storing add-ins
|
||||
* (compiled programs), MCS (main memory) saves, and
|
||||
* e-acts (simple documents). */
|
||||
|
||||
enum g1m_type {
|
||||
g1m_type_addin = 0xF3,
|
||||
g1m_type_mcs = 0x31,
|
||||
g1m_type_eact = 0x49
|
||||
};
|
||||
|
||||
/* It all starts with a header, called Standard Header by Simon Lothar.
|
||||
* This Standard Header contains the total filesize, the G1M type (add-in,
|
||||
* MCS, e-acts), some data that will be useful for the MCS type, and some
|
||||
* magic and control bytes.
|
||||
*
|
||||
* Multi-bytes integers are Big Endian for all of the headers.
|
||||
* The LSB is the Least Significant Byte: once adapted to the host endianness,
|
||||
* it can simply be obtained bitwise-AND-ing with 0xff. */
|
||||
|
||||
struct standard_header {
|
||||
/* the file identifier, should be "USBPower". */
|
||||
uint8_t main_id[8];
|
||||
|
||||
/* our filetype! */
|
||||
uint8_t type;
|
||||
|
||||
/* magic numbers: {0x00, 0x10, 0x00, 0x10, 0x00} */
|
||||
uint8_t magic[5];
|
||||
|
||||
/* first control byte: filesize LSB + 0x41 */
|
||||
uint8_t control;
|
||||
|
||||
/* magic byte: 0x01 */
|
||||
uint8_t magic2;
|
||||
|
||||
/* total filesize */
|
||||
uint32_t filesize;
|
||||
|
||||
/* second control byte: filesize LSB + 0xb8 */
|
||||
uint8_t control2;
|
||||
|
||||
/* 4-bytes alignment */
|
||||
uint8_t align[9] __unused;
|
||||
|
||||
/* number of objects contained (useful for MCS filetype) */
|
||||
uint16_t number;
|
||||
};
|
||||
|
||||
/* After the Standard Header is read and the G1M type is read, we have parts,
|
||||
* each with their own subheaders.
|
||||
*
|
||||
* Let's start with the simplest type: the add-in part. Well, it will always
|
||||
* have one part: the add-in part, with the G1A subheader. */
|
||||
|
||||
struct g1a_subheader {
|
||||
/* the internal name, of format "@APPNAME".
|
||||
* useful for add-ins calling themselves... I guess? */
|
||||
uint8_t internal_name[8];
|
||||
|
||||
/* the number of estrips (I don't know yet) */
|
||||
uint8_t estrips_count;
|
||||
|
||||
/* the add-in version, of format "01.23.4567"
|
||||
* the "01.23" will be displayed in SYSTEM > VERSION */
|
||||
uint8_t version[10];
|
||||
|
||||
/* the add-in creation type, of format "YYYY.MMDD.HHMM" */
|
||||
uint8_t creation_date[14];
|
||||
|
||||
/* 30x17 pixel menu icon bitmap */
|
||||
uint8_t icon[68];
|
||||
|
||||
/* program title */
|
||||
uint8_t title[8];
|
||||
|
||||
/* and the filesize of the part! */
|
||||
uint32_t filesize;
|
||||
};
|
||||
|
||||
/* Then the G1A file will just contain the add-in code and stop.
|
||||
* But hey, that was the easiest G1M type. Let's dive through the feared
|
||||
* type: the MCS one.
|
||||
*
|
||||
* So now we are not restricted to only one part. Remember the `number` field
|
||||
* of the Standard Header? Well, it's the number of parts there is.
|
||||
* And each part have a header, so let's describe it here.
|
||||
*/
|
||||
|
||||
struct mcs_subheader {
|
||||
/* main ID ("PROGRAM", zero padded) */
|
||||
uint8_t intname[16];
|
||||
|
||||
/* subitem count: haha, read what follows! */
|
||||
uint32_t subcount;
|
||||
};
|
||||
|
||||
/* Because yes, an part of an MCS G1M file has subparts!
|
||||
* Each one of them represent a single file in the MCS.
|
||||
* According to their type, they are in different directories: */
|
||||
|
||||
enum mcs_dirtype {
|
||||
mcs_dtype_program = 0x1,
|
||||
mcs_dtype_list = 0x5,
|
||||
mcs_dtype_picture = 0x7,
|
||||
mcs_dtype_capture = 0xa
|
||||
};
|
||||
|
||||
/* And they also have a directory name, which is less precise. Why?
|
||||
* We don't know! That's the main thing with reverse engineering.
|
||||
*
|
||||
* For basic programs, it is: */
|
||||
#define DIRNAME_PROGRAM "system"
|
||||
/* For most alpha-mem elements (list, matrixes, pictures): */
|
||||
#define DIRNAME_ALPHAMEM "main"
|
||||
/* And for captures: */
|
||||
#define DIRNAME_CAPTURE "@REV2"
|
||||
|
||||
/* Now all of this is said, each part has this header: */
|
||||
|
||||
struct mcs_partheader {
|
||||
/* the directory name (zero-padded).*/
|
||||
uint8_t dirname[8];
|
||||
|
||||
/* the file name (item name) */
|
||||
uint8_t filename[8];
|
||||
|
||||
/* the directory type. */
|
||||
uint8_t dirtype;
|
||||
|
||||
/* the size of the part data, without the part header. */
|
||||
uint16_t datalength;
|
||||
|
||||
/* some alignment */
|
||||
uint8_t align[3] __unused;
|
||||
};
|
||||
|
||||
/* And I don't know anything about the E-Act type, sorry. */
|
||||
|
||||
#endif /* LIBG1M_INTERNALS_FORMAT_H */
|
|
@ -0,0 +1,59 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* libg1m/internals/log.h |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/05 12:58:52 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef LIBG1M_INTERNALS_LOG_H
|
||||
# define LIBG1M_INTERNALS_LOG_H
|
||||
|
||||
/* ************************************************************************** */
|
||||
/* Log utility */
|
||||
/* ************************************************************************** */
|
||||
/* Log level */
|
||||
# define ll_info 0
|
||||
# define ll_warn 1
|
||||
# define ll_error 2
|
||||
# define ll_fatal 3
|
||||
# define ll_none 4
|
||||
|
||||
/* Macros */
|
||||
# define log(P, S, ...) fprintf(stderr, P "%s: " S "\n", __FUNCTION__, ##__VA_ARGS__)
|
||||
# define logm(S, M, N) g1m_log_mem(S, M, N)
|
||||
|
||||
# if LOGLEVEL <= ll_info
|
||||
# define log_info(S, ...) log("[libg1m info] ", S, ##__VA_ARGS__)
|
||||
# define logm_info(M, N) logm("[libg1m info] ", M, N)
|
||||
# else
|
||||
# define log_info(S, ...)
|
||||
# define logm_info(M, N)
|
||||
# endif
|
||||
|
||||
# if LOGLEVEL <= ll_warn
|
||||
# define log_warn(S, ...) log("[libg1m warn] ", S, ##__VA_ARGS__)
|
||||
# define logm_warn(M, N) logm("[libg1m warn] ", M, N)
|
||||
# else
|
||||
# define log_warn(S, ...)
|
||||
# define logm_warn(M, N)
|
||||
# endif
|
||||
|
||||
# if LOGLEVEL <= ll_error
|
||||
# define log_error(S, ...) log("[libg1m error] ", S, ##__VA_ARGS__)
|
||||
# else
|
||||
# define log_error(S, ...)
|
||||
# endif
|
||||
|
||||
# if LOGLEVEL <= ll_fatal
|
||||
# define log_fatal(S, ...) log("[libg1m fatal] ", S, ##__VA_ARGS__)
|
||||
# else
|
||||
# define log_fatal(S, ...)
|
||||
# endif
|
||||
|
||||
/* Functions prototypes */
|
||||
void g1m_log_mem(const char *prefix, void *m, size_t n);
|
||||
|
||||
#endif /* LIBG1M_INTERNALS_LOG_H */
|
|
@ -0,0 +1,85 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* handle.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/09/04 00:09:47 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* g1m_fopen:
|
||||
* Open handle using FILE* pointer.
|
||||
*
|
||||
* @arg handle the handle to create
|
||||
* @arg stream the stream
|
||||
* @return the error code (0 if ok)
|
||||
*/
|
||||
|
||||
int g1m_fopen(g1m_t **handle, FILE *stream)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* check stream */
|
||||
if (!stream) return (g1m_error_nostream);
|
||||
if (!__freadable(stream)) return (g1m_error_noread);
|
||||
|
||||
/* seek to beginning */
|
||||
if (fseek(stream, 0L, SEEK_SET)) return (g1m_error_noseek);
|
||||
|
||||
/* create the handle */
|
||||
*handle = malloc(sizeof(g1m_t));
|
||||
if (!*handle) return (g1m_error_alloc);
|
||||
(*handle)->stream = stream;
|
||||
|
||||
/* fill it by parsing opened file */
|
||||
if ((err = g1m_parse(*handle))) {
|
||||
free(*handle);
|
||||
*handle = NULL;
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* everything ok */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_open:
|
||||
* Open handle using path.
|
||||
*
|
||||
* @arg handle the handle to create.
|
||||
* @arg path the path of the file to open.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
int g1m_open(g1m_t **handle, const char *path)
|
||||
{
|
||||
/* open stream */
|
||||
FILE *f = fopen(path, "r+");
|
||||
if (!f) return (g1m_error_errno);
|
||||
|
||||
/* open using `g1m_fopen` */
|
||||
int err;
|
||||
if ((err = g1m_fopen(handle, f)))
|
||||
fclose(f);
|
||||
return (err);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_close:
|
||||
* Close handle using path.
|
||||
*
|
||||
* @arg handle the handle to close.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
void g1m_close(g1m_t *handle)
|
||||
{
|
||||
/* close stream */
|
||||
fclose(handle->stream);
|
||||
free(handle);
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* log.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project : libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/08/19 12:04:33 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#define min(A, B) ((A) < (B) ? (A) : (B))
|
||||
|
||||
/**
|
||||
* putascii:
|
||||
* Put a number in ASCII-hex, in a n-dimensionned field.
|
||||
*
|
||||
* @arg p pointer where to put ASCII number
|
||||
* @arg i ASCII number
|
||||
* @arg n the size of the field
|
||||
*/
|
||||
|
||||
static void putascii(unsigned char *p, unsigned int i, int n)
|
||||
{
|
||||
/* goto end of the field */
|
||||
p += (n - 1);
|
||||
/* for each digit */
|
||||
while (n--) {
|
||||
/* get end digit from this point */
|
||||
int j = i % 16;
|
||||
/* put it in ASCII-hex */
|
||||
*p-- = j >= 10 ? j - 10 + 'A' : j + '0';
|
||||
/* then go to digit that's left */
|
||||
i /= 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log_mem_hex:
|
||||
* Prints the octal interpretation of a max of two octets.
|
||||
*
|
||||
* @arg s the string where to put it
|
||||
* @arg m the memory zone to print
|
||||
* @arg n the size of the memory zone
|
||||
*/
|
||||
|
||||
static void log_mem_hex(char *s, unsigned char *m, size_t n)
|
||||
{
|
||||
size_t l = 0;
|
||||
while (l < 16) {
|
||||
/* put the hex number */
|
||||
if (n) putascii((unsigned char*)s, *m++, 2), s += 2;
|
||||
else *s++ = ' ', *s++ = ' ';
|
||||
|
||||
/* decrement size of the memory zone to go */
|
||||
n -= !!n;
|
||||
|
||||
/* go to next character if s is at the ending of a group */
|
||||
if (l++ % 2) s++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log_mem_asc:
|
||||
* Prints the ascii interpretation of a max of two octets.
|
||||
*
|
||||
* @arg s the string where to put it
|
||||
* @arg m the memory zone to print
|
||||
* @arg n the size of the memory zone
|
||||
*/
|
||||
|
||||
static void log_mem_asc(char *s, unsigned char *m, size_t n)
|
||||
{
|
||||
size_t l = 0;
|
||||
/* for each byte */
|
||||
while (n-- && l++ < 16) {
|
||||
/* put the character (or a dot if non printable) */
|
||||
if (isprint(*m++)) *s++ = *((char*)m - 1);
|
||||
else *s++ = '.';
|
||||
}
|
||||
/* put the line ending */
|
||||
*s++ = '\n', *s = '\0';
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_log_mem:
|
||||
* Print memory zone.
|
||||
*
|
||||
* @arg prefx the line prefix
|
||||
* @arg m the memory zone to print
|
||||
* @arg n the size of the memory zone
|
||||
*/
|
||||
|
||||
void g1m_log_mem(const char *prefx, void *m, size_t n)
|
||||
{
|
||||
/* if nothing, print it directly */
|
||||
if (!n) fprintf(stderr, "%s(nothing)\n", prefx);
|
||||
|
||||
/* prepare line buffer */
|
||||
unsigned int lineoff = strlen(prefx);
|
||||
char linebuf[strlen(prefx) + 58];
|
||||
memcpy(linebuf, prefx, lineoff);
|
||||
/* - for spaces - */
|
||||
memcpy(&linebuf[lineoff], "0000 0000 0000 0000 0000 0000 0000 0000 ", 40);
|
||||
|
||||
/* then loop-loop-loop-loop-loop */
|
||||
unsigned char *p = m;
|
||||
while (n > 0) {
|
||||
/* fill in ascii-hex part */
|
||||
log_mem_hex(&linebuf[lineoff], p, n);
|
||||
/* fill in ascii part */
|
||||
log_mem_asc(&linebuf[lineoff + 40], p, n);
|
||||
/* then print line */
|
||||
fputs(linebuf, stderr);
|
||||
/* and increment pointer */
|
||||
p += 16;
|
||||
n -= min(16, n);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* parse.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/10/30 18:24:25 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
#include <string.h>
|
||||
#include <endian.h>
|
||||
|
||||
/**
|
||||
* g1m_parse_addin:
|
||||
* We have passed the Standard Header and it's a b... add-in! Let's parse it!
|
||||
*
|
||||
* @arg handle the handle.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
static int g1m_parse_addin(g1m_t *handle)
|
||||
{
|
||||
/* get the subheader */
|
||||
struct g1a_subheader hd;
|
||||
size_t rc = fread(&hd, sizeof(struct g1a_subheader), 1, handle->stream);
|
||||
if (rc < sizeof(struct g1a_subheader)) return (g1m_error_magic);
|
||||
|
||||
/* correct subheader endianess */
|
||||
hd.filesize = be32toh(hd.filesize);
|
||||
|
||||
/* no errors */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_parse_mcs:
|
||||
* We have passed the Standard Header and it's a g... MCS! Let's parse it!
|
||||
*
|
||||
* @arg handle the handle.
|
||||
* @arg num number of sizes.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
static int g1m_parse_mcs(g1m_t *handle, uint_fast16_t num)
|
||||
{
|
||||
/* read all of the parts */
|
||||
for (uint_fast16_t i = 0; i < num; i++) {
|
||||
/* get the subheader */
|
||||
struct mcs_subheader hd;
|
||||
size_t rc = fread(&hd, sizeof(struct mcs_subheader), 1, handle->stream);
|
||||
if (rc < sizeof(struct mcs_subheader)) return (g1m_error_magic);
|
||||
|
||||
/* correct endianess */
|
||||
hd.subcount = be32toh(hd.subcount);
|
||||
|
||||
/* foreach subpart */
|
||||
for (uint_fast32_t j = 0; j < num; j++) {
|
||||
/* get the part header */
|
||||
struct mcs_partheader phd;
|
||||
rc = fread(&phd, sizeof(struct mcs_partheader), 1, handle->stream);
|
||||
if (rc < sizeof(struct mcs_partheader)) return (g1m_error_magic);
|
||||
|
||||
/* correct endianess */
|
||||
phd.datalength = be32toh(phd.datalength);
|
||||
|
||||
/* and read that much data */
|
||||
if (fseek(handle->stream, phd.datalength, SEEK_CUR))
|
||||
return (g1m_error_magic);
|
||||
}
|
||||
}
|
||||
|
||||
/* no error */
|
||||
return (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* g1m_parse:
|
||||
* Parse a G1M file.
|
||||
*
|
||||
* Read the standard header, correct endianness, check magic numbers,
|
||||
* then read subparts according to the G1M type.
|
||||
*
|
||||
* @arg handle the handle.
|
||||
* @return the error code (0 if ok).
|
||||
*/
|
||||
|
||||
int g1m_parse(g1m_t *handle)
|
||||
{
|
||||
/* get the standard header */
|
||||
struct standard_header hd;
|
||||
size_t rc = fread(&hd, sizeof(struct standard_header), 1, handle->stream);
|
||||
if (rc < sizeof(struct standard_header)) return (g1m_error_magic);
|
||||
|
||||
/* correct standard header endianess */
|
||||
hd.filesize = be32toh(hd.filesize);
|
||||
hd.number = be16toh(hd.number);
|
||||
|
||||
/* check standard header magics */
|
||||
if (memcmp(hd.magic, (unsigned char[]){0x00, 0x10, 0x00, 0x10, 0x00}, 5))
|
||||
return (g1m_error_magic);
|
||||
if (hd.magic2 != 0x01)
|
||||
return (g1m_error_magic);
|
||||
if (hd.control != ((hd.filesize + 0x41) & 0xff))
|
||||
return (g1m_error_magic);
|
||||
if (hd.control2 != ((hd.filesize + 0xb8) & 0xff))
|
||||
return (g1m_error_magic);
|
||||
|
||||
/* log some data */
|
||||
log_info("Standard header was the following:");
|
||||
logm_info(&hd, sizeof(struct standard_header));
|
||||
log_info("G1M type was '%8s'", hd.main_id);
|
||||
log_info("Type was 0x%02x", hd.type);
|
||||
|
||||
/* subparse. */
|
||||
switch (hd.type) {
|
||||
case g1m_type_addin:
|
||||
return (g1m_parse_addin(handle));
|
||||
case g1m_type_mcs:
|
||||
return (g1m_parse_mcs(handle, hd.number));
|
||||
/* TODO: add g1m_type_eact */
|
||||
default: break;
|
||||
}
|
||||
|
||||
/* no error */
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* strerror.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/10/30 20:05:20 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
#include <libg1m/internals.h>
|
||||
|
||||
/**
|
||||
* g1m_error_strings:
|
||||
* String descriptions of libg1m errors.
|
||||
*
|
||||
* This list MUST evolve whenever the g1m_error_t enumeration
|
||||
* is updated. Could cause invalid error strings otherwise,
|
||||
* or segfaults!
|
||||
*/
|
||||
|
||||
const char *g1m_error_strings[] = {
|
||||
[g1m_noerror] =
|
||||
"no error have been encountered",
|
||||
|
||||
[g1m_error_errno] =
|
||||
"libc error, check errno for more info",
|
||||
[g1m_error_nostream] =
|
||||
"sent stream was NULL",
|
||||
[g1m_error_noread] =
|
||||
"given stream was not readable",
|
||||
[g1m_error_noseek] =
|
||||
"given stream was not seekable",
|
||||
[g1m_error_magic] =
|
||||
"magic/control/size problem",
|
||||
[g1m_error_alloc] =
|
||||
"could not allocate memory",
|
||||
};
|
|
@ -0,0 +1,57 @@
|
|||
/* ************************************************************************** */
|
||||
/* _____ _ */
|
||||
/* version.c |_ _|__ _ _| |__ ___ _ _ */
|
||||
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
||||
/* | | (_) | |_| | | | | __/ |_| | */
|
||||
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
||||
/* Last updated: 2016/10/13 07:33:17 |___/ */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include <libg1m/internals.h>
|
||||
#include <unistd.h>
|
||||
#define Q(x) #x
|
||||
#define QUOTE(x) Q(x)
|
||||
|
||||
/* get loglevel string */
|
||||
#if LOGLEVEL == ll_info
|
||||
# define LLS "info"
|
||||
#elif LOGLEVEL == ll_warn
|
||||
# define LLS "warn"
|
||||
#elif LOGLEVEL == ll_error
|
||||
# define LLS "error"
|
||||
#elif LOGLEVEL == ll_fatal
|
||||
# define LLS "fatal"
|
||||
#elif LOGLEVEL == ll_none
|
||||
# define LLS "none"
|
||||
#else
|
||||
# define LLS "unknown"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* version_message:
|
||||
* The message that should be displayed when the library is executed.
|
||||
*/
|
||||
|
||||
static const char version_message[] =
|
||||
"libg1m v" QUOTE(VERSION) " (licensed under " QUOTE(LICENSE) ")\n"
|
||||
"Made by " QUOTE(AUTHOR) " <" QUOTE(AUTHOR_MAIL) ">.\n"
|
||||
"\n"
|
||||
"Compiled with the '" LLS "' loglevel.\n"
|
||||
"\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or\n"
|
||||
"FITNESS FOR A PARTICULAR PURPOSE.";
|
||||
|
||||
/**
|
||||
* __libg1m_version:
|
||||
* Display version when the library is executed.
|
||||
*/
|
||||
|
||||
extern void __libg1m_version(void)
|
||||
__attribute__((noreturn));
|
||||
void __libg1m_version(void)
|
||||
{
|
||||
puts(version_message);
|
||||
_exit(0);
|
||||
}
|
Reference in New Issue