mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add carray(1).
This commit is contained in:
parent
a7cf2c4b36
commit
7c1306ff7b
6 changed files with 457 additions and 0 deletions
3
Makefile
3
Makefile
|
@ -10,6 +10,7 @@ libm \
|
|||
libpthread \
|
||||
dispd \
|
||||
bench \
|
||||
carray \
|
||||
ext \
|
||||
games \
|
||||
mbr \
|
||||
|
@ -47,11 +48,13 @@ all: sysroot
|
|||
|
||||
.PHONY: build-tools
|
||||
build-tools:
|
||||
$(MAKE) -C carray
|
||||
$(MAKE) -C mkinitrd
|
||||
$(MAKE) -C tix
|
||||
|
||||
.PHONY: install-build-tools
|
||||
install-build-tools:
|
||||
$(MAKE) -C carray install
|
||||
$(MAKE) -C mkinitrd install
|
||||
$(MAKE) -C tix install
|
||||
|
||||
|
|
1
carray/.gitignore
vendored
Normal file
1
carray/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
carray
|
25
carray/Makefile
Normal file
25
carray/Makefile
Normal file
|
@ -0,0 +1,25 @@
|
|||
include ../compiler.mak
|
||||
include ../version.mak
|
||||
include ../dirs.mak
|
||||
|
||||
OPTLEVEL?=$(DEFAULT_OPTLEVEL)
|
||||
CXXFLAGS?=$(OPTLEVEL)
|
||||
|
||||
CPPFLAGS:=$(CPPFLAGS) -DVERSIONSTR=\"$(VERSION)\"
|
||||
CXXFLAGS:=$(CXXFLAGS) -Wall -Wextra -fno-exceptions -fno-rtti
|
||||
|
||||
BINARY:=carray
|
||||
|
||||
all: $(BINARY)
|
||||
|
||||
.PHONY: all install uninstall clean
|
||||
|
||||
install: all
|
||||
mkdir -p $(DESTDIR)$(BINDIR)
|
||||
install $(BINARY) $(DESTDIR)$(BINDIR)
|
||||
|
||||
%: %.c++
|
||||
$(CXX) -std=gnu++11 $(CPPFLAGS) $(CXXFLAGS) $< -o $@
|
||||
|
||||
clean:
|
||||
rm -f $(BINARY) *.o
|
417
carray/carray.c++
Normal file
417
carray/carray.c++
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2014.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
carray.c++
|
||||
Convert a binary file to a C array.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <errno.h>
|
||||
#include <error.h>
|
||||
#include <locale.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if !defined(VERSIONSTR)
|
||||
#define VERSIONSTR "unknown version"
|
||||
#endif
|
||||
|
||||
static void compact_arguments(int* argc, char*** argv)
|
||||
{
|
||||
for ( int i = 0; i < *argc; i++ )
|
||||
{
|
||||
while ( i < *argc && !(*argv)[i] )
|
||||
{
|
||||
for ( int n = i; n < *argc; n++ )
|
||||
(*argv)[n] = (*argv)[n+1];
|
||||
(*argc)--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool get_option_variable(const char* option, char** varptr,
|
||||
const char* arg, int argc, char** argv, int* ip,
|
||||
const char* argv0)
|
||||
{
|
||||
size_t option_len = strlen(option);
|
||||
if ( strncmp(option, arg, option_len) != 0 )
|
||||
return false;
|
||||
if ( arg[option_len] == '=' )
|
||||
{
|
||||
*varptr = strdup(arg + option_len + 1);
|
||||
return true;
|
||||
}
|
||||
if ( arg[option_len] != '\0' )
|
||||
return false;
|
||||
if ( *ip + 1 == argc )
|
||||
{
|
||||
fprintf(stderr, "%s: expected operand after `%s'\n", argv0, option);
|
||||
exit(1);
|
||||
}
|
||||
*varptr = strdup(argv[++*ip]), argv[*ip] = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
#define GET_OPTION_VARIABLE(str, varptr) \
|
||||
get_option_variable(str, varptr, arg, argc, argv, &i, argv0)
|
||||
|
||||
void get_short_option_variable(char c, char** varptr,
|
||||
const char* arg, int argc, char** argv, int* ip,
|
||||
const char* argv0)
|
||||
{
|
||||
free(*varptr);
|
||||
if ( *(arg+1) )
|
||||
{
|
||||
*varptr = strdup(arg + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( *ip + 1 == argc )
|
||||
{
|
||||
error(0, 0, "option requires an argument -- '%c'", c);
|
||||
fprintf(stderr, "Try `%s --help' for more information.\n", argv0);
|
||||
exit(1);
|
||||
}
|
||||
*varptr = strdup(argv[*ip + 1]);
|
||||
argv[++(*ip)] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_SHORT_OPTION_VARIABLE(c, varptr) \
|
||||
get_short_option_variable(c, varptr, arg, argc, argv, &i, argv0)
|
||||
|
||||
static void help(FILE* fp, const char* argv0)
|
||||
{
|
||||
fprintf(fp, "Usage: %s [OPTION]... [INPUT...] -o OUTPUT\n", argv0);
|
||||
fprintf(fp, "Convert a binary file to a C array.\n");
|
||||
fprintf(fp, "\n");
|
||||
fprintf(fp, "Mandatory arguments to long options are mandatory for short options too.\n");
|
||||
fprintf(fp, " -c, --const add const keyword\n");
|
||||
fprintf(fp, " -e, --extern add extern keyword\n");
|
||||
fprintf(fp, " --extern-c use C linkage\n");
|
||||
fprintf(fp, " -f, --forward forward declare rather than define\n");
|
||||
fprintf(fp, " --guard=MACRO use include guard macro MACRO\n");
|
||||
fprintf(fp, " -g, --use-guard add include guard\n");
|
||||
fprintf(fp, " -i, --include include prerequisite headers\n");
|
||||
fprintf(fp, " --identifier=NAME use identifier NAME\n");
|
||||
fprintf(fp, " --includes=INCLUDES emit raw preprocessor INCLUDES\n");
|
||||
fprintf(fp, " -o, --output=FILE write result to FILE\n");
|
||||
fprintf(fp, " -r, --raw emit only raw \n");
|
||||
fprintf(fp, " -s, --static add static keyword\n");
|
||||
fprintf(fp, " --type=TYPE use type TYPE [unsigned char]\n");
|
||||
fprintf(fp, " -v, --volatile add volatile keyword\n");
|
||||
fprintf(fp, " --char use type char\n");
|
||||
fprintf(fp, " --signed-char use type signed char\n");
|
||||
fprintf(fp, " --unsigned-char use type unsigned char\n");
|
||||
fprintf(fp, " --int8_t use type int8_t\n");
|
||||
fprintf(fp, " --uint8_t use type uint8_t\n");
|
||||
fprintf(fp, " --help display this help and exit\n");
|
||||
fprintf(fp, " --version output version information and exit\n");
|
||||
}
|
||||
|
||||
static void version(FILE* fp, const char* argv0)
|
||||
{
|
||||
fprintf(fp, "%s (Sortix) %s\n", argv0, VERSIONSTR);
|
||||
fprintf(fp, "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n");
|
||||
fprintf(fp, "This is free software: you are free to change and redistribute it.\n");
|
||||
fprintf(fp, "There is NO WARRANTY, to the extent permitted by law.\n");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
bool flag_const = false;
|
||||
bool flag_extern_c = false;
|
||||
bool flag_extern = false;
|
||||
bool flag_forward = false;
|
||||
bool flag_guard = false;
|
||||
bool flag_include = false;
|
||||
bool flag_raw = false;
|
||||
bool flag_static = false;
|
||||
bool flag_volatile = false;
|
||||
|
||||
char* arg_guard = NULL;
|
||||
char* arg_identifier = NULL;
|
||||
char* arg_includes = NULL;
|
||||
char* arg_output = NULL;
|
||||
char* arg_type = NULL;
|
||||
|
||||
const char* argv0 = argv[0];
|
||||
for ( int i = 1; i < argc; i++ )
|
||||
{
|
||||
const char* arg = argv[i];
|
||||
if ( arg[0] != '-' || !arg[1] )
|
||||
continue;
|
||||
argv[i] = NULL;
|
||||
if ( !strcmp(arg, "--") )
|
||||
break;
|
||||
if ( arg[1] != '-' )
|
||||
{
|
||||
while ( char c = *++arg ) switch ( c )
|
||||
{
|
||||
case 'c': flag_const = true; break;
|
||||
case 'e': flag_extern = true; break;
|
||||
case 'f': flag_forward = true; break;
|
||||
case 'g': flag_guard = true; break;
|
||||
case 'i': flag_include = true; break;
|
||||
case 'o': GET_SHORT_OPTION_VARIABLE('o', &arg_output); arg = "o"; break;
|
||||
case 'r': flag_raw = true; break;
|
||||
case 's': flag_static = true; break;
|
||||
case 'v': flag_volatile = true; break;
|
||||
default:
|
||||
fprintf(stderr, "%s: unknown option -- '%c'\n", argv0, c);
|
||||
help(stderr, argv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if ( !strcmp(arg, "--help") )
|
||||
help(stdout, argv0), exit(0);
|
||||
else if ( !strcmp(arg, "--version") )
|
||||
version(stdout, argv0), exit(0);
|
||||
else if ( !strcmp(arg, "--const") )
|
||||
flag_const = true;
|
||||
else if ( !strcmp(arg, "--extern") )
|
||||
flag_extern = true;
|
||||
else if ( !strcmp(arg, "--forward") )
|
||||
flag_forward = true;
|
||||
else if ( !strcmp(arg, "--use-guard") )
|
||||
flag_guard = true;
|
||||
else if ( !strcmp(arg, "--include") )
|
||||
flag_include = true;
|
||||
else if ( !strcmp(arg, "--raw") )
|
||||
flag_raw = true;
|
||||
else if ( !strcmp(arg, "--static") )
|
||||
flag_static = true;
|
||||
else if ( !strcmp(arg, "--volatile") )
|
||||
flag_volatile = true;
|
||||
else if ( !strcmp(arg, "--char") )
|
||||
free(arg_type), arg_type = strdup("char");
|
||||
else if ( !strcmp(arg, "--signed-char") )
|
||||
free(arg_type), arg_type = strdup("signed char");
|
||||
else if ( !strcmp(arg, "--unsigned-char") )
|
||||
free(arg_type), arg_type = strdup("unsigned char");
|
||||
else if ( !strcmp(arg, "--int8_t") )
|
||||
free(arg_type), arg_type = strdup("int8_t");
|
||||
else if ( !strcmp(arg, "--uint8_t") )
|
||||
free(arg_type), arg_type = strdup("uint8_t");
|
||||
else if ( GET_OPTION_VARIABLE("--guard", &arg_guard) )
|
||||
flag_guard = true;
|
||||
else if ( GET_OPTION_VARIABLE("--identifier", &arg_identifier) ) { }
|
||||
else if ( GET_OPTION_VARIABLE("--includes", &arg_includes) )
|
||||
flag_include = true;
|
||||
else if ( GET_OPTION_VARIABLE("--output", &arg_output) ) { }
|
||||
else if ( GET_OPTION_VARIABLE("--type", &arg_type) ) { }
|
||||
else if ( !strcmp(arg, "--extern-c") )
|
||||
flag_extern_c = true;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "%s: unknown option: %s\n", argv0, arg);
|
||||
help(stderr, argv0);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
compact_arguments(&argc, &argv);
|
||||
|
||||
const char* output_path = arg_output;
|
||||
|
||||
if ( flag_extern && flag_static )
|
||||
error(1, 0, "the --extern and --static are mutually incompatible");
|
||||
if ( flag_forward && flag_raw )
|
||||
error(1, 0, "the --forward and --raw are mutually incompatible");
|
||||
|
||||
if ( !arg_type )
|
||||
arg_type = strdup("unsigned char");
|
||||
|
||||
char* guard = arg_guard;
|
||||
if ( !guard )
|
||||
{
|
||||
if ( output_path )
|
||||
guard = strdup(output_path);
|
||||
else if ( 2 <= argc && strcmp(argv[1], "-") != 0 )
|
||||
{
|
||||
guard = (char*) malloc(strlen(argv[1]) + 2 + 1);
|
||||
strcpy(guard, argv[1]);
|
||||
strcat(guard, "_H");
|
||||
}
|
||||
else
|
||||
guard = strdup("CARRAY_H");
|
||||
|
||||
for ( size_t i = 0; guard[i]; i++ )
|
||||
{
|
||||
if ( 'A' <= guard[i] && guard[i] <= 'Z' )
|
||||
continue;
|
||||
else if ( 'a' <= guard[i] && guard[i] <= 'z' )
|
||||
guard[i] = 'A' + guard[i] - 'a';
|
||||
else if ( i != 0 && '0' <= guard[i] && guard[i] <= '9' )
|
||||
continue;
|
||||
else if ( guard[i] == '+' )
|
||||
guard[i] = 'X';
|
||||
else if ( i == 0 )
|
||||
guard[i] = 'X';
|
||||
else
|
||||
guard[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
if ( flag_include && !arg_includes )
|
||||
{
|
||||
if ( !strcmp(arg_type, "int8_t") ||
|
||||
!strcmp(arg_type, "uint8_t") )
|
||||
arg_includes = strdup("#include <stdint.h>");
|
||||
}
|
||||
|
||||
char* identifier = arg_identifier;
|
||||
if ( !identifier )
|
||||
{
|
||||
if ( output_path )
|
||||
identifier = strdup(output_path);
|
||||
else if ( 2 <= argc && strcmp(argv[1], "-") != 0 )
|
||||
identifier = strdup(argv[1]);
|
||||
else
|
||||
identifier = strdup("carray");
|
||||
|
||||
for ( size_t i = 0; identifier[i]; i++ )
|
||||
{
|
||||
if ( i && identifier[i] == '.' && !strchr(identifier + i, '/') )
|
||||
identifier[i] = '\0';
|
||||
else if ( 'a' <= identifier[i] && identifier[i] <= 'z' )
|
||||
continue;
|
||||
else if ( 'A' <= identifier[i] && identifier[i] <= 'Z' )
|
||||
identifier[i] = 'a' + identifier[i] - 'A';
|
||||
else if ( i != 0 && '0' <= identifier[i] && identifier[i] <= '9' )
|
||||
continue;
|
||||
else if ( guard[i] == '+' )
|
||||
identifier[i] = 'x';
|
||||
else if ( i == 0 )
|
||||
identifier[i] = 'x';
|
||||
else
|
||||
identifier[i] = '_';
|
||||
}
|
||||
}
|
||||
|
||||
if ( output_path && !freopen(output_path, "w", stdout) )
|
||||
error(1, errno, "%s", output_path);
|
||||
|
||||
if ( flag_guard && guard )
|
||||
{
|
||||
printf("#ifndef %s\n", guard);
|
||||
printf("#define %s\n", guard);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( flag_include && arg_includes )
|
||||
{
|
||||
printf("%s\n", arg_includes);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( !flag_raw )
|
||||
{
|
||||
if ( flag_extern_c )
|
||||
{
|
||||
printf("#if defined(__cplusplus)\n");
|
||||
printf("extern \"C\" {\n");
|
||||
printf("#endif\n");
|
||||
printf("\n");
|
||||
}
|
||||
if ( flag_extern )
|
||||
printf("extern ");
|
||||
if ( flag_static )
|
||||
printf("static ");
|
||||
if ( flag_const )
|
||||
printf("const ");
|
||||
if ( flag_volatile )
|
||||
printf("volatile ");
|
||||
printf("%s %s[]", arg_type, identifier);
|
||||
if ( flag_forward )
|
||||
printf(";\n");
|
||||
else
|
||||
printf(" = {\n");
|
||||
}
|
||||
|
||||
if ( !flag_forward )
|
||||
{
|
||||
bool begun_row = false;
|
||||
unsigned int position = 0;
|
||||
|
||||
for ( int i = 0; i < argc; i++ )
|
||||
{
|
||||
if ( i == 0 && 2 <= argc )
|
||||
continue;
|
||||
FILE* fp;
|
||||
const char* arg;
|
||||
if ( argc == 1 || !strcmp(argv[i], "-") )
|
||||
{
|
||||
arg = "<stdin>";
|
||||
fp = stdin;
|
||||
}
|
||||
else
|
||||
{
|
||||
arg = argv[i];
|
||||
fp = fopen(arg, "r");
|
||||
}
|
||||
if ( !fp )
|
||||
error(1, errno, "%s", arg);
|
||||
int ic;
|
||||
while ( (ic = fgetc(fp)) != EOF )
|
||||
{
|
||||
printf("%c0x%02X,", position++ ? ' ' : '\t', ic);
|
||||
begun_row = true;
|
||||
if ( position == (80 - 8) / 6 )
|
||||
{
|
||||
printf("\n");
|
||||
position = 0;
|
||||
begun_row = false;
|
||||
}
|
||||
}
|
||||
if ( ferror(fp) )
|
||||
error(1, errno, "fgetc: %s", arg);
|
||||
if ( fp != stdin )
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
if ( begun_row )
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
if ( !flag_raw )
|
||||
{
|
||||
if ( !flag_forward )
|
||||
printf("};\n");
|
||||
if ( flag_extern_c )
|
||||
{
|
||||
printf("\n");
|
||||
printf("#if defined(__cplusplus)\n");
|
||||
printf("} /* extern \"C\" */\n");
|
||||
printf("#endif\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ( flag_guard && guard )
|
||||
{
|
||||
printf("\n");
|
||||
printf("#endif\n");
|
||||
}
|
||||
|
||||
if ( ferror(stdout) || fflush(stdout) == EOF )
|
||||
error(1, errno, "%s", output_path ? output_path : "stdout");
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -145,6 +145,7 @@ Sortix comes with a number of home-made programs. Here is an overview:
|
|||
* `benchctxswitch` - useless benchmark
|
||||
* `benchsyscall` - slightly less useless benchmark
|
||||
* `calc` - reverse polish calculator
|
||||
* `carray` - convert a binary file to a C array
|
||||
* `cat` - display file on terminal
|
||||
* `chmod` - change file mode bits
|
||||
* `chroot` - change the root directory
|
||||
|
@ -550,6 +551,14 @@ driver program.
|
|||
make
|
||||
make install
|
||||
|
||||
### Building carray ###
|
||||
|
||||
This program converts a binary file to an C array.
|
||||
|
||||
cd /src/carray
|
||||
make
|
||||
make install
|
||||
|
||||
### Building the Sortix Kernel ###
|
||||
|
||||
The Sortix kernel is the core of the Sortix operating system. It provides all
|
||||
|
|
|
@ -22,6 +22,7 @@ clean:
|
|||
$(MAKE) -B -C $(SRCDIR)/libpthread clean
|
||||
$(MAKE) -B -C $(SRCDIR)/dispd clean
|
||||
$(MAKE) -B -C $(SRCDIR)/bench clean
|
||||
$(MAKE) -B -C $(SRCDIR)/carray clean
|
||||
$(MAKE) -B -C $(SRCDIR)/games clean
|
||||
$(MAKE) -B -C $(SRCDIR)/mkinitrd clean
|
||||
$(MAKE) -B -C $(SRCDIR)/utils clean
|
||||
|
@ -71,6 +72,7 @@ system:
|
|||
$(MAKE) -B -C $(SRCDIR)/libm install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/libpthread install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/dispd install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/bench install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/games install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/mkinitrd install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
$(MAKE) -B -C $(SRCDIR)/utils install DESTDIR=$(ROOT) C_INCLUDE_PATH=$(ROOT)/include CPLUS_INCLUDE_PATH=$(ROOT)/include LIBRARY_PATH=$(ROOT)/$(cputype)/lib
|
||||
|
|
Loading…
Reference in a new issue